系统供电3.3V,PA1连接电池电压(最高4.2v锂电池)分压电阻为910K、390K,PA3用于测试外部12V-26V外接电压,分压电阻1M、100K,不用细究。同样,前面是头文件代码,后面是应用代码,仅做记录,方便以后移植应用,代码已实测。
#ifndef __ADC_VOLTAGE_H__
#define __ADC_VOLTAGE_H__
// #include "n32wb452.h"
#include "main.h"
// #define HARD_202303 1
#ifdef HARD_202303 //LDO芯片3.3V贴错成了2.8V的.
#define ADC1_TO_V_FACTOR (2800*(390.0f+910)/4096/390) //The coefficient:adc value to voltage value,mv.
#else
#define ADC1_TO_V_FACTOR ((3300*(1300.0f))/(4096*390)) //The coefficient:adc value to voltage value,mv.
// #define ADC_TO_V_FACTOR ((3300*(390.0f+910))/(4096*390.0f)) //转换系数:ADC采样值转换到电池电压单位mv
#endif
// #define ADC2_TO_V_FACTOR (3300*(1100.0f)/4096/100)
#define ADC2_TO_V_FACTOR (3300*(11.0f)/4096)
//__packed
struct __ADC__
{
u16 voltage; //转换出来的电压值,单位mv
u16 value; //ADC原始数据
u32 sampleTime; //采样时间
double tem; //温度
u8 ok; //采样OK标志
u8 debug; //调试模式控制。
};
// float TempCal(uint16_t TempAdVal);
extern struct __ADC__ adc1; //battery
extern struct __ADC__ adc2; //type_c J405
extern u16 cpuTemperature; //0.1摄氏度
extern float cpuTemperatureFloat;
void adcInit(void); //adc 初始化
void adcDeal(void); //ADC数据处理
uint16_t ADC_GetData(uint8_t ADC_Channel);
#endif
#include "adc.h"
//u16 voltage = 0; //power voltage
u16 cpuTemperature = 0; //0.1摄氏度
float cpuTemperatureFloat = 0;
struct __ADC__ adc1; //PA1 ADC1 battery voltage
struct __ADC__ adc2; //PA5 ADC2 TYPE_C NTC
struct __ADC__ adc0; //PA5 ADC2 TYPE_C NTC
void ADC_Initial(ADC_Module* ADCx)
{
ADC_InitType ADC_InitStructure;
// ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT; //独立模式
ADC_InitStructure.MultiChEn = DISABLE; //单通道
ADC_InitStructure.ContinueConvEn = DISABLE; //单次转换
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; //软件触发方式
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R; //数据右对齐
ADC_InitStructure.ChsNumber = 1;//
ADC_Init(ADCx, &ADC_InitStructure);
/* ADC1 enable temperature */
ADC_EnableTempSensorVrefint( ENABLE);
/* ADC1 regular ADC_CH_TEMP_SENSOR configuration */
ADC_ConfigRegularChannel(ADC, ADC_CH_TEMP_SENSOR, 1, ADC_SAMP_TIME_239CYCLES5);
ADC_Enable(ADCx, ENABLE);
while(ADC_GetFlagStatusNew(ADCx,ADC_FLAG_RDY) == RESET);
ADC_StartCalibration(ADCx);
while (ADC_GetCalibrationStatus(ADCx));
}
void adcInit(void) //adc 初始化 PA1:ADC1 电池电压 PA2:连接到TypeC接口
{
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);
// RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8); //selsect HSE as RCC ADC1M CLK Source
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8); //selsect HSI as RCC ADC1M CLK Source
/* Configure PA1 PA2 as analog input -------------------------*/
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure); //初始化结构体
GPIO_InitStructure.Pin = GPIO_PIN_1|GPIO_PIN_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Analog;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
ADC_InitType ADC_InitStructure;
ADC_InitStructure.MultiChEn = DISABLE; //单通道
ADC_InitStructure.ContinueConvEn = DISABLE; //单次转换
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; //软件触发方式
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R; //数据右对齐
ADC_InitStructure.ChsNumber = 1;//
ADC_Init(ADC, &ADC_InitStructure);
ADC_Enable(ADC, ENABLE);
while(ADC_GetFlagStatusNew(ADC,ADC_FLAG_RDY) == RESET);
ADC_StartCalibration(ADC);
while (ADC_GetCalibrationStatus(ADC));
// ADC_Initial(ADC);
adc1.sampleTime = 5000; //This code just for testing.
adc2.sampleTime = 5000; //This code just for testing.
// battery.powerDownFlag = FALSE;
// battery.lowPowerFlag = FALSE;
adc1.debug = DEBUG_ENABLE; //debug mode :default disable
// adc1.debug = DEBUG_DISABLE; //debug mode :default disable
adc2.debug = DEBUG_ENABLE; //debug mode :default disable
// adc2.debug = DEBUG_DISABLE; //debug mode :default disable
}
uint16_t ADC_GetData(uint8_t ADC_Channel)
{
uint16_t dat;
ADC_ConfigRegularChannel(ADC, ADC_Channel, 1, ADC_SAMP_TIME_55CYCLES5);
/* Start ADC Software Conversion */
ADC_EnableSoftwareStartConv(ADC,ENABLE);
while(ADC_GetFlagStatus(ADC,ADC_FLAG_ENDC)==0){
}
ADC_ClearFlag(ADC,ADC_FLAG_ENDC);
ADC_ClearFlag(ADC,ADC_FLAG_STR);
dat=ADC_GetDat(ADC);
return dat;
}
// u16 V30 = 0;
#define Vc0 0 //X
#define Tc1 1.5f
#define V25 1.32f
#define AVG_SLOPE 0.004f
float TempCal(uint16_t TempAdVal)
{
float Temperate;
// u16 V30 = *(__IO uint32_t*)((uint32_t)0x1FFFF7D0);
u16 V30 = *(__IO uint32_t*)((uint32_t)0x1FFFF7D0);
/* Get the temperature inside the chip */
// Temperate=((V30+Vc0-TempAdVal)*3.3/4095)/AVG_SLOPE+30.0f-Tc1;
// Temperate=((V30+Vc0-TempAdVal)*2.8/4095)/AVG_SLOPE+30.0f-Tc1;
Temperate=((V30+Vc0-TempAdVal)*3.3/4095)/AVG_SLOPE+30.0f-Tc1;
return Temperate;
}
float TempGet(void) //CPU内部温度获取。
{
float Temperate;
u16 adcValue;
ADC_ConfigRegularChannel(ADC, ADC_CH_TEMP_SENSOR, 1, ADC_SAMP_TIME_239CYCLES5);//ADC_CH_17:测温度,ADC_CH_18:测内部1.2V基准
ADC_EnableTempSensorVrefint(ENABLE);
ADC_EnableSoftwareStartConv(ADC, ENABLE);
while(ADC_GetFlagStatus(ADC, ADC_FLAG_ENDC)==0){
}
ADC_ClearFlag(ADC, ADC_FLAG_ENDC);
ADC_ClearFlag(ADC, ADC_FLAG_STR);
adcValue=ADC_GetDat(ADC);
adc0.value = adcValue;
// Voltage value of temperature sensor
Temperate = TempCal(adcValue);
return Temperate;
}
void adcDeal(void) //ADC数据处理
{
static u32 adc1Time = 0;
static u32 adc2Time = 0;
static u32 cpuTemTime = 0;
if (systemTime1ms - cpuTemTime>5000)
{
cpuTemTime = systemTime1ms;
float Temperate = TempGet();
Temperate = Temperate;
adc0.tem = Temperate;
cpuTemperature = Temperate*10;
cpuTemperatureFloat = Temperate;
// printf("CPU 温度:%f.\n",Temperate);
// printf("CPU 平台温度:%d.\n",cpuTemperature);
}
if(systemTime1ms-adc1Time>adc1.sampleTime) //sampling time control.
{
adc1Time = systemTime1ms;
adc1.value = ADC_GetData(ADC_CH_2_PA1);
adc1.voltage = adc1.value*ADC1_TO_V_FACTOR; //equipment.voltage分辨率 mV
adc1.ok = TRUE;
// if(adc1.debug ==DEBUG_ENABLE)
// {
// printf("ADC1 value:%d,voltage:%dmv.\r\n",adc1.value,adc1.voltage); //This code just for test.Edit by kevin.
// }
}
if(systemTime1ms-adc2Time>adc2.sampleTime) //sampling time control.
{
adc2Time = systemTime1ms;
adc2.value = ADC_GetData(ADC_CH_4_PA3);
adc2.voltage = adc2.value*ADC2_TO_V_FACTOR+parm.rsErrorCompenstateV; //分辨率 mV parm.rsErrorCompenstateV OBD外电ADC分压电阻误差补偿参数。
if (battery.obdChargeFlag == TRUE)
{
adc2.voltage += parm.chargeCompenstateV; //充电OBD拉低补偿。
}
adc2.ok = TRUE;
// if(adc2.debug ==DEBUG_ENABLE)
// {
// printf("ADC2 value:%d,voltage:%dmv.-------------------\r\n",adc2.value,adc2.voltage); //This code just for test.Edit by kevin.
// }
}
}