您的当前位置:首页正文

STM32L051电阻分压ADC电量采集

2020-06-23 来源:客趣旅游网


电阻分压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;

}

}

}

因篇幅问题不能全部显示,请点此查看更多更全内容