系统供电3.3V,PA1连接电池电压(最高4.2v锂电池)分压电阻为470K、100K,PA5用于测试外部NTC温度检测,后来又改为了霍尔检测,无应用需求的,可不用细究。代码结构:前面是头文件代码,后面是应用代码,仅做记录,方便以后移植应用,代码已测试。
#ifndef __ADC_H__
#define __ADC_H__
// #include "n32wb452.h"
#include "main.h"
#define V25 1.32f
#define AVG_SLOPE 0.004f
//__packed
struct __ADC__
{
u16 voltage; //power voltage
u16 adcBuf[10];
u32 value; //ADC原始数据
u32 sampleTime; //采样时间
double tem; //温度
u32 resistance; //电阻值
u8 ok; //采样OK标志
u8 debug; //调试模式控制。
};
extern struct __ADC__ Adc1; //battery
extern struct __ADC__ Adc2; //type_c J405
extern u16 cpuTemperature; //0.1摄氏度
extern float cpuTemperatureFloat;
float TempCal(uint16_t TempAdVal);
uint16_t ADC_GetData(ADC_Module* ADCx, uint8_t ADC_Channel);
float cpuTempGet(void); //CPU内部温度获取。
void adcInit(void); //adc 初始化
void adcDeal(void); //ADC数据处理
#endif
// #include "main.h"
#include "adc.h"
#ifdef HARD_202303 //LDO芯片3.3V贴错成了2.8V的.
#define ADC1_TO_V_FACTOR ((28*(570.0f))/4096) //The coefficient:adc value to voltage value,mv.
#else
#define ADC1_TO_V_FACTOR ((33*(570.0f))/4096) //The coefficient:adc value to voltage value,mv.
// #define ADC_TO_V_FACTOR ((3300*(100.0f+470))/(4096*100.0f)) //转换系数:ADC采样值转换到电池电压单位mv
#endif
#define ADC2_TO_V_FACTOR (3300/4096.0f)
u16 cpuTemperature = 0; //0.1摄氏度
float cpuTemperatureFloat = 0;
struct __ADC__ Adc1; //PA1 ADC1 battery voltage
struct __ADC__ Adc2; //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);
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 供电电压 PA5:连接到TypeC接口
{
GPIO_InitType GPIO_Initure;
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC1,ENABLE);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC2,ENABLE);
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV16);
GPIO_Initure.Pin = GPIO_PIN_1|GPIO_PIN_5;
GPIO_Initure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitPeripheral(GPIOA, &GPIO_Initure);
ADC_Initial(ADC1);
ADC_Initial(ADC2);
Adc1.sampleTime = 500; //This code just for testing.
Adc2.sampleTime = 100; //This code just for testing.
Power.powerDown = FALSE;
Power.lowPower = 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(ADC_Module* ADCx, uint8_t ADC_Channel)
{
uint16_t dat;
ADC_ConfigRegularChannel(ADCx, ADC_Channel, 1, ADC_SAMP_TIME_239CYCLES5);
ADC_EnableSoftwareStartConv(ADCx, ENABLE);
while(ADC_GetFlagStatus(ADCx, ADC_FLAG_ENDC)==0){
}
ADC_ClearFlag(ADCx, ADC_FLAG_ENDC);
ADC_ClearFlag(ADCx, ADC_FLAG_STR);
dat=ADC_GetDat(ADCx);
return dat;
}
// u16 V30 = 0;
#define Vc0 0 //X
#define Tc1 1.5f
float TempCal(uint16_t TempAdVal)
{
float Temperate;
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;
return Temperate;
}
float cpuTempGet(void) //CPU内部温度获取。
{
float Temperate;
float tempValue;
ADC_ConfigRegularChannel(ADC1, ADC_CH_16, 1, ADC_SAMP_TIME_239CYCLES5);//ADC_CH_16:测温度,ADC_CH_18:测内部1.2V基准
ADC_EnableTempSensorVrefint(ENABLE);
ADC_EnableSoftwareStartConv(ADC1, ENABLE);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ENDC)==0)
{
}
ADC_ClearFlag(ADC1, ADC_FLAG_ENDC);
ADC_ClearFlag(ADC1, ADC_FLAG_STR);
tempValue=ADC_GetDat(ADC1);
// Voltage value of temperature sensor
Temperate = TempCal(tempValue);
return Temperate;
}
void adcDeal(void) //ADC数据处理
{
static u32 adc1Time = 0;
static u32 adc2Time = 0;
static u32 cpuTemTime = 0;
if (Timer.ms - cpuTemTime>5000)
{
cpuTemTime = Timer.ms;
float Temperate = cpuTempGet();
cpuTemperature = Temperate*10;
cpuTemperatureFloat = Temperate;
// debugLog("CPU 温度:%f.",Temperate);
}
if(Timer.ms -adc1Time>Adc1.sampleTime) //sampling time control.
{
adc1Time = Timer.ms;
static u8 index = 0;
Adc1.adcBuf[index++] = ADC_GetData(ADC1,ADC1_Channel_02_PA1);
if (index>=10)
{
u16 max = Adc1.adcBuf[0];
u16 min = Adc1.adcBuf[0];
for (int i = 1; i < 10; i++) //从1开始
{
if (Adc1.adcBuf[i] > max)
{
max = Adc1.adcBuf[i];
}
else if (Adc1.adcBuf[i] < min)
{
min = Adc1.adcBuf[i];
}
}
Adc1.value = 0;
for (int i = 0; i < 10; i++)
{
Adc1.value += Adc1.adcBuf[i];
}
Adc1.value = Adc1.value-max-min; //去掉一个最大值,去掉一个最小值
Adc1.value = Adc1.value>>3; //取8个采样点平均值。
Adc1.voltage = Adc1.value*ADC1_TO_V_FACTOR; //equipment.voltage分辨率 mV
Adc1.ok = TRUE;
index = 0;
}
}
if(Timer.ms -adc2Time>Adc2.sampleTime) //sampling time control. NTC
{
static u8 times = 0;
static u32 averageAdcValue = 0;
adc2Time = Timer.ms;
averageAdcValue += ADC_GetData(ADC2,ADC2_Channel_02_PA5); //ADC value.
if (++times<10) return;
times = 0;
Adc2.value = averageAdcValue/10; //计算平均值。
averageAdcValue = 0;
Adc2.voltage = Adc2.value*ADC2_TO_V_FACTOR; //equipment.voltage分辨率 0.001V
Adc2.tem = getNtcTempertature(Adc2.voltage);
if (Adc2.value>2000)
{
if (Device.hallSw == 0)
{
Device.hallSw = 1; //0:霍尔闭合状态,关门 1:开门,霍尔弹起状态
Jt808.alarm = ALARM_HALL_ON;
printf("霍尔报警:%d.\r\n",Device.hallSw);
}
}
else
{
if (Device.hallSw == 1)
{
Device.hallSw = 0; //0:霍尔闭合状态,关门 1:开门,霍尔弹起状态
Jt808.alarm = ALARM_HALL_OFF;
printf("霍尔报警:%d.\r\n",Device.hallSw);
}
}
debugLog("CPU温度:%.2f,温度:%.2f,湿度:%0.2f%%,NTC温度:%.2f,NTC_ADC:%d,NTC_V:%dmv,NTC RS:%dR.",cpuTemperatureFloat, Aht20.tem/10.0,Aht20.hum/10.0,Adc2.tem,Adc2.value,Adc2.voltage,Adc2.resistance);
Adc2.ok = TRUE;
}
}