下面是我写的代码,你分析一下什么原因#include "adc.h"
#include "./SYSTEM/delay/delay.h"
#include <math.h>
ADC_HandleTypeDef g_adc_handle; /* ADC句柄 */
///* ADC初始化函数,本函数支持ADC1/ADC2任意通道, 但是不支持ADC3 */
//void adc_init(void)
//{
// g_adc_handle.Instance = ADC_ADCX; /* 选择哪个ADC */
// g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; /* 数据对齐方式:右对齐 */
// g_adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE; /* 非扫描模式,仅用到一个通道 */
// g_adc_handle.Init.ContinuousConvMode = DISABLE; /* 关闭连续转换模式 */
// g_adc_handle.Init.NbrOfConversion = 1; /* 赋值范围是1~16,本实验用到1个规则通道序列 */
// g_adc_handle.Init.DiscontinuousConvMode = DISABLE; /* 禁止规则通道组间断模式 */
// g_adc_handle.Init.NbrOfDiscConversion = 0; /* 配置间断模式的规则通道个数,禁止规则通道组间断模式后,此参数忽略 */
// g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* 触发转换方式:软件触发 */
// HAL_ADC_Init(&g_adc_handle); /* 初始化 */
// HAL_ADCEx_Calibration_Start(&g_adc_handle); /* 校准ADC */
//}
///* ADC底层驱动,引脚配置,时钟使能 */
//void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
//{
// if(hadc->Instance == ADC_ADCX)
// {
// GPIO_InitTypeDef gpio_init_struct;
// RCC_PeriphCLKInitTypeDef adc_clk_init = {0};
//
// ADC_ADCX_CHY_CLK_ENABLE(); /* 使能ADCx时钟 */
// ADC_ADCX_CHY_GPIO_CLK_ENABLE(); /* 开启GPIO时钟 */
// /* 设置ADC时钟 */
// adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC; /* ADC外设时钟 */
// adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6; /* 分频因子6时钟为72M/6=12MHz */
// HAL_RCCEx_PeriphCLKConfig(&adc_clk_init); /* 设置ADC时钟 */
// /* 设置AD采集通道对应IO引脚工作模式 */
// gpio_init_struct.Pin = ADC_ADCX_CHY_GPIO_PIN; /* ADC通道IO引脚 */
// gpio_init_struct.Mode = GPIO_MODE_ANALOG; /* 模拟 */
// HAL_GPIO_Init(ADC_ADCX_CHY_GPIO_PORT, &gpio_init_struct);
// }
//}
///**
// * @brief 设置ADC通道采样时间
// * @param adcx : adc句柄指针,ADC_HandleTypeDef
// * @param ch : 通道号, ADC_CHANNEL_0~ADC_CHANNEL_17
// * @param stime: 采样时间 0~7, 对应关系为:
// * @arg ADC_SAMPLETIME_1CYCLE_5, 1.5个ADC时钟周期 ADC_SAMPLETIME_7CYCLES_5, 7.5个ADC时钟周期
// * @arg ADC_SAMPLETIME_13CYCLES_5, 13.5个ADC时钟周期 ADC_SAMPLETIME_28CYCLES_5, 28.5个ADC时钟周期
// * @arg ADC_SAMPLETIME_41CYCLES_5, 41.5个ADC时钟周期 ADC_SAMPLETIME_55CYCLES_5, 55.5个ADC时钟周期
// * @arg ADC_SAMPLETIME_71CYCLES_5, 71.5个ADC时钟周期 ADC_SAMPLETIME_239CYCLES_5, 239.5个ADC时钟周期
// * @param rank: 多通道采集时需要设置的采集编号,
// 假设你定义channle1的rank=1,channle2 的rank=2,
// 那么对应你在DMA缓存空间的变量数组AdcDMA[0] 就i是channle1的转换结果,AdcDMA[1]就是通道2的转换结果。
// 单通道DMA设置为 ADC_REGULAR_RANK_1
// * @arg 编号1~16:ADC_REGULAR_RANK_1~ADC_REGULAR_RANK_16
// * @retval 无
// */
//void adc_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime)
//{
// ADC_ChannelConfTypeDef adc_ch_conf;
//
// adc_ch_conf.Channel = ch; /* 通道 */
// adc_ch_conf.Rank = rank; /* 序列 */
// adc_ch_conf.SamplingTime = stime; /* 采样时间 */
// HAL_ADC_ConfigChannel(adc_handle, &adc_ch_conf); /* 通道配置 */
//}
///**
// * @brief 获得ADC转换后的结果
// * @param ch: 通道值 0~17,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_17
// * @retval 无
// */
//uint32_t adc_get_result(uint32_t ch)
//{
// adc_channel_set(&g_adc_handle , ch, ADC_REGULAR_RANK_1, ADC_SAMPLETIME_239CYCLES_5); /* 设置通道,序列和采样时间 */
// HAL_ADC_Start(&g_adc_handle); /* 开启ADC */
// HAL_ADC_PollForConversion(&g_adc_handle, 20); /* 轮询转换 */
// return (uint16_t)HAL_ADC_GetValue(&g_adc_handle); /* 返回最近一次ADC1规则组的转换结果 */
//}
///**
// * @brief 获取通道ch的转换值,取times次,然后平均
// * @param ch : 通道号, 0~17
// * @param times : 获取次数
// * @retval 通道ch的times次转换结果平均值
// */
//uint32_t adc_get_result_average(uint32_t ch, uint8_t times)
//{
// uint32_t temp_val = 0;
// uint8_t t;
// for (t = 0; t < times; t++) /* 获取times次数据 */
// {
// temp_val += adc_get_result(ch);
// delay_ms(5);
// }
// return temp_val / times; /* 返回平均值 */
//}
/*************************单通道ADC采集(DMA读取)实验和多通道ADC采集(DMA读取)实验公用代码*******************************/
DMA_HandleTypeDef g_dma_adc_handle = {0}; // 定义要搬运ADC数据的DMA句柄
ADC_HandleTypeDef g_adc_dma_handle = {0}; // 定义ADC(DMA读取)句柄
uint8_t g_adc_dma_sta = 0; // DMA传输状态标志, 0,未完成; 1, 已完成
DMA_HandleTypeDef g_dma_nch_adc_handle = {0}; /* 定义要搬运ADC多通道数据的DMA句柄 */
ADC_HandleTypeDef g_adc_nch_dma_handle = {0}; /* 定义ADC(多通道DMA读取)句柄 */
/**
* @brief ADC N通道(6通道) DMA读取 初始化函数
* @note 本函数还是使用adc_init对ADC进行大部分配置,有差异的地方再单独配置
* 另外,由于本函数用到了6个通道, 宏定义会比较多内容, 因此,本函数就不采用宏定义的方式来修改通道了,
* 直接在本函数里面修改, 这里我们默认使用PA0~PA5这6个通道.
*
* 注意: 本函数还是使用 ADC_ADCX(默认=ADC1) 和 ADC_ADCX_DMACx( DMA1_Channel1 ) 及其相关定义
* 不要乱修改adc.h里面的这两部分内容, 必须在理解原理的基础上进行修改, 否则可能导致无法正常使用.
*
* @param mar : 存储器地址
* @retval 无
*/
void adc_nch_dma_init(uint32_t mar)
{
GPIO_InitTypeDef gpio_init_struct;
RCC_PeriphCLKInitTypeDef adc_clk_init = {0};
ADC_ChannelConfTypeDef adc_ch_conf = {0};
ADC_ADCX_CHY_CLK_ENABLE(); /* 使能ADCx时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 开启GPIOA时钟 */
if ((uint32_t)ADC_ADCX_DMACx > (uint32_t)DMA1_Channel7) /* 大于DMA1_Channel7, 则为DMA2的通道了 */
{
__HAL_RCC_DMA2_CLK_ENABLE(); /* DMA2时钟使能 */
}
else
{
__HAL_RCC_DMA1_CLK_ENABLE(); /* DMA1时钟使能 */
}
/* 设置ADC时钟 */
adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC; /* ADC外设时钟 */
adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6; /* 分频因子6时钟为72M/6=12MHz */
HAL_RCCEx_PeriphCLKConfig(&adc_clk_init); /* 设置ADC时钟 */
/*
设置ADC1通道0~5对应的IO口模拟输入
AD采集引脚模式设置,模拟输入
PA1对应 ADC1_IN1
PA2对应 ADC1_IN2
PA3对应 ADC1_IN3
*/
gpio_init_struct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3; /* GPIOA1-3 */
gpio_init_struct.Mode = GPIO_MODE_ANALOG; /* 模拟 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
/* 初始化DMA */
g_dma_nch_adc_handle.Instance = ADC_ADCX_DMACx; /* 设置DMA通道 */
g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; /* 从外设到存储器模式 */
g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设非增量模式 */
g_dma_nch_adc_handle.Init.MemInc = DMA_MINC_ENABLE; /* 存储器增量模式 */
g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* 外设数据长度:16位 */
g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; /* 存储器数据长度:16位 */
g_dma_nch_adc_handle.Init.Mode = DMA_NORMAL; /* 外设流控模式 */
g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM; /* 中等优先级 */
HAL_DMA_Init(&g_dma_nch_adc_handle);
__HAL_LINKDMA(&g_adc_nch_dma_handle, DMA_Handle, g_dma_nch_adc_handle); /* 将DMA与adc联系起来 */
/* 初始化ADC */
g_adc_nch_dma_handle.Instance = ADC_ADCX; /* 选择哪个ADC */
g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; /* 数据对齐方式:右对齐 */
g_adc_nch_dma_handle.Init.ScanConvMode = ADC_SCAN_ENABLE; /* 使能扫描模式 */
g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE; /* 使能连续转换 */
g_adc_nch_dma_handle.Init.NbrOfConversion = 3; /* 赋值范围是1~16,本实验用到3个规则通道序列 */
g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE; /* 禁止规则通道组间断模式 */
g_adc_nch_dma_handle.Init.NbrOfDiscConversion = 0; /* 配置间断模式的规则通道个数,禁止规则通道组间断模式后,此参数忽略 */
g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* 软件触发 */
HAL_ADC_Init(&g_adc_nch_dma_handle); /* 初始化 */
HAL_ADCEx_Calibration_Start(&g_adc_nch_dma_handle); /* 校准ADC */
/* 配置ADC通道 */
adc_ch_conf.Channel = ADC_CHANNEL_1; /* 配置使用的ADC通道 */
adc_ch_conf.Rank = ADC_REGULAR_RANK_1; /* 采样序列里的第1个 */
adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5 ; /* 采样时间,设置最大采样周期:239.5个ADC周期 */
HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf); /* 通道配置 */
adc_ch_conf.Channel = ADC_CHANNEL_2; /* 配置使用的ADC通道 */
adc_ch_conf.Rank = ADC_REGULAR_RANK_2; /* 采样序列里的第2个 */
adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5 ; /* 采样时间,设置最大采样周期:239.5个ADC周期 */
HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf); /* 配置ADC通道 */
adc_ch_conf.Channel = ADC_CHANNEL_3; /* 配置使用的ADC通道 */
adc_ch_conf.Rank = ADC_REGULAR_RANK_3; /* 采样序列里的第3个 */
adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5 ; /* 采样时间,设置最大采样周期:239.5个ADC周期 */
HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf); /* 配置ADC通道 */
/* 配置DMA数据流请求中断优先级 */
HAL_NVIC_SetPriority(ADC_ADCX_DMACx_IRQn, 3, 3);
HAL_NVIC_EnableIRQ(ADC_ADCX_DMACx_IRQn);
HAL_DMA_Start_IT(&g_dma_nch_adc_handle, (uint32_t)&ADC1->DR, mar, 0); /* 启动DMA,并开启中断 */
HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar, 0); /* 开启ADC,通过DMA传输结果 */
}
/*************************单通道ADC采集(DMA读取)实验和多通道ADC采集(DMA读取)实验公用代码*******************************/
/**
* @brief 使能一次ADC DMA传输
* @note 该函数用寄存器来操作,防止用HAL库操作对其他参数有修改,也为了兼容性
* @param ndtr: DMA传输的次数
* @retval 无
*/
void adc_dma_enable(uint16_t cndtr)
{
ADC_ADCX->CR2 &= ~(1 << 0); /* 先关闭ADC */
ADC_ADCX_DMACx->CCR &= ~(1 << 0); /* 关闭DMA传输 */
while (ADC_ADCX_DMACx->CCR & (1 << 0)); /* 确保DMA可以被设置 */
ADC_ADCX_DMACx->CNDTR = cndtr; /* DMA传输数据量 */
ADC_ADCX_DMACx->CCR |= 1 << 0; /* 开启DMA传输 */
ADC_ADCX->CR2 |= 1 << 0; /* 重新启动ADC */
ADC_ADCX->CR2 |= 1 << 22; /* 启动规则转换通道 */
}
/**
* @brief ADC DMA采集中断服务函数
* @param 无
* @retval 无
*/
void ADC_ADCX_DMACx_IRQHandler(void)
{
if (ADC_ADCX_DMACx_IS_TC())
{
g_adc_dma_sta = 1; /* 标记DMA传输完成 */
ADC_ADCX_DMACx_CLR_TC(); /* 清除DMA1 数据流7 传输完成中断 */
}
},main.c代码#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/DMA/dma.h"
#include "./BSP/KEY/key.h"
#include "./BSP/ADC/adc.h"
#include "OLED.h"
// 重新排序全局变量定义,确保阈值变量在ADC缓冲区之前
volatile float MQ7_ALARM_THRESHOLD = 7.0; // 添加volatile防止优化
volatile float MQ8_ALARM_THRESHOLD = 20.0;
volatile float MP2_ALARM_THRESHOLD = 15.0;
// 添加全局变量存储基线值
float baseline_values[3] = {0};
extern const uint8_t HZ_zhong[];
// 添加内存保护屏障
#define ADC_DMA_BUF_SIZE (3 * 50) /* ADC DMA缓冲区大小 */
uint32_t __attribute__((aligned(4))) memory_barrier[4]; // 内存屏障
static uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE]; /* ADC DMA缓冲区 */
extern uint8_t g_adc_dma_sta; /* DMA传输完成标志 */
// 汉字点阵数据
const uint8_t HZ_guo[] =
{
0x00,0xFE,0xFE,0x12,0x92,0x92,0x92,0xF2,
0xF2,0x92,0x92,0x92,0x12,0xFE,0xFE,0x00,
0x00,0xFF,0xFF,0x48,0x48,0x48,0x48,0x4F,
0x4F,0x4A,0x4E,0x4C,0x48,0xFF,0xFF,0x00
};
const uint8_t HZ_nan[] =
{
0x04,0xE4,0xE4,0x24,
0x64,0xE4,0xA4,0x3F,
0x3F,0xA4,0xE4,0x64,
0x24,0xE4,0xE4,0x04,
0x00,0xFF,0xFF,0x08,
0x09,0x09,0x09,0x7F,
0x7F,0x09,0x09,0x49,
0xC8,0xFF,0x7F,0x00,/*"南",0*/
};
const uint8_t HZ_fang[] =
{
0x08,0x08,0x08,0x08,
0x08,0xF8,0xF9,0x8F,
0x8E,0x88,0x88,0x88,
0x88,0x08,0x08,0x08,
0x00,0x80,0xC0,0x60,
0x38,0x1F,0x07,0x00,
0x40,0xC0,0xC0,0x7F,
0x3F,0x00,0x00,0x00,/*"方",0*/
};
const uint8_t HZ_dian[] =
{
0x00,0x00,0xF8,0xF8,
0x88,0x88,0x88,0xFF,
0xFF,0x88,0x88,0x88,
0xF8,0xF8,0x00,0x00,
0x00,0x00,0x1F,0x1F,
0x08,0x08,0x08,0x7F,
0xFF,0x88,0x88,0x88,
0x9F,0x9F,0xF0,0xF0,/*"电",0*/
};
const uint8_t HZ_wang[] =
{
0x00,0xFE,0xFE,0x22,
0x62,0xC2,0xF2,0x72,
0x22,0x62,0xC2,0xF2,
0x72,0xFE,0xFE,0x00,
0x00,0xFF,0xFF,0x18,
0x0E,0x07,0x0F,0x1E,
0x18,0x0E,0x07,0x4F,
0xCE,0xFF,0x7F,0x00,/*"网",0*/
};
////////////////////////////////////// 按键处理优化 ///////////////////////////////////
int selected_sensor = 0; // 当前选择的传感器
// 按键状态结构体
typedef struct {
uint32_t last_time; // 上次检测时间
uint8_t last_state; // 上次状态
uint8_t pressed; // 按下标志
} KeyState;
KeyState xz_key = {0, 1, 0};
KeyState key0_key = {0, 1, 0};
KeyState key1_key = {0, 1, 0};
// 更新阈值函数(带范围限制)
void update_threshold(float delta)
{
switch (selected_sensor) {
case 0:
MQ7_ALARM_THRESHOLD += delta;
if (MQ7_ALARM_THRESHOLD < 0) MQ7_ALARM_THRESHOLD = 0;
if (MQ7_ALARM_THRESHOLD > 100) MQ7_ALARM_THRESHOLD = 100;
break;
case 1:
MQ8_ALARM_THRESHOLD += delta;
if (MQ8_ALARM_THRESHOLD < 0) MQ8_ALARM_THRESHOLD = 0;
if (MQ8_ALARM_THRESHOLD > 100) MQ8_ALARM_THRESHOLD = 100;
break;
case 2:
MP2_ALARM_THRESHOLD += delta;
if (MP2_ALARM_THRESHOLD < 0) MP2_ALARM_THRESHOLD = 0;
if (MP2_ALARM_THRESHOLD > 100) MP2_ALARM_THRESHOLD = 100;
break;
}
}
// 更新按键状态
void update_key_state(KeyState *key, GPIO_PinState current_state)
{
uint32_t now = HAL_GetTick();
uint8_t current_pin_state = (current_state == GPIO_PIN_SET) ? 1 : 0;
// 检测下降沿(按键按下)
if (key->last_state == 1 && current_pin_state == 0) {
if ((now - key->last_time) > 20) { // 20ms消抖
key->pressed = 1;
}
}
// 更新状态
key->last_state = current_pin_state;
key->last_time = now;
}
// 处理按键逻辑
void process_keys(void)
{
// 更新按键状态
update_key_state(&xz_key, HAL_GPIO_ReadPin(XZ_GPIO_PORT, XZ_GPIO_PIN));
update_key_state(&key0_key, HAL_GPIO_ReadPin(KEY0_GPIO_PORT, KEY0_GPIO_PIN));
update_key_state(&key1_key, HAL_GPIO_ReadPin(KEY1_GPIO_PORT, KEY1_GPIO_PIN));
// 处理XZ按键(选择传感器)
if (xz_key.pressed) {
selected_sensor = (selected_sensor + 1) % 3;
xz_key.pressed = 0;
}
// 处理KEY0按键(增加阈值)
if (key0_key.pressed) {
update_threshold(1.0f);
key0_key.pressed = 0;
}
// 处理KEY1按键(减少阈值)
if (key1_key.pressed) {
update_threshold(-1.0f);
key1_key.pressed = 0;
}
}
///////////////////////////////////////////////////////////////////////////////////
// 显示电压值(清除残留字符)
void display_voltage_value(uint8_t x, uint8_t y, float voltage)
{
char buffer[10];
// 清除旧内容(5位宽度,包括小数点和两位小数)
OLED_ShowString(x, y, " ", 8);
// 显示新值
snprintf(buffer, sizeof(buffer), "%.0f", voltage);
OLED_ShowString(x, y, buffer, 8);
}
// 显示阈值值(清除残留字符)
void display_threshold_value(uint8_t x, uint8_t y, float threshold)
{
char buffer[10];
// 清除旧内容(4位宽度,包括小数点和一位小数)
OLED_ShowString(x, y, " ", 8);
// 显示新值
snprintf(buffer, sizeof(buffer), "%.1f", threshold);
OLED_ShowString(x, y, buffer, 8);
}
int main(void)
{
// float mq7_concentration, mq8_concentration, mp2_concentration;
HAL_Init();
sys_stm32_clock_init(RCC_PLL_MUL9);
delay_init(72);
usart_init(115200);
led_init();
key_init();
OLED_Init();
OLED_Clear();
// 开机动画
OLED_ShowChinese(2, 16, HZ_zhong);
OLED_ShowChinese(21, 16, HZ_guo);
OLED_ShowChinese(40, 16, HZ_nan);
OLED_ShowChinese(59, 16, HZ_fang);
OLED_ShowChinese(78, 16, HZ_dian);
OLED_ShowChinese(97, 16, HZ_wang);
OLED_UpData();
delay_ms(1000);
OLED_Clear();
// 添加变量用于存储每个通道的ADC值和电压
uint16_t adc_value[3] = {0};
float voltage[3] = {0.0f};
// 初始化ADC DMA
adc_nch_dma_init((uint32_t)g_adc_dma_buf);
adc_dma_enable(ADC_DMA_BUF_SIZE);
// 显示初始静态文本
OLED_ShowString(1, 1, "CO:", 8);
OLED_ShowString(1, 16, "CO2:", 8);
OLED_ShowString(1, 32, "CH4:", 8);
// 初始显示阈值(使用清除残留字符的函数)
display_threshold_value(90, 1, MQ7_ALARM_THRESHOLD);
display_threshold_value(90, 16, MQ8_ALARM_THRESHOLD);
display_threshold_value(90, 32, MP2_ALARM_THRESHOLD);
// 初始选择标记
selected_sensor = 0;
OLED_ShowString(80, 1, "*", 8); // 初始选择第一个传感器
OLED_UpData();
delay_ms(100);
while (1)
{
// 处理按键
process_keys();
// 更新选择标记 - 先清除所有标记
OLED_ShowString(80, 1, " ", 8);
OLED_ShowString(80, 16, " ", 8);
OLED_ShowString(80, 32, " ", 8);
// 设置当前选中标记
switch (selected_sensor) {
case 0: OLED_ShowString(80, 1, "*", 8); break;
case 1: OLED_ShowString(80, 16, "*", 8); break;
case 2: OLED_ShowString(80, 32, "*", 8); break;
}
if (g_adc_dma_sta == 1)
{
// 处理DMA缓冲区数据
for (uint8_t j = 0; j < 3; j++)
{
uint32_t sum = 0;
// 计算该通道的平均值
for (uint16_t i = 0; i < (ADC_DMA_BUF_SIZE / 3); i++)
{
sum += g_adc_dma_buf[(3 * i) + j];
}
// 存储平均值
adc_value[j] = sum / (ADC_DMA_BUF_SIZE / 3);
switch(j)
{
case 0:
display_voltage_value(35, 1, adc_value[0] );
break;
case 1:
display_voltage_value(35, 16, adc_value[1] );
break;
case 2:
display_voltage_value(35, 32, adc_value[2] );
break;
}
}
display_threshold_value(90, 1, MQ7_ALARM_THRESHOLD);
display_threshold_value(90, 16, MQ8_ALARM_THRESHOLD);
display_threshold_value(90, 32, MP2_ALARM_THRESHOLD);
g_adc_dma_sta = 0;
adc_dma_enable(ADC_DMA_BUF_SIZE);
}
LED0_TOGGLE();
OLED_UpData();
delay_ms(10);
}
},用的是STM32F103的M48Z-M3的单片机开发板,出现了使用多通道ADC采集时给ADC采集引脚接上气体传感器后其数值变化浮动很大的情况,并且气体传感器在检测到对应气体时依旧我行我素地在那波动,而不是检测到气体后数值升高