软件环境:keil 5.23
硬件环境:AC7811 demo板
有些客户使用我们芯片内部的温度传感器,但发现计算出来的温度值偏差太大,这里给大家提供一个计算温度的demo
#include "ac78xx.h"
#include "ac78xx_adc.h"
uint32_t ADC_Average(uint32_t *uADC_Value, uint32_t num)
{
uint32_t Max, Min, AVERAGE, SUM, j;
Max = uADC_Value[0];
Min = uADC_Value[0];
SUM = 0;
AVERAGE = 0;
j = 0;
for (j = 0; j < num; j++)
{
SUM += uADC_Value[j];
if(uADC_Value[j] > Max)
{
Max = uADC_Value[j];
}
else if (uADC_Value[j] < Min)
{
Min = uADC_Value[j];
}
}
SUM = SUM - Max - Min;
AVERAGE = SUM / (num - 2);
return(AVERAGE);
}
uint32_t bandGapAVG = 0;
uint32_t bandGapTmp[8];
uint32_t adcVal = 0;
uint8_t bIndex = 0;
float bgVol = 0.0;
float vt25Vol = 0.0;
float vt25Temprature = 0.0;
float referVol = 0.0, TsensorVol = 0.0;
float g_temperatureVal = 0.0;
uint32_t TsensorCali = 0;
uint8_t VbandgapRT = 0;
uint8_t VtsensorRT = 0;
uint8_t RTERR = 0;
#define TSENSOR_CALI_ENABLE
float ADC_GetTemperature(void)
{
ADC_InitType tempAdcConfig = {0, 0, 0, 0, 0, 0, 0};
ADC_TrigSourceType tempAdcTrigSource = {0, 0};
ADC_InitType* adcConfig;
ADC_TrigSourceType* adcTrigSource;
float temperatureVal = 0.0;
adcConfig = &tempAdcConfig;
adcTrigSource = &tempAdcTrigSource;
adcConfig->scanMode = 0;
adcConfig->continousMode = 0;
adcConfig->disContinousModeOnRegularGroup = 0;
adcConfig->disContinousModeOnInjectGroup = 0;
adcConfig->injectAutoMode = 0;
ADC_Init(ADC, adcConfig);
ADC_SetClockPrescaler(ADC, 7);
ADC_TrigSourceInit(ADC, adcTrigSource);
ADC_SetRegularGroupLength(ADC, 1);
ADC_SetRegularGroupSequence(ADC, 1, ADC_CHANNEL_AD16_BANDGAP); ///set ADC_CHANNEL_AD16_BANDGAP for AD Sample
ADC_ChannelSampleTimeSel(ADC, ADC_CHANNEL_AD16_BANDGAP, ADC_SampleTime_215Cycle);
ADC_Cmd(ADC, ADC_ENABLE);
#ifdef TSENSOR_CALI_ENABLE
TsensorCali = *((uint32_t*)0x40003050);
VbandgapRT = (uint8_t)(TsensorCali & 0x1F);
VtsensorRT = (uint8_t)((TsensorCali >> 5) & 0xFF);
RTERR = (uint8_t)((TsensorCali >> 13) & 0x3F);
printf("[ADC]TsensorCali is %u %u %u %u\r\n", TsensorCali, VbandgapRT, VtsensorRT, RTERR);
/* BG calibration */
if (VbandgapRT >> 4)
{
bgVol = 1200 - (VbandgapRT & 0xF);
}
else
{
bgVol = 1200 + (VbandgapRT & 0xF);
}
/* Vtsensor calibration */
if (VtsensorRT >> 7)
{
vt25Vol = 720 - (VtsensorRT & 0x7F) * 0.5;
}
else
{
vt25Vol = 720 + (VtsensorRT & 0x7F) * 0.5;
}
/* Temperature calibration */
if (RTERR >> 5)
{
vt25Temprature = 25 - (RTERR & 0x0F) * 0.5;
}
else
{
vt25Temprature = 25 + (RTERR & 0x0F) * 0.5;
}
#else
bgVol = 1200;
vt25Vol = 720;
vt25Temprature = 25;
#endif
for (bIndex = 0; bIndex < 8; bIndex++)
{
ADC_SoftwareStartRegularConvCmd(ADC, 1);
while (!ADC_GetIntFlag(ADC, ADC_FLAG_EOC));
bandGapTmp[bIndex] = ADC_GetRegularConversionValue(ADC);
}
bandGapAVG = ADC_Average(bandGapTmp , 8);
referVol = 4096.0 * bgVol / bandGapAVG;
ADC_SetRegularGroupSequence(ADC, 1, ADC_CHANNEL_AD17_TEMPSENSOR);
ADC_ChannelSampleTimeSel(ADC, ADC_CHANNEL_AD17_TEMPSENSOR, ADC_SampleTime_215Cycle);
udelay(5);
ADC_SoftwareStartRegularConvCmd(ADC, ADC_ENABLE);
while (!ADC_GetIntFlag(ADC, ADC_FLAG_EOC));
adcVal = ADC_GetRegularConversionValue(ADC);
TsensorVol = (adcVal / 4096.0) * referVol;
temperatureVal = (vt25Vol - TsensorVol) / 1.629 + vt25Temprature;
printf("[ADC]Tsensor temperature:%f\r\n", temperatureVal);
return temperatureVal;
}
误差嘛,我也没有严格的测试过,但是对比直接通过数据手册的参数计算,感觉误差确实要小一点。
|