本帖最后由 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小跑堂 |