BGM220P开发板IADC读取MQ-2传感器无串口输出问题
解决BGM220使用IADC读取MQ-2传感器无串口输出问题
问题背景
基于Silicon Labs官方IADC单中断示例开发代码,尝试用IADC读取MQ-2气体传感器数据,编译烧录到BGM220PC22HNA开发板(Simplicity Studio + Gecko 4.4.3 SDK)后,串口无任何输出。硬件连接为:
- MQ-2的A0引脚 → BGM220的B0引脚
- MQ-2的GND → 开发板GND
- MQ-2的VCC → 5V电源
原始代码
#include <stdio.h> #include "em_device.h" #include "em_chip.h" #include "em_core.h" #include "em_cmu.h" #include "em_emu.h" #include "em_iadc.h" #include "em_gpio.h" #include "app_log.h" #define CLK_SRC_ADC_FREQ 10000000 #define CLK_ADC_FREQ 10000000 #define IADC_INPUT_0_PORT_PIN iadcPosInputPortBPin0 #define IADC_INPUT_0_BUS BBUSALLOC #define IADC_INPUT_0_BUSALLOC GPIO_BBUSALLOC_BEVEN0_ADC0 #define EM2DEBUG 1 static volatile IADC_Result_t sample; static volatile float singleResult; void initIADC(void) { IADC_Init_t init = IADC_INIT_DEFAULT; IADC_AllConfigs_t initAllConfigs = IADC_ALLCONFIGS_DEFAULT; IADC_InitSingle_t initSingle = IADC_INITSINGLE_DEFAULT; IADC_SingleInput_t initSingleInput = IADC_SINGLEINPUT_DEFAULT; CMU_ClockEnable(cmuClock_IADC0, true); CMU_ClockEnable(cmuClock_GPIO, true); IADC_reset(IADC0); CMU_ClockSelectSet(cmuClock_IADCCLK, cmuSelect_FSRCO); // FSRCO - 20MHz init.warmup = iadcWarmupKeepWarm; init.srcClkPrescale = IADC_calcSrcClkPrescale(IADC0, CLK_SRC_ADC_FREQ, 0); initAllConfigs.configs[0].reference = iadcCfgReferenceVddx; initAllConfigs.configs[0].vRef = 5000; initAllConfigs.configs[0].adcClkPrescale = IADC_calcAdcClkPrescale(IADC0, CLK_ADC_FREQ, 0, iadcCfgModeNormal, init.srcClkPrescale); initSingleInput.posInput = IADC_INPUT_0_PORT_PIN; initSingleInput.negInput = iadcNegInputGnd; GPIO->BBUSALLOC |= GPIO_BBUSALLOC_BEVEN0_ADC0; IADC_init(IADC0, &init, &initAllConfigs); IADC_initSingle(IADC0, &initSingle, &initSingleInput); IADC_clearInt(IADC0, _IADC_IF_MASK); IADC_enableInt(IADC0, IADC_IEN_SINGLEDONE); NVIC_ClearPendingIRQ(IADC_IRQn); NVIC_EnableIRQ(IADC_IRQn); } void IADC_IRQHandler(void) { uint32_t flags = IADC_getInt(IADC0); sample = IADC_pullSingleFifoResult(IADC0); singleResult = (sample.data * 5.0) / 0xFFF; app_log("data: %.2f V\n", singleResult); IADC_clearInt(IADC0, flags); } int main(void) { CHIP_Init(); initIADC(); #ifdef EM2DEBUG EMU->CTRL_SET = EMU_CTRL_EM2DBGEN; #endif while (1) { IADC_command(IADC0, iadcCmdStartSingle); IADC_IRQHandler(); CORE_DECLARE_IRQ_STATE; CORE_ENTER_CRITICAL(); EMU_EnterEM2(true); CORE_EXIT_CRITICAL(); } }
问题分析与修正方案
1. 错误调用中断处理函数
main循环中直接调用IADC_IRQHandler()会跳过硬件中断触发逻辑,此时ADC尚未完成转换,读取的FIFO数据无效,同时破坏了中断的正常工作流程。必须移除该主动调用,由硬件中断自动触发执行。
2. 缺失日志/串口初始化
app_log依赖SDK的日志模块(通常基于UART或VCOM),未初始化的话无法输出任何内容。需要在main函数开头添加日志初始化:
app_log_init();
同时需确保Simplicity Studio中已配置好对应的串口外设(比如VCOM),并在工程设置中启用日志功能。
3. ADC参考电压配置错误
BGM220的VDDx最大为3.3V,代码中设置vRef = 5000(5V)与实际硬件不符,会导致采样值计算错误。修正为:
initAllConfigs.configs[0].vRef = 3300;
同时采样值的计算也需对应调整:
singleResult = (sample.data * 3.3) / 0xFFF;
4. 低功耗进入时机不当
启动ADC转换后立即进入EM2,可能导致ADC转换未完成就进入低功耗状态,中断无法触发。调整main循环逻辑,等待ADC转换完成后再进入低功耗:
修正后的main循环:
int main(void) { CHIP_Init(); app_log_init(); // 添加日志初始化 initIADC(); #ifdef EM2DEBUG EMU->CTRL_SET = EMU_CTRL_EM2DBGEN; #endif while (1) { IADC_command(IADC0, iadcCmdStartSingle); // 进入EM2等待中断唤醒 CORE_DECLARE_IRQ_STATE; CORE_ENTER_CRITICAL(); EMU_EnterEM2(true); CORE_EXIT_CRITICAL(); } }
5. 可选:添加GPIO引脚配置
尽管IADC初始化会复用引脚,但显式配置引脚为输入模式可避免意外,在initIADC函数中添加:
GPIO_PinModeSet(gpioPortB, 0, gpioModeInput, 0);
验证步骤
- 应用所有修正后重新编译烧录
- 确认串口工具的波特率与日志配置一致(通常为115200)
- 检查MQ-2传感器是否正常供电(5V),引脚连接是否牢固
内容的提问来源于stack exchange,提问作者baor
相关产品推荐
相关产品推荐

