[AT32F403/403A] AT32F403A下ADC+DMA采集电压值

[复制链接]
2150|8
 楼主| hejun96 发表于 2021-4-14 11:25 | 显示全部楼层 |阅读模式
本帖最后由 hejun96 于 2021-6-11 09:37 编辑
  1. #ifndef __BSP_ADC_H_
  2. #define __BSP_ADC_H_


  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif


  6. typedef struct
  7. {
  8.         void (*Config)(void);
  9.         void (*Handler) (void);
  10.         
  11.         volatile uint16_t usValue;
  12.         float fVoltage;
  13. }adc_t;



  14. static void AdcDmaConfig(void);
  15. static void ADCxGPIOConfig(void);
  16. static void ADCxModeConfig(void);
  17. void adcConfig(void);
  18. u16 GetAdc(u8 ch);
  19. u16 GetAdcAverage(u8 ch,u8 times);



  20. static void Voltage_ADC_Filter(void);
  21. float Get_VoltageValue(void);
  22. //ADC Temperature Sensor

  23. void TemperatureadcConfig(void);
  24. u16 GetTemperatureAdc(u8 ch);
  25. u16 GetTemperatureAverage(void);
  26. u16 GetTemperatureAdcAverage(u8 ch,u8 times);
  27. short GetTemperatureValue(void);

  28. extern adc_t Adc;

  29. #ifdef __cplusplus
  30. }
  31. #endif


  32. #endif

#申请原创#

AT32F403A下ADC+DMA采集电压值
  1. <div class="blockcode"><blockquote>/* Includes -------------------------------------------------*/
  2. #include "includes.h"


  3. /* Private define -------------------------------------------*/
  4. //DMA
  5. /*采集的通道数*/
  6. #define SAMPLE_CHANNEL_NUM                          (1)//ֻ只需要1个DMA通道///(5)

  7. /*一次采集的次数*/
  8. #define SAMPLE_COUNT                                          (10)  
  9. #define ADC1_DR_ADDRESS                             ((uint32_t)0x4001244C)
  10. //ADC
  11. //ADC_GPIO宏定义
  12. #define ADC_GPIO_APBxClockFUN                        RCC_APB2PeriphClockCmd
  13. #define ADC_GPIO_CLK                                        RCC_APB2Periph_GPIOA
  14. #define ADC_PORT                                                GPIOA
  15. #define ADC_PIN                                                        GPIO_Pin_11
  16. //ADC编号选择
  17. #define ADC_APBxClock_FUN                                RCC_APB2PeriphClockCmd
  18. #define ADC_x                                                        ADC1
  19. #define ADC_CLk                                                        RCC_APB2Periph_ADC1
  20. #define ADC_CHANNEL                                                        
  21. #define ADC_IRQ                                                        ADC1_2_IRQn
  22. #define ADC_IRQHandler                                        ADC1_2_IRQHnadler


  23. #define ADCx                        ADC1
  24. #define ADC_CHLx                ADC_Channel_10
  25. #define ADC_DMA_CHANNEL        DMA1_Channel1

  26. /* Private variables ----------------------------------------*/

  27. static unsigned int mmi_adc_timer;

  28. /*采集存放的AD值ֵ ADC1转换的电压值通过MDA方式传到SRAM*/
  29. ///static volatile u16 ADC_ConvertedValue[SAMPLE_CHANNEL_NUM*SAMPLE_COUNT];
  30. volatile uint16_t ADC_ConvertedValue;///[SAMPLE_CHANNEL_NUM*SAMPLE_COUNT];
  31. static u16 nDmaMenLen;//保存DMA每次数据传送的长度

  32. ///__IO uint16_t ADC_ConvertedValue[50];

  33. __IO uint16_t After_filter;//用来存放求平均值之后的结果

  34. /* Private function prototypes ------------------------------*/
  35. static void adcConfig(void);
  36. static void adcHandler(void);
  37. static u16 GetAdc(u8 ch);
  38. static u16 getAdcAverage(u8 ch,u8 times);
  39. /* Public variables -----------------------------------------*/


  40. adc_t Adc =
  41. {
  42.         adcConfig,
  43.         adcHandler,
  44.         
  45.         0,
  46.         0.0,
  47. };

  48. //PA1-Voltage ADC
  49. static void ADCxGPIOConfig(void)
  50. {
  51.         /*
  52.         GPIO_InitType GPIO_InitStructure;
  53.         //1.配置ADC_IO引脚模式,模拟输入
  54.         
  55.         GPIO_InitStructure.GPIO_Pins = ADC_DET_PIN;//ADC对应PA1口
  56.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_ANALOG;//模拟输入
  57.         GPIO_Init(ADC_DET_PORT,&GPIO_InitStructure);
  58.         */
  59.         GPIOC->CTRLL &= 0XFFFFFFF0;//先获取该bit位
  60.         GPIOC->CTRLL |= 0X00000000;//设置bit位
  61.         
  62. }


  63. static void AdcDmaConfig(void)
  64. {
  65.         
  66.         DMA_InitType DMA_InitStructure;
  67.         // 配置 DMA 初始化结构体
  68.         // 外设基址为:ADC 数据寄存器地址
  69.         
  70.         //使能DMA1通道1
  71.         DMA_Reset(ADC_DMA_CHANNEL);
  72.         
  73.         //外设地址
  74.         DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_ADDRESS;
  75.         
  76.         // 存储器地址
  77.         DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Adc.usValue;
  78.         
  79.         // 数据源来自外设
  80.         DMA_InitStructure.DMA_Direction = DMA_DIR_PERIPHERALSRC;
  81.         
  82.         // 缓冲区大小,应该等于数据目的地的大小
  83.         DMA_InitStructure.DMA_BufferSize = SAMPLE_CHANNEL_NUM*SAMPLE_COUNT;//
  84.         
  85.         // 外设寄存器只有一个,地址不用递增
  86.         DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;

  87.         //  存储器地址固定
  88.         DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_DISABLE;
  89.         
  90.         // 外设数据大小为半字,即两个字节
  91.         DMA_InitStructure.DMA_PeripheralDataWidth = DMA_PERIPHERALDATAWIDTH_HALFWORD;
  92.         
  93.         // 内存数据大小也为半字,跟外设数据大小相同
  94.         DMA_InitStructure.DMA_MemoryDataWidth = DMA_MEMORYDATAWIDTH_HALFWORD;
  95.         
  96.         //循环传输模式
  97.         DMA_InitStructure.DMA_Mode = DMA_MODE_CIRCULAR;        
  98.         
  99.         // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
  100.         ///DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  101.         
  102.         // 禁止存储器到存储器模式,因为是从外设到存储器
  103.         DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
  104.         
  105.         // 初始化DMA
  106.         DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);
  107.         
  108.         // 使能 DMA 通道
  109.         DMA_ChannelEnable(ADC_DMA_CHANNEL , ENABLE);
  110. }
  111. //DMA1的各通道配置
  112. //这里的传输形式是固定的,这点要根据不同的情况来修改
  113. //从存储器->外设模式/8位数据宽度/存储器增量模式
  114. //DmaChannelx:DMA通道CHx
  115. //cpar:外设地址
  116. //cmar:存储器地址
  117. //cndtr:数据传输量  
  118. static void DmaConfig(DMA_Channel_Type* DMA_CHANNELx,u32 cpar,u32 cmar,u16 cndtr)
  119. {
  120.         GeneralTimer.Timer4DelayNms(5);//等待DMA时钟稳定
  121.         DMA_CHANNELx->CPBA=cpar;                  //DMA1 外设地址
  122.         DMA_CHANNELx->CMBA=(u32)cmar;         //DMA1,存储器地址
  123.         nDmaMenLen=cndtr;              //保存DMA传输数据量
  124.         DMA_CHANNELx->TCNT=cndtr;            //DMA1,传输数据量
  125.         DMA_CHANNELx->CHCTRL=0X00000000;        //复位
  126.         DMA_CHANNELx->CHCTRL|=1<<4;                  //从存储器读
  127.         DMA_CHANNELx->CHCTRL|=0<<5;                  //普通模式
  128.         DMA_CHANNELx->CHCTRL|=0<<6;                 //外设地址非增量模式
  129.         DMA_CHANNELx->CHCTRL|=1<<7;                  //存储器增量模式
  130.         DMA_CHANNELx->CHCTRL|=0<<8;                  //外设数据宽度为8位
  131.         DMA_CHANNELx->CHCTRL|=0<<10;                 //存储器数据宽度8位
  132.         ///DMA_CHANNELx->CHCTRL|=1<<12;                 //中等优先级
  133.         DMA_CHANNELx->CHCTRL|=0<<14;                 //非存储器到存储器模式               
  134. }
  135. //ADC2没有DMA,故使用DMA1
  136. static void ADCxModeConfig(void)
  137. {        
  138.         
  139.         ADC_InitType ADC_InitStructure;
  140.         //1.打开ADC_IO接口时钟
  141.         AdcDmaConfig();

  142.         ///ADC_Reset(ADCx);
  143.         
  144.         //只使用一个ADC,属于单模式
  145.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  146.         ADC_InitStructure.ADC_ScanMode = DISABLE;//一次是否需要同时转换多个ADC通道,不需要则设置DISABLE,反之ENABLE
  147.         ADC_InitStructure.ADC_ContinuousMode = ENABLE;//连续转换
  148.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  149.         ADC_InitStructure.ADC_ExternalTrig = ADC_ExternalTrig_None;
  150.         ADC_InitStructure.ADC_NumOfChannel = SAMPLE_CHANNEL_NUM;//单通道采集
  151.         ADC_Init(ADCx,&ADC_InitStructure);
  152.         
  153.         RCC_ADCCLKConfig(RCC_APB2CLK_Div4);//AT32F403A ADC频率不超过28MHz,72/6 = 12MHz
  154.         
  155.         //配置 ADC 通道转换顺序为1,第一个转换,采样时间为239.5个时钟周期
  156.         ADC_RegularChannelConfig(ADCx,ADC_CHLx,1,ADC_SampleTime_239_5);
  157.         //使能ADC1的DMA搬运功能
  158.         ADC_DMACtrl(ADCx,ENABLE);
  159.         
  160.         ADC_Ctrl(ADCx, ENABLE);        //使能指定的ADC1
  161.         /*
  162.         //GD32F103这里适当加延时
  163.         GeneralTimer.Timer4DelayNms(1);//1ms延时
  164.         */
  165.         ADC_RstCalibration(ADCx);        //使能复位校准
  166.          
  167.         while(ADC_GetResetCalibrationStatus(ADCx));        //等待复位校准结束
  168.         
  169.         ADC_StartCalibration(ADCx);         //开启AD校准
  170.         
  171.         while(ADC_GetCalibrationStatus(ADCx));         //等待校准结束
  172.         /*
  173.         //GD32F103这里适当延时
  174.         GeneralTimer.Timer4DelayNms(1);//1ms延时
  175.         */
  176.         //由于没有采用外部触发,所以使用软件触发ADC转换
  177.         ADC_SoftwareStartConvCtrl(ADCx,ENABLE);
  178. }

  179. static void adcConfig(void)
  180. {
  181.         ADCxGPIOConfig();
  182.         ADCxModeConfig();
  183. }


  184. /*****************************************
  185. Function:GetAdc
  186. Description:
  187. Calls:
  188. Called By:
  189. Table Accessed:
  190. Table Update:
  191. Input:
  192. Output:
  193. Return:ADC_GetConversionValue(ADC1);
  194. Others:

  195. ******************************************/
  196. static u16 GetAdc(u8 ch)
  197. {
  198.         //设置指定ADC的规则组通道,一个序列,采样时间
  199.         ADC_RegularChannelConfig(ADCx,ch,1,ADC_SampleTime_239_5);
  200.         
  201.         ADC_SoftwareStartConvCtrl(ADCx,ENABLE);
  202.         
  203.         while(!ADC_GetFlagStatus(ADCx,ADC_FLAG_EC));
  204.         return ADC_GetConversionValue(ADCx);        
  205. }

  206. /*
  207. *@brief:获取ADC的平均值
  208. *@function:u16 GetAdcAverage
  209. *@param:u8 ch,u8 times
  210. *@retval:AdcAverageValue/times
  211. */


  212. static u16 getAdcAverage(u8 ch,u8 times)
  213. {
  214.         u32 AdcAverageValue=0;
  215.         u8 t;
  216.         for(t=0;t<times;t++)
  217.         {
  218.                 AdcAverageValue+=GetAdc(ch);
  219.                 GeneralTimer.Timer4DelayNms(5);
  220.         }
  221.         return AdcAverageValue/times;
  222. }

  223. static float getVoltageValue(void)
  224. {
  225.         /*
  226.         Adc.usAdcValue = getAdcAverage(ADC_CHLx,10);//PC0-AD_IN10采集10次
  227.         Adc.fVoltage = (float)Adc.usAdcValue*(3.3/(1000/1470) / 4095);//adcValue =  (3.3V/(1000KΩ/(1000+470)KΩ))/4095 分压电阻(R1/R1+R2)
  228.         */
  229.          
  230.         Adc.fVoltage = (float) Adc.usValue*(3.3/(1000/1470) / 4095);
  231.         return Adc.fVoltage;///return Adc.fVoltage;
  232. }

  233. static void adcHandler(void)
  234. {
  235.         //ADC任务写在这里
  236.         float fVoltageValue;
  237.         fVoltageValue = getVoltageValue();
  238.         
  239.         if(Adc.usValue < 2955)//DC 在3.5V以下进入休眠模式 Adc.usAdcValue < (3.5V * 4095 * 1000 / 1470 /3.3)
  240.         {
  241.                 Led.Mode = LED_BLINK;
  242.         }
  243.         else
  244.         {
  245.                 Led.Mode = LED_LIGHTING;
  246.         }
  247.         
  248. }


  249. /*
  250. //求平均值函数
  251. static void Voltage_ADC_Filter(void)
  252. {
  253.         int sum = 0;
  254.         uint8_t count;
  255.         
  256.         for(count=0;count<50;count++)
  257.         {
  258.                 sum += ADC_ConvertedValue[count];
  259.         
  260.         }
  261.         After_filter = sum/50;
  262. }

  263. float Get_VoltageValue(void)
  264. {
  265.         float Value;
  266.         Voltage_ADC_Filter();
  267.         
  268.         Value = (float)After_filter*(float)3.3/4096;
  269.         return Value;
  270. }

  271. */

由于使用了AT32F403A的DMA,getAdcAverage这个函数就不需要了  @21小跑堂  
两只袜子 发表于 2021-4-14 15:17 | 显示全部楼层
很棒的
huquanz711 发表于 2021-4-15 07:21 来自手机 | 显示全部楼层
不错,感谢楼主的分享。
duckfans 发表于 2021-4-17 23:46 | 显示全部楼层
学习了,感谢分享
天意无罪 发表于 2021-4-18 14:21 | 显示全部楼层
建议楼主不要一来就是粘贴代码啊,好歹还是写点介绍性的文字啊。
zhengshuai888 发表于 2021-4-18 14:36 | 显示全部楼层
ST得代码应该不能直接拿来用把
muyichuan2012 发表于 2021-4-18 15:21 来自手机 | 显示全部楼层
本帖最后由 muyichuan2012 于 2021-5-6 09:09 编辑

这是基于at32 bsp开发的代码。
lidi911 发表于 2021-4-18 18:43 | 显示全部楼层
谢谢楼主的分享,刚好在搞ADC这块。
 楼主| hejun96 发表于 2021-4-22 11:51 | 显示全部楼层
muyichuan2012 发表于 2021-4-18 15:21
这是应该是基于at32 bsp开发的代码。

是的,看bsp学习,支持雅特力
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

55

帖子

2

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