• STM32基于HAL库的非DMA的轮询ADC单通道与多通道的采样


    目录

    单通道(连续转换模式)

    单通道(单次转换模式) 

    非DMA的多通道采样


    单通道(连续转换模式)

    扫描模式失能,间断模式失能,连续转换模式使能

    规则模式使能

     

    对于F1系列的芯片

    HAL_ADCEx_Calibration_Start(&hadc1);    //AD校准

    F4则不需要,已经自动进行了校准

    在while前只需启动一次ADC

     HAL_ADC_Start(&hadc1);     //启动ADC转换

    定时读取adc

    1. if(adct>1000){
    2. adct=0;
    3. HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50为最大等待时间,单位为ms
    4. if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
    5. {
    6. adcval[0] = HAL_ADC_GetValue(&hadc1); //获取AD值
    7. printf("ADC1 Reading : %d \r\n",adcval[0]);
    8. printf("PA1 True Voltage value : %.4f \r\n",adcval[0]*3.3f/4096);
    9. }
    10. }

     串口读取

    [2022-07-20_18:10:59:740]ADC1 Reading : 2017 
    [2022-07-20_18:10:59:740]PA1 True Voltage value : 1.6250 

     

    单通道(单次转换模式) 

    而单次转换每次转换都要启动adc

    1. HAL_ADC_Start(&hadc1); //启动ADC转换
    2. HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50为最大等待时间,单位为ms

    非DMA的多通道采样

    这个问题困扰了我很久,轮询模式(单次加间断)我也试过了,多通道测试的时候数据不准,比如两个通道的引脚外接0或3.3v的电压,要么就都是0要么就都是3.3

    但经过测试又读出来不一样两个通道的电压值又不一样

     

    参考

    stm32cubeMX配置ADC多通道采集(非dma和中断方式)_Error-500的博客-CSDN博客_stm32扫描多通道采集

    对比cubeMX依据hal库生成的adc初始化代码

    只要在cubeMX里配置多通道,那么多通道就给你使能了。

    另外还有这两句

    1. sConfig.Channel = ADC_CHANNEL_5;
    2. sConfig.Rank = ADC_REGULAR_RANK_1;
    3. sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
    4. if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
    5. {
    6. Error_Handler();
    7. }
    8. /** Configure Regular Channel
    9. */
    10. sConfig.Channel = ADC_CHANNEL_1;
    11. sConfig.Rank = ADC_REGULAR_RANK_2;
    12. if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
    13. {
    14. Error_Handler();
    15. }

    这样配置明显后者设置的通道覆盖了前者,属于冗余的代码。

    这是通道配置的结构体参数,也就是sConfig 

     再进入HAL_ADC_ConfigChannel(对寄存器进行赋值)

     

    #define MODIFY_REG(REG, CLEARMASK, SETMASK)  WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))

    还是之前没有去仔细看配置过程,单纯为了用库而用库,所以按照很多教程(非DMA得多通道采样都失败了。)

    最终看到正点原子文档上的代码。(它用的hal库,但延续了标准库的风格,所以完全就是自己写,没有用cubeMX去自动生成代码)

    最终解决方法:简单地说就是让多通道变成单通道,改配置就好了,改的配置就是通道!因为cubeMX只生成了一次,所以就定义了一次配置。。。。

     

     重写adc的初始化: 也就是变成单通道

    1. void MX_ADC1_Init(void)
    2. {
    3. ADC_ChannelConfTypeDef sConfig = {0};
    4. /** Common config
    5. */
    6. hadc1.Instance = ADC1;
    7. hadc1.Init.ScanConvMode = DISABLE;
    8. hadc1.Init.ContinuousConvMode = DISABLE;
    9. hadc1.Init.DiscontinuousConvMode = DISABLE;
    10. hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    11. hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    12. hadc1.Init.NbrOfConversion = 1;
    13. }

    另外引脚的GPIO初始化为模拟输入这个用cubeMX生成的就可以。

    每次根据自己想读的adc通道去进行读取,也就是改adc句柄的配置,以adc1位例子

    1. u16 get_adc(u32 ch){
    2. ADC_ChannelConfTypeDef _adc;
    3. _adc.Channel=ch;
    4. _adc.Rank=1;
    5. _adc.SamplingTime=ADC_SAMPLETIME_239CYCLES_5;
    6. HAL_ADC_ConfigChannel(&hadc1,&_adc);
    7. HAL_ADC_Start(&hadc1);
    8. HAL_ADC_PollForConversion(&hadc1,10);
    9. return (u16)HAL_ADC_GetValue(&hadc1);
    10. }

    效果 (引脚测试电压正确)

     

    结论:多通道按单通道配置。我测试的时候是单次转换和连续转换都行。

     

     

     

  • 相关阅读:
    DWT变换
    方舟单机/管理员生物指令代码大全
    web前端期末大作业:基于HTML+CSS+JavaScript奥迪企业bootstrap响应式网站
    双线性插值
    【Linux】自动化构建工具-make/Makefile&&第一个小程序
    异地办公也能畅快、无限制远程访问公司内网的解决方案
    linux设备模型:pci驱动程序注册过程
    【Java开发语言 00】环境搭建(配置java环境+‘javac’不是内部或外部命令,也不是可运行的程序+安装idea+idea基本用法)
    云原生应用开发培训,开启云计算时代的新征程
    HJ86 求最大连续bit数
  • 原文地址:https://blog.csdn.net/PHILICS7/article/details/125898094