电阻分压ADC电量采集
STM32的ADC特点:
※STM32L051单片机具有12位ADC(逐次逼近型ADC);
※ADC具有四中工作模式:单次、连续、扫描、不连续;
※ADC采集的结果具有左对齐和右对齐两种方式的16位寄存器;
※ADC模拟看门狗功能允许开发人员监测ADC的电压输入是否超过设置上下门限;
※一个高效的低功耗模式允许ADC采集在极低的功耗下运行;
※ADC具有多点连续采集模式,该模式通过硬件完成多点采集减少了CPU的占用率提高采样效率;
STM32的ADC功能描述:
ADC具有内部独立的电压调节器,调节器必须在使用ADC前使能并且等待调节器稳定后才能使用ADC;调节器的稳定时间由硬件自己决定,开发人员无需关注;
校准:ADC具有自动校准功能,开发人员在校准ADC之后才能使用ADC,校准能够消除芯片和芯片之间的差异以及其他硬件偏移;
ADC时钟:ADC具有双时钟模式,ADC有一个独立的内部时钟源;
1 初始化:
Linki2u产品的ADC采集通过STM32的ADC单次采样模式进行;电量检测通过电阻分压的方式进行,ADC的初始化配置:
AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4;
//初始化ADC的时钟,这个参数只能在ADC停止工作的时候更改 ****
AdcHandle.Init.Resolution = ADC_RESOLUTION12b;
//初始化ADC的分辨率 ****
AdcHandle.Init.ScanDirection = ADC_SCAN_DIRECTION_UPWARD;
//采样方向
AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIG_EDGE_NONE;
//触发方式
AdcHandle.Init.EOCSelection = EOC_SINGLE_CONV;
//采样完成EOC标志位置位
AdcHandle.Init.DMAContinuousRequests = DISABLE;
//DMA连续模式关闭
AdcHandle.Init.DiscontinuousConvMode = DISABLE;
//非连续模式关闭
AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
//右对齐
AdcHandle.Init.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
//采样周期设置
AdcHandle.Init.OversamplingMode = DISABLE;
//过量采集模式禁止
AdcHandle.Init.LowPowerAutoOff = ENABLE;
//使能单次采集模式
AdcHandle.Init.LowPowerFrequencyMode = DISABLE;
//
AdcHandle.Init.LowPowerAutoWait = DISABLE;
//
AdcHandle.Init.ContinuousConvMode = DISABLE;
//
HAL_ADC_Init(&AdcHandle);
//初始化ADC参数
2ADC校准
HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_SINGLE_ENDED);
//开启ADC校准
3设置ADC通道
sConfig.Channel = ADC_CHANNEL_7;
//ADC采样通道
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
//设置ADC采样通道
4使能ADC功能
HAL_ADC_Start(&AdcHandle);
单次采集流程:
电池电量通过电阻分压ADC采样的方式获取;
1) 程序中定义了一个电池电量的结构体:
typedef uint16_t (* ARRAYAVRAGE ) (uint16_t buf[],uint8_t len);
typedef uint16_t (* PARAMEMPTYFUN) (void);
typedef struct Tag_Framet_Battery
{
uint8_t lnvalue; //电池电量的线性系数
uint8_t adcnt; //电池电量ADC采样次数
uint8_t delay_cnt; //延时次数
uint16_t *ptr; //电池电量采样指针
uint16_t ADCValue[10]; //电池电量采样数据数组
float bat_value; //电池电量
ARRAYAVRAGE AvgFun; //电池电量数据处理函数
PARAMEMPTYFUN ValueFun; //电池电量采样函数
}Framet_Battery;
2 初始化电池电量采集的参数
void BatTest_funInit(Framet_Battery *bat)
{
bat->lnvalue=0;
bat->adcnt=0;
bat->delay_cnt=0;
bat->bat_value=0;
bat->ValueFun=(PARAMEMPTYFUN)Get_singleADCValue;//单次采样模式
bat->ptr=bat->ADCValue;
bat->AvgFun=(ARRAYAVRAGE) StrBubble_Sort; //数据求均值
}
3 ADC采集
主循环中进行数据采集;
#define FILTERCOUNTER 10 //¶¨ÒåÊý¾ÝÂ˲¨¸öÊý
#define VDD_ADCREF (3.3)
#define MAX_ADCSAMPLE (4096.0)
#define ADCRESOLUTION (VDD_ADCREF/MAX_ADCSAMPLE)
#define RES_UP (133000.0)
#define RES_DOWN (100000.0)
#define RES_SUM (RES_UP+RES_DOWN)
#define BAT_MAXVALUE (4.1)//ΪÁËÂú×ã﮵ç³ØÌØÐÔ½«ÉÏÏÞ¼õС
#define BAT_MINVALUE (3.0)
#define BAT_ABSOLUTE (BAT_MAXVALUE-BAT_MINVALUE)
#define PERCENTAGE (100.0)
uint16_t Get_singleADCValue()
{
uint16_t ADCvalue;
ADC1->CR |= ADC_CR_ADSTART;
HAL_ADC_PollForConversion(&AdcHandle,5000);
ADCvalue=HAL_ADC_GetValue(&AdcHandle);
return ADCvalue;
}
void Get_BatLinValue(Framet_Battery *bat)
{
bat->delay_cnt++;
if(bat->delay_cnt==100)
{
bat->delay_cnt=0;
bat->ADCValue[bat->adcnt++]=bat->ValueFun();
if(bat->adcnt==10)
{
bat->adcnt=0;
bat->bat_value=
bat->AvgFun(bat->ptr,FILTERCOUNTER)*ADCRESOLUTION*RES_SUM/RES_DOWN;
bat->lnvalue=(uint8_t)((bat->bat_value-BAT_MINVALUE)*PERCENTAGE/BAT_ABSOLUTE);
if(bat->lnvalue>100) bat->lnvalue=100;
}
}
}
因篇幅问题不能全部显示,请点此查看更多更全内容