STM32CubeMX使用(四)之DMA方式使用ADC、ADC使用遇到的问题

本文详述了在STM32G0B1RCT6芯片上使用ADC和DMA进行数据采集的过程,包括配置端口、开启DMA中断、测试ADC以及遇到的两个问题:通道间干扰和无输入电压时的非零读数。作者通过调整代码和增加独立的ADC数据获取函数解决了这些问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

本文记录下ADC的使用过程,主要是后续使用,能有个参考。同样,以后遇到的ADC问题,也都收录在本文后面。
芯片: STM32G0B1RCT6

二、Pinout&Configuration

2.1 选择端口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 开启DMA中断

在这里插入图片描述

三、测试ADC

测试代码可参考demo工程,同样是DMA方式:
在这里插入图片描述
主要步骤为:

  1. 定义采集值缓存
    在这里插入图片描述
  2. 开启ADC校准在这里插入图片描述
  3. 开启DMA功能*。在这里插入图片描述
  4. 主循环内重复开启ADC转换并打印采集结果:在这里插入图片描述
  5. 发现打印结果如下,每次只转换了一个通道:
    在这里插入图片描述
    开启ADC后1S还不够采集完成吗?
  6. 回到demo中查看,是在回调函数中设置标志,然后在主循环中判断标志才进行打印。
    在这里插入图片描述
    修改后果然正常了:
    在这里插入图片描述
    这样看来每次开启ADC,只转换了一个通道。CubeMX设置有些问题。使能了scan扫描模式,应该会转换完所有通道吧?回头再看下。

注意:HAL_ADC_Start_DMA后,不要使用立即调用HAL_ADC_Start。

2021-12-9补充:

  1. 前面混合使用了HAL_ADC_Start_DMA和HAL_ADC_Start,是有些问题的。可以只使用HAL_ADC_Start_DMA,但要注意,不能重复调用,每次转换完要先使用HAL_ADC_Stop_DMA关闭。

  2. 修改cube设置
    在这里插入图片描述
    转换完所有通道后关闭ADC。

四、遇到的问题

4.1 采集到其他通道的值

使用N32G031C8开发板,采集channel1和channel8两路ADC。发现只给channel1输入2V电压,channel8采集值也随之改变。两次采集之间也增加了500ms延时,是什么原因呢?
暂时没有细究。开发板只是把IO直接引出来方便测试,并没有包含外围分压电路。在channel8也输入一路电压,可以看到channel1和channel8都能够正常采集了。

继续4.1的问题

硬件做好后测试,采集channel1、channel8、channel7三路电压,发现仍然存在问题:
在这里插入图片描述
正常情况下,只有ADU路是有电压的,但有时ADU会采集到0,或者HW_VER路采集到ADU的电压值。测试了多通道采集和连续转换,发现都不是问题的原因。开发板例程的ADC采集了浪路,参考设置是一样的,仍然有问题。最终发现,增加一个ADC_GetData函数,就可以了。

static uint16_t ADC_GetData(uint8_t ADC_Channel)
{
    uint16_t dat;
    
    ADC_ConfigRegularChannel(ADC1, ADC_Channel, 1, ADC_SAMP_TIME_56CYCLES5);
    /* Start ADC Software Conversion */
    ADC_EnableSoftwareStartConv(ADC1, ENABLE);
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ENDC)==0){
    }
    ADC_ClearFlag(ADC1, ADC_FLAG_ENDC);
    ADC_ClearFlag(ADC1, ADC_FLAG_STR);
    dat = ADC_GetDat(ADC1);
    
    return dat;
}


#if USE_ADC1
static int32_t n32_adc1_read(uint8_t channel)
{
    int32_t read_value = 0;
    uint16_t dat;
    
//    ADC_ConfigRegularChannel(ADC1, channel, 1, ADC_SAMP_TIME_56CYCLES5);
//    /* Start ADC Software Conversion */
//    ADC_EnableSoftwareStartConv(ADC1, ENABLE);
//    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ENDC)==0){
//    }
//    ADC_ClearFlag(ADC1, ADC_FLAG_ENDC);
//    ADC_ClearFlag(ADC1, ADC_FLAG_STR);
//    
    read_value = ADC_GetDat(ADC1);
//    dat = ADC_GetDat(ADC1);
//    read_value = dat;
    
    read_value = ADC_GetData(channel);

    return read_value;
}
#endif

为什么单独封装一个函数,效果就不一样了呢?暂时没搞明白

4.2 STM32 ADC没有输入电压时,采集结果不为0

单独写为一篇:添加链接描述

### STM32 CubeMX 单通道 ADC 配置教程 在使用 STM32CubeMX 进行单通道 ADC 的配置时,可以按照以下方法完成设置。以下是详细的说明: #### 1. 创建工程并选择设备 启动 STM32CubeMX 并新建一个项目,在此过程中选择目标 MCU 型号(如 STM32F446VE),然后初始化引脚布局。 #### 2. 启用 ADC 功能模块 进入 **Pinout & Configuration** 页面,找到 **Analog** 类别的外设列表,启用 ADC 模块。对于单通道采样,通常只需要配置一个 ADC 实例即可[^2]。 #### 3. 设置时钟源与时基 转到 RCC (Reset and Clock Control) 参数页面调整系统总线频率以及 ADC 所需的工作时钟树结构。确保所选的 APB 总线速度满足 ADC 转换速率需求[^1]。 #### 4. 定义输入信道 回到 ADC 初始化界面下拉菜单选项里指定要使用的模拟输入端口作为第一个也是唯一的一个测量路径。例如 PA0 或者其他 GPIO 引脚被映射成对应的功能角色之后才能参与实际的数据获取过程。 #### 5. 编辑高级控制属性 继续深入探索 Advanced Settings 下面提供更多定制化可能性的地方比如分辨率模式(Single-ended/Differential), 对齐方式(Left/Right justified data format),扫描方向等等细节都可根据具体应用场景灵活变动。 #### 6. 波特率及其他通信接口无关设定项忽略不计因为这里讨论单纯针对内部模数变换器操作流程本身而不涉及外部串行传输机制部分所以无需特别关注这部分内容. #### 7. 生成代码框架 当上述硬件层面准备工作完成后点击 GENERATE CODE 将会自动生成基于 HAL 库或者 LL API 形式的驱动程序样板文件供后续开发人员进一步完善逻辑实现功能。 ```c // 示例:HAL库中的ADC单次转换函数调用 HAL_ADC_Start(&hadc1); if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK){ uint16_t adcValue = HAL_ADC_GetValue(&hadc1); } ``` 以上即为通过STM32CubeMX工具快速搭建起支持单一信号采集环境所需经历的主要环节概述。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值