You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

验证步骤

  1. 应用所有修正后重新编译烧录
  2. 确认串口工具的波特率与日志配置一致(通常为115200)
  3. 检查MQ-2传感器是否正常供电(5V),引脚连接是否牢固

内容的提问来源于stack exchange,提问作者baor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 09:10:59