[APM32E0] APM32E030ADC

[复制链接]
 楼主| LIZARD925 发表于 2025-7-20 17:57 | 显示全部楼层 |阅读模式
本帖最后由 LIZARD925 于 2025-7-20 17:39 编辑

#技术资源#

APM32E030系列使用记录--ADC的使用

  • ADC单通道,实现ADC采样的与读取
目标:实现阻塞式读取ADC数值
程序中使用ADC1的通道2进行ADC的读取,初始化程序如下
  1. void AD_Init(void)
  2. {
  3.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  4.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
  5.         
  6.         GPIO_Config_T GPIO_InitStructure;
  7.         GPIO_InitStructure.mode = GPIO_MODE_AN;
  8.         GPIO_InitStructure.pupd = GPIO_PUPD_NO;
  9.         GPIO_InitStructure.pin = GPIO_PIN_2;
  10.         GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
  11.         GPIO_Config(GPIOA, &GPIO_InitStructure);
  12.         
  13.         ADC_Reset();
  14.         
  15.         ADC_Config_T ADC_InitStructure;
  16.         ADC_InitStructure.resolution = ADC_RESOLUTION_12B;                         //ADC数据分辨率
  17.         ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;                        //ADC扫描序列方向
  18.         ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS;                //连续扫描
  19.         ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT;                        //右对齐
  20.         ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;                //禁用外部触发转换模式
  21.         ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0;                //ADC外部触发转换定时器1 TRG0
  22.         ADC_Config(&ADC_InitStructure);
  23.         
  24.         ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5);
  25.         
  26.         ADC_ReadCalibrationFactor();        //ADC 读取校准系数
  27.         
  28.     ADC_Enable();
  29.         
  30.         ADC_StartConversion();                        //开始转换
  31. }

  32. uint16_t AD_getvalue(void)
  33. {
  34.         while(ADC_ReadStatusFlag(ADC_FLAG_CC)==RESET);                //转换结束标志
  35.         return ADC_ReadConversionValue();
  36. }
此方式的ADC数值读取使用阻塞的方式,可能会阻塞主循环的其它函数,使用滑动电阻求连接ADC引脚,通过串口将采集的数据打印出来,查看是否正确
  1. uint16_t ADvalue;
  2. float v;

  3. int main (void)
  4. {
  5.         LED_init();
  6.         AD_Init();
  7.         Serial_Init(115200);

  8.         printf("APM32E030\r\n");
  9.         
  10.         while(1)
  11.         {
  12.                 ADvalue=AD_getvalue();
  13.                 v=(float)ADvalue/4095*3.3;
  14.                 printf("ADC:%f\n",v);
  15.                
  16.                 LED1_turn();
  17.                 Delay_ms(1000);
  18.                
  19.                 rx_test();        //串口接收
  20.         }
  21. }
  • ADC单通道+中断,实现ADC采样的与读取
目标:实现中断读取ADC数值
程序中使用ADC1的通道2进行ADC的读取,初始化程序如下
  1. void AD_Init(void)
  2. {
  3.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  4.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
  5.         RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
  6.         
  7.         GPIO_Config_T GPIO_InitStructure;
  8.         GPIO_InitStructure.mode = GPIO_MODE_AN;
  9.         GPIO_InitStructure.pupd = GPIO_PUPD_NO;
  10.         GPIO_InitStructure.pin = GPIO_PIN_2;
  11.         GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
  12.         GPIO_Config(GPIOA, &GPIO_InitStructure);
  13.         
  14.         ADC_Reset();
  15.         
  16.         ADC_Config_T ADC_InitStructure;
  17.         ADC_InitStructure.resolution = ADC_RESOLUTION_12B;                         //ADC数据分辨率
  18.         ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;                        //ADC扫描序列方向
  19.         ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS;                //连续扫描
  20.         ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT;                        //右对齐
  21.         ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;                //禁用外部触发转换模式
  22.         ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0;                //ADC外部触发转换定时器1 TRG0
  23.         ADC_Config(&ADC_InitStructure);
  24.         
  25.         ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5);
  26.         
  27.         /* Enable Interrupt*/
  28.     ADC_EnableInterrupt(ADC_INT_CS);
  29.     NVIC_EnableIRQRequest(ADC1_IRQn, 2);
  30.         
  31.         ADC_ReadCalibrationFactor();        //ADC 读取校准系数
  32.     ADC_Enable();
  33.         /* Wait until ADC is ready */
  34.     while (!ADC_ReadStatusFlag(ADC_FLAG_ADRDY));
  35.         ADC_StartConversion();                        //开始转换

  36. }
只有ADC采集结束才会进入中断,将数据进行保存,此方式不阻塞主循环的其它函数,主循环通过串口将采集的数据进行打印,查看是否正确采集
  1. uint16_t ADvalue;
  2. float v;

  3. int main (void)
  4. {
  5.         LED_init();
  6.         Serial_Init(115200);
  7.         AD_Init();

  8.         printf("APM32E030\r\n");

  9.         while(1)
  10.         {
  11.                 v=(float)ADvalue/4095*3.3;
  12.                 printf("ADC:%f\n",v);
  13.                
  14.                 LED1_turn();
  15.                 Delay_ms(1000);
  16.                
  17.                 rx_test();        //串口接收
  18.         }
  19. }

  20. void ADC1_IRQHandler(void)
  21. {
  22.     if (ADC_ReadIntFlag(ADC_INT_FLAG_CS) == SET)
  23.     {
  24.         ADC_ClearIntFlag(ADC_INT_FLAG_CS);
  25.         ADvalue = ADC_ReadConversionValue();
  26.     }
  27. }
  • ADC多通道+DMA,实现ADC采样的与读取
目标:实现DMA读取ADC数值
程序中使用ADC1的通道0、1、2、3进行ADC的读取,初始化程序如下
  1. #define ADC_CH_SIZE         4
  2. uint16_t adcData[ADC_CH_SIZE];

  3. void DMA_Init(void)
  4. {
  5.     DMA_Config_T dmaConfig;

  6.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);

  7.     dmaConfig.peripheralAddress = ((uint32_t)ADC_BASE + 0x40);
  8.     dmaConfig.memoryAddress = (uint32_t)&adcData;
  9.     dmaConfig.direction = DMA_DIR_PERIPHERAL;
  10.     dmaConfig.bufferSize = ADC_CH_SIZE;
  11.     dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
  12.     dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
  13.     dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_HALFWORD;
  14.     dmaConfig.memoryDataSize = DMA_MEMORY_DATASIZE_HALFWORD;
  15.     dmaConfig.circular = DMA_CIRCULAR_ENABLE;
  16.     dmaConfig.memoryTomemory = DMA_M2M_DISABLE;
  17.     dmaConfig.priority = DMA_PRIORITY_LEVEL_HIGHT;

  18.     DMA_Config(DMA1_CHANNEL_1, &dmaConfig);
  19.     DMA_Enable(DMA1_CHANNEL_1);
  20. }

  21. void AD_Init(void)
  22. {
  23.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  24.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
  25.         
  26.         GPIO_Config_T GPIO_InitStructure;
  27.         GPIO_InitStructure.mode = GPIO_MODE_AN;
  28.         GPIO_InitStructure.pupd = GPIO_PUPD_NO;
  29.         GPIO_InitStructure.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  30.         GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
  31.         GPIO_Config(GPIOA, &GPIO_InitStructure);
  32.         
  33.         ADC_Reset();
  34.         
  35.         ADC_Config_T ADC_InitStructure;
  36.         ADC_InitStructure.resolution = ADC_RESOLUTION_12B;
  37.         ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;
  38.         ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS;        //连续扫描
  39.         ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT;        //右对齐
  40.         ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;
  41.         ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0;
  42.         ADC_Config(&ADC_InitStructure);
  43.         
  44.         ADC_ConfigChannel(ADC_CHANNEL_0, ADC_SAMPLE_TIME_239_5);
  45.     ADC_ConfigChannel(ADC_CHANNEL_1, ADC_SAMPLE_TIME_239_5);
  46.     ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5);
  47.         ADC_ConfigChannel(ADC_CHANNEL_3, ADC_SAMPLE_TIME_239_5);
  48.         
  49.         DMA_Init();
  50.         ADC_ReadCalibrationFactor();
  51.         
  52.         ADC_EnableDMA();
  53.     ADC_DMARequestMode(ADC_DMA_MODE_CIRCULAR);
  54.         
  55.     ADC_Enable();

  56.         ADC_StartConversion();
  57. }

  58. uint16_t AD_getvalue(uint8_t index)
  59. {
  60.         return adcData[index];
  61. }
配置DMA进行ADC数据的搬运,我们只需要在必要的时候读取buff中的数据即可得到ADC采集的数据,主循环中通过串口将采集的数据进行打印,查看数据是否正确
  1. uint16_t ADvalue;
  2. float v;

  3. int main (void)
  4. {
  5.         LED_init();
  6.         Serial_Init(115200);
  7.         AD_Init();
  8.         printf("APM32E030\r\n");
  9.         
  10.         while(1)
  11.         {
  12.                 ADvalue=AD_getvalue(0);
  13.                 v=(float)ADvalue/4095*3.3;
  14.                 printf("PA0ADC:%f\n",v);
  15.                
  16.                 ADvalue=AD_getvalue(1);
  17.                 v=(float)ADvalue/4095*3.3;
  18.                 printf("PA1ADC:%f\n",v);
  19.                
  20.                 ADvalue=AD_getvalue(2);
  21.                 v=(float)ADvalue/4095*3.3;
  22.                 printf("PA2ADC:%f\n",v);
  23.                
  24.                 ADvalue=AD_getvalue(3);
  25.                 v=(float)ADvalue/4095*3.3;
  26.                 printf("PA3ADC:%f\r\n",v);

  27.                 LED1_turn();
  28.                 Delay_ms(1000);
  29.                
  30.                 rx_test();        //串口接收
  31.         }
  32. }
  • ADC单通道+参考电压/温度,实现ADC采样的与读取
目标:实现读取ADC数值
程序中使用ADC1的通道16/17进行ADC的读取参考电压,初始化程序如下
  1. #include "ad.h"                  // Device header

  2. void AD_Init(void)
  3. {
  4.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);

  5.         ADC_Reset();
  6. //        ADC_EnableTempSensor();        //温度初始化
  7.         ADC_EnableVrefint();        //参考电压初始化
  8.         
  9.         ADC_Config_T ADC_InitStructure;
  10.         ADC_InitStructure.resolution = ADC_RESOLUTION_12B;                         //ADC数据分辨率
  11.         ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;                        //ADC扫描序列方向
  12.         ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS;                //连续扫描
  13.         ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT;                        //右对齐
  14.         ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;                //禁用外部触发转换模式
  15.         ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0;                //ADC外部触发转换定时器1 TRG0
  16.         ADC_Config(&ADC_InitStructure);
  17.         
  18. //        ADC_ConfigChannel(ADC_CHANNEL_16, ADC_SAMPLE_TIME_239_5);
  19.         ADC_ConfigChannel(ADC_CHANNEL_17, ADC_SAMPLE_TIME_239_5);
  20.         
  21.         ADC_ReadCalibrationFactor();        //ADC 读取校准系数
  22.         
  23.     ADC_Enable();
  24.         
  25.         ADC_StartConversion();                        //开始转换
  26. }

  27. void AD_getvalue(void)
  28. {        
  29.         uint32_t reference_adc_value = 0, tsen_adc_value = 0;
  30.         ADC_DisableTempSensor();

  31. //        ADC_ConfigChannel(ADC_CHANNEL_16, ADC_SAMPLE_TIME_239_5);
  32. //        ADC_StartConversion();
  33. //        while(ADC_ReadStatusFlag(ADC_FLAG_CC)==RESET);                //转换结束标志
  34. //        tsen_adc_value = ADC_ReadConversionValue();
  35. //        printf("tsen_adc_value: %d\n", tsen_adc_value);

  36.         
  37.         ADC_StopConversion();
  38.         ADC_ConfigChannel(ADC_CHANNEL_17, ADC_SAMPLE_TIME_239_5);
  39.         ADC_StartConversion();
  40.         while(ADC_ReadStatusFlag(ADC_FLAG_CC)==RESET);                //转换结束标志
  41.         reference_adc_value = ADC_ReadConversionValue();
  42.         printf("reference_adc_value: %d\n", reference_adc_value);
  43. }
但是读取的结果与手册写的1.2v有出入,我读到的是1.5V,不知道哪里出了问题,中断与DMA的流程和之前的一样,都可以进行读取
  • ADC多通道+参考电压/温度,实现ADC采样的与读取
目标:实现DMA读取ADC数值
程序中使用ADC1的通道进行ADC的读取,初始化程序如下
  1. #include "ad.h"                  // Device header

  2. #define ADC_CH_SIZE         6
  3. uint16_t adcData[ADC_CH_SIZE];

  4. void DMA_Init(void)
  5. {
  6.     DMA_Config_T dmaConfig;

  7.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);

  8.     dmaConfig.peripheralAddress = ((uint32_t)ADC_BASE + 0x40);
  9.     dmaConfig.memoryAddress = (uint32_t)&adcData;
  10.     dmaConfig.direction = DMA_DIR_PERIPHERAL;
  11.     dmaConfig.bufferSize = ADC_CH_SIZE;
  12.     dmaConfig.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;
  13.     dmaConfig.memoryInc = DMA_MEMORY_INC_ENABLE;
  14.     dmaConfig.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_HALFWORD;
  15.     dmaConfig.memoryDataSize = DMA_MEMORY_DATASIZE_HALFWORD;
  16.     dmaConfig.circular = DMA_CIRCULAR_ENABLE;
  17.     dmaConfig.memoryTomemory = DMA_M2M_DISABLE;
  18.     dmaConfig.priority = DMA_PRIORITY_LEVEL_HIGHT;

  19.     DMA_Config(DMA1_CHANNEL_1, &dmaConfig);
  20.     DMA_Enable(DMA1_CHANNEL_1);
  21. }

  22. void AD_Init(void)
  23. {
  24.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  25.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
  26.        
  27.         GPIO_Config_T GPIO_InitStructure;
  28.         GPIO_InitStructure.mode = GPIO_MODE_AN;
  29.         GPIO_InitStructure.pupd = GPIO_PUPD_NO;
  30.         GPIO_InitStructure.pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  31.         GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
  32.         GPIO_Config(GPIOA, &GPIO_InitStructure);
  33.        
  34.         ADC_Reset();
  35.         ADC_EnableTempSensor();
  36.         ADC_EnableVrefint();
  37.        
  38.         ADC_Config_T ADC_InitStructure;
  39.         ADC_InitStructure.resolution = ADC_RESOLUTION_12B;
  40.         ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;
  41.         ADC_InitStructure.convMode = ADC_CONVERSION_CONTINUOUS;        //连续扫描
  42.         ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT;        //右对齐
  43.         ADC_InitStructure.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;
  44.         ADC_InitStructure.extTrigConv = ADC_EXT_TRIG_CONV_TRG0;
  45.         ADC_Config(&ADC_InitStructure);
  46.        
  47.         ADC_ConfigChannel(ADC_CHANNEL_0, ADC_SAMPLE_TIME_239_5);
  48.     ADC_ConfigChannel(ADC_CHANNEL_1, ADC_SAMPLE_TIME_239_5);
  49.     ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5);
  50.         ADC_ConfigChannel(ADC_CHANNEL_3, ADC_SAMPLE_TIME_239_5);
  51.         ADC_ConfigChannel(ADC_CHANNEL_16, ADC_SAMPLE_TIME_239_5);
  52.         ADC_ConfigChannel(ADC_CHANNEL_17, ADC_SAMPLE_TIME_239_5);
  53.        

  54.         DMA_Init();
  55.         ADC_ReadCalibrationFactor();
  56.        
  57.         ADC_EnableDMA();
  58.     ADC_DMARequestMode(ADC_DMA_MODE_CIRCULAR);
  59.        
  60.     ADC_Enable();

  61.         ADC_StartConversion();
  62. }

  63. uint16_t AD_getvalue(uint8_t index)
  64. {
  65.         return adcData[index];
  66. }


将每个通道保存到buff中,进行读取即可
  1. uint16_t ADvalue;
  2. float v;

  3. int main (void)
  4. {
  5.         LED_init();
  6.         Serial_Init(115200);
  7.         AD_Init();
  8.         printf("APM32E030\r\n");
  9.        
  10.         while(1)
  11.         {
  12.                 ADvalue=AD_getvalue(0);
  13.                 v=(float)ADvalue/4095*3.3;
  14.                 printf("PA0ADC:%f\n",v);
  15.                
  16.                 ADvalue=AD_getvalue(1);
  17.                 v=(float)ADvalue/4095*3.3;
  18.                 printf("PA1ADC:%f\n",v);
  19.                
  20.                 ADvalue=AD_getvalue(2);
  21.                 v=(float)ADvalue/4095*3.3;
  22.                 printf("PA2ADC:%f\n",v);
  23.                
  24.                 ADvalue=AD_getvalue(3);
  25.                 v=(float)ADvalue/4095*3.3;
  26.                 printf("PA3ADC:%f\r\n",v);
  27.                
  28.                 ADvalue=AD_getvalue(4);
  29.                 printf("TempSensor:%d\r\n",ADvalue);
  30.                
  31.                 ADvalue=AD_getvalue(5);
  32.                 printf("Vref:%d\r\n",ADvalue);

  33.                 LED1_turn();
  34.                 Delay_ms(1000);
  35.                
  36.                 rx_test();        //串口接收
  37.         }
  38. }
ADC的使用到此基本差不多了,对于基准电压的采集,以后再找问题






6-1 APM32E030-ADC.zip

176.18 KB, 下载次数: 0

6-2 APM32E030-ADC中断.zip

177.23 KB, 下载次数: 0

6-3 APM32E030-ADC多通道.zip

177.69 KB, 下载次数: 1

6-4 APM32E030-ADC_temperature.zip

2.31 MB, 下载次数: 0

6-6 APM32E030-ADC多通道_temperature.zip

179.46 KB, 下载次数: 0

天体书记 发表于 2025-7-21 11:06 | 显示全部楼层
这个ADC的帖子也太霸气了。
我倾向于DMA按顺序周期扫描的策略。
黄昏收获 发表于 2025-7-21 15:21 | 显示全部楼层
这颗小芯片的ADC功能还这么丰富啊
永恒回声 发表于 2025-7-21 16:59 | 显示全部楼层
是不是M0内核的ADC模块都没有外部参考电压引脚。
我总觉得VCCA的电压不稳会带来ADC采样精度的偏差
lgm_sz 发表于 2025-8-5 20:53 | 显示全部楼层
感谢作者大佬
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

19

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部