本帖最后由 hejun96 于 2021-6-11 09:37 编辑
- #ifndef __BSP_ADC_H_
- #define __BSP_ADC_H_
- #ifdef __cplusplus
- extern "C" {
- #endif
- typedef struct
- {
- void (*Config)(void);
- void (*Handler) (void);
-
- volatile uint16_t usValue;
- float fVoltage;
- }adc_t;
- static void AdcDmaConfig(void);
- static void ADCxGPIOConfig(void);
- static void ADCxModeConfig(void);
- void adcConfig(void);
- u16 GetAdc(u8 ch);
- u16 GetAdcAverage(u8 ch,u8 times);
- static void Voltage_ADC_Filter(void);
- float Get_VoltageValue(void);
- //ADC Temperature Sensor
- void TemperatureadcConfig(void);
- u16 GetTemperatureAdc(u8 ch);
- u16 GetTemperatureAverage(void);
- u16 GetTemperatureAdcAverage(u8 ch,u8 times);
- short GetTemperatureValue(void);
- extern adc_t Adc;
- #ifdef __cplusplus
- }
- #endif
- #endif
#申请原创#
AT32F403A下ADC+DMA采集电压值
- <div class="blockcode"><blockquote>/* Includes -------------------------------------------------*/
- #include "includes.h"
- /* Private define -------------------------------------------*/
- //DMA
- /*采集的通道数*/
- #define SAMPLE_CHANNEL_NUM (1)//ֻ只需要1个DMA通道///(5)
- /*一次采集的次数*/
- #define SAMPLE_COUNT (10)
- #define ADC1_DR_ADDRESS ((uint32_t)0x4001244C)
- //ADC
- //ADC_GPIO宏定义
- #define ADC_GPIO_APBxClockFUN RCC_APB2PeriphClockCmd
- #define ADC_GPIO_CLK RCC_APB2Periph_GPIOA
- #define ADC_PORT GPIOA
- #define ADC_PIN GPIO_Pin_11
- //ADC编号选择
- #define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd
- #define ADC_x ADC1
- #define ADC_CLk RCC_APB2Periph_ADC1
- #define ADC_CHANNEL
- #define ADC_IRQ ADC1_2_IRQn
- #define ADC_IRQHandler ADC1_2_IRQHnadler
- #define ADCx ADC1
- #define ADC_CHLx ADC_Channel_10
- #define ADC_DMA_CHANNEL DMA1_Channel1
- /* Private variables ----------------------------------------*/
- static unsigned int mmi_adc_timer;
- /*采集存放的AD值ֵ ADC1转换的电压值通过MDA方式传到SRAM*/
- ///static volatile u16 ADC_ConvertedValue[SAMPLE_CHANNEL_NUM*SAMPLE_COUNT];
- volatile uint16_t ADC_ConvertedValue;///[SAMPLE_CHANNEL_NUM*SAMPLE_COUNT];
- static u16 nDmaMenLen;//保存DMA每次数据传送的长度
- ///__IO uint16_t ADC_ConvertedValue[50];
- __IO uint16_t After_filter;//用来存放求平均值之后的结果
- /* Private function prototypes ------------------------------*/
- static void adcConfig(void);
- static void adcHandler(void);
- static u16 GetAdc(u8 ch);
- static u16 getAdcAverage(u8 ch,u8 times);
- /* Public variables -----------------------------------------*/
- adc_t Adc =
- {
- adcConfig,
- adcHandler,
-
- 0,
- 0.0,
- };
- //PA1-Voltage ADC
- static void ADCxGPIOConfig(void)
- {
- /*
- GPIO_InitType GPIO_InitStructure;
- //1.配置ADC_IO引脚模式,模拟输入
-
- GPIO_InitStructure.GPIO_Pins = ADC_DET_PIN;//ADC对应PA1口
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_ANALOG;//模拟输入
- GPIO_Init(ADC_DET_PORT,&GPIO_InitStructure);
- */
- GPIOC->CTRLL &= 0XFFFFFFF0;//先获取该bit位
- GPIOC->CTRLL |= 0X00000000;//设置bit位
-
- }
- static void AdcDmaConfig(void)
- {
-
- DMA_InitType DMA_InitStructure;
- // 配置 DMA 初始化结构体
- // 外设基址为:ADC 数据寄存器地址
-
- //使能DMA1通道1
- DMA_Reset(ADC_DMA_CHANNEL);
-
- //外设地址
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_ADDRESS;
-
- // 存储器地址
- DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Adc.usValue;
-
- // 数据源来自外设
- DMA_InitStructure.DMA_Direction = DMA_DIR_PERIPHERALSRC;
-
- // 缓冲区大小,应该等于数据目的地的大小
- DMA_InitStructure.DMA_BufferSize = SAMPLE_CHANNEL_NUM*SAMPLE_COUNT;//
-
- // 外设寄存器只有一个,地址不用递增
- DMA_InitStructure.DMA_PeripheralInc = DMA_PERIPHERALINC_DISABLE;
- // 存储器地址固定
- DMA_InitStructure.DMA_MemoryInc = DMA_MEMORYINC_DISABLE;
-
- // 外设数据大小为半字,即两个字节
- DMA_InitStructure.DMA_PeripheralDataWidth = DMA_PERIPHERALDATAWIDTH_HALFWORD;
-
- // 内存数据大小也为半字,跟外设数据大小相同
- DMA_InitStructure.DMA_MemoryDataWidth = DMA_MEMORYDATAWIDTH_HALFWORD;
-
- //循环传输模式
- DMA_InitStructure.DMA_Mode = DMA_MODE_CIRCULAR;
-
- // DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
- ///DMA_InitStructure.DMA_Priority = DMA_Priority_High;
-
- // 禁止存储器到存储器模式,因为是从外设到存储器
- DMA_InitStructure.DMA_MTOM = DMA_MEMTOMEM_DISABLE;
-
- // 初始化DMA
- DMA_Init(ADC_DMA_CHANNEL, &DMA_InitStructure);
-
- // 使能 DMA 通道
- DMA_ChannelEnable(ADC_DMA_CHANNEL , ENABLE);
- }
- //DMA1的各通道配置
- //这里的传输形式是固定的,这点要根据不同的情况来修改
- //从存储器->外设模式/8位数据宽度/存储器增量模式
- //DmaChannelx:DMA通道CHx
- //cpar:外设地址
- //cmar:存储器地址
- //cndtr:数据传输量
- static void DmaConfig(DMA_Channel_Type* DMA_CHANNELx,u32 cpar,u32 cmar,u16 cndtr)
- {
- GeneralTimer.Timer4DelayNms(5);//等待DMA时钟稳定
- DMA_CHANNELx->CPBA=cpar; //DMA1 外设地址
- DMA_CHANNELx->CMBA=(u32)cmar; //DMA1,存储器地址
- nDmaMenLen=cndtr; //保存DMA传输数据量
- DMA_CHANNELx->TCNT=cndtr; //DMA1,传输数据量
- DMA_CHANNELx->CHCTRL=0X00000000; //复位
- DMA_CHANNELx->CHCTRL|=1<<4; //从存储器读
- DMA_CHANNELx->CHCTRL|=0<<5; //普通模式
- DMA_CHANNELx->CHCTRL|=0<<6; //外设地址非增量模式
- DMA_CHANNELx->CHCTRL|=1<<7; //存储器增量模式
- DMA_CHANNELx->CHCTRL|=0<<8; //外设数据宽度为8位
- DMA_CHANNELx->CHCTRL|=0<<10; //存储器数据宽度8位
- ///DMA_CHANNELx->CHCTRL|=1<<12; //中等优先级
- DMA_CHANNELx->CHCTRL|=0<<14; //非存储器到存储器模式
- }
- //ADC2没有DMA,故使用DMA1
- static void ADCxModeConfig(void)
- {
-
- ADC_InitType ADC_InitStructure;
- //1.打开ADC_IO接口时钟
- AdcDmaConfig();
- ///ADC_Reset(ADCx);
-
- //只使用一个ADC,属于单模式
- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
- ADC_InitStructure.ADC_ScanMode = DISABLE;//一次是否需要同时转换多个ADC通道,不需要则设置DISABLE,反之ENABLE
- ADC_InitStructure.ADC_ContinuousMode = ENABLE;//连续转换
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
- ADC_InitStructure.ADC_ExternalTrig = ADC_ExternalTrig_None;
- ADC_InitStructure.ADC_NumOfChannel = SAMPLE_CHANNEL_NUM;//单通道采集
- ADC_Init(ADCx,&ADC_InitStructure);
-
- RCC_ADCCLKConfig(RCC_APB2CLK_Div4);//AT32F403A ADC频率不超过28MHz,72/6 = 12MHz
-
- //配置 ADC 通道转换顺序为1,第一个转换,采样时间为239.5个时钟周期
- ADC_RegularChannelConfig(ADCx,ADC_CHLx,1,ADC_SampleTime_239_5);
- //使能ADC1的DMA搬运功能
- ADC_DMACtrl(ADCx,ENABLE);
-
- ADC_Ctrl(ADCx, ENABLE); //使能指定的ADC1
- /*
- //GD32F103这里适当加延时
- GeneralTimer.Timer4DelayNms(1);//1ms延时
- */
- ADC_RstCalibration(ADCx); //使能复位校准
-
- while(ADC_GetResetCalibrationStatus(ADCx)); //等待复位校准结束
-
- ADC_StartCalibration(ADCx); //开启AD校准
-
- while(ADC_GetCalibrationStatus(ADCx)); //等待校准结束
- /*
- //GD32F103这里适当延时
- GeneralTimer.Timer4DelayNms(1);//1ms延时
- */
- //由于没有采用外部触发,所以使用软件触发ADC转换
- ADC_SoftwareStartConvCtrl(ADCx,ENABLE);
- }
- static void adcConfig(void)
- {
- ADCxGPIOConfig();
- ADCxModeConfig();
- }
- /*****************************************
- Function:GetAdc
- Description:
- Calls:
- Called By:
- Table Accessed:
- Table Update:
- Input:
- Output:
- Return:ADC_GetConversionValue(ADC1);
- Others:
- ******************************************/
- static u16 GetAdc(u8 ch)
- {
- //设置指定ADC的规则组通道,一个序列,采样时间
- ADC_RegularChannelConfig(ADCx,ch,1,ADC_SampleTime_239_5);
-
- ADC_SoftwareStartConvCtrl(ADCx,ENABLE);
-
- while(!ADC_GetFlagStatus(ADCx,ADC_FLAG_EC));
- return ADC_GetConversionValue(ADCx);
- }
- /*
- *@brief:获取ADC的平均值
- *@function:u16 GetAdcAverage
- *@param:u8 ch,u8 times
- *@retval:AdcAverageValue/times
- */
- static u16 getAdcAverage(u8 ch,u8 times)
- {
- u32 AdcAverageValue=0;
- u8 t;
- for(t=0;t<times;t++)
- {
- AdcAverageValue+=GetAdc(ch);
- GeneralTimer.Timer4DelayNms(5);
- }
- return AdcAverageValue/times;
- }
- static float getVoltageValue(void)
- {
- /*
- Adc.usAdcValue = getAdcAverage(ADC_CHLx,10);//PC0-AD_IN10采集10次
- Adc.fVoltage = (float)Adc.usAdcValue*(3.3/(1000/1470) / 4095);//adcValue = (3.3V/(1000KΩ/(1000+470)KΩ))/4095 分压电阻(R1/R1+R2)
- */
-
- Adc.fVoltage = (float) Adc.usValue*(3.3/(1000/1470) / 4095);
- return Adc.fVoltage;///return Adc.fVoltage;
- }
- static void adcHandler(void)
- {
- //ADC任务写在这里
- float fVoltageValue;
- fVoltageValue = getVoltageValue();
-
- if(Adc.usValue < 2955)//DC 在3.5V以下进入休眠模式 Adc.usAdcValue < (3.5V * 4095 * 1000 / 1470 /3.3)
- {
- Led.Mode = LED_BLINK;
- }
- else
- {
- Led.Mode = LED_LIGHTING;
- }
-
- }
- /*
- //求平均值函数
- static void Voltage_ADC_Filter(void)
- {
- int sum = 0;
- uint8_t count;
-
- for(count=0;count<50;count++)
- {
- sum += ADC_ConvertedValue[count];
-
- }
- After_filter = sum/50;
- }
- float Get_VoltageValue(void)
- {
- float Value;
- Voltage_ADC_Filter();
-
- Value = (float)After_filter*(float)3.3/4096;
- return Value;
- }
- */
由于使用了AT32F403A的DMA,getAdcAverage这个函数就不需要了 @21小跑堂
|