[学习笔记] AC7811获取内部Tsensor温度的方法

[复制链接]
416|9
 楼主 | 2020-1-10 11:44 | 显示全部楼层 |阅读模式
软件环境:keil 5.23
硬件环境:AC7811 demo板

有些客户使用我们芯片内部的温度传感器,但发现计算出来的温度值偏差太大,这里给大家提供一个计算温度的demo


  1. #include "ac78xx.h"
  2. #include "ac78xx_adc.h"
  3. uint32_t ADC_Average(uint32_t *uADC_Value, uint32_t num)
  4. {
  5.     uint32_t Max, Min, AVERAGE, SUM, j;
  6.     Max = uADC_Value[0];
  7.     Min = uADC_Value[0];
  8.     SUM = 0;
  9.     AVERAGE = 0;
  10.     j = 0;

  11.     for (j = 0; j < num; j++)
  12.     {
  13.         SUM += uADC_Value[j];
  14.         if(uADC_Value[j] > Max)
  15.         {
  16.             Max = uADC_Value[j];
  17.         }
  18.         else if (uADC_Value[j] < Min)
  19.         {
  20.             Min = uADC_Value[j];
  21.         }
  22.     }
  23.     SUM = SUM - Max - Min;
  24.     AVERAGE = SUM / (num - 2);
  25.     return(AVERAGE);
  26. }


  27. uint32_t bandGapAVG = 0;
  28. uint32_t bandGapTmp[8];
  29. uint32_t adcVal = 0;
  30. uint8_t bIndex = 0;
  31. float bgVol = 0.0;
  32. float vt25Vol = 0.0;
  33. float vt25Temprature = 0.0;
  34. float referVol = 0.0, TsensorVol = 0.0;
  35. float g_temperatureVal = 0.0;


  36. uint32_t TsensorCali = 0;
  37. uint8_t VbandgapRT = 0;
  38. uint8_t VtsensorRT = 0;
  39. uint8_t RTERR = 0;

  40. #define TSENSOR_CALI_ENABLE
  41. float ADC_GetTemperature(void)
  42. {
  43.     ADC_InitType tempAdcConfig = {0, 0, 0, 0, 0, 0, 0};
  44.     ADC_TrigSourceType tempAdcTrigSource = {0, 0};
  45.     ADC_InitType* adcConfig;
  46.     ADC_TrigSourceType* adcTrigSource;
  47.     float temperatureVal = 0.0;
  48.   
  49.     adcConfig = &tempAdcConfig;
  50.     adcTrigSource = &tempAdcTrigSource;
  51.     adcConfig->scanMode = 0;
  52.     adcConfig->continousMode = 0;
  53.     adcConfig->disContinousModeOnRegularGroup = 0;
  54.     adcConfig->disContinousModeOnInjectGroup = 0;
  55.     adcConfig->injectAutoMode = 0;
  56.     ADC_Init(ADC, adcConfig);
  57.     ADC_SetClockPrescaler(ADC, 7);
  58.     ADC_TrigSourceInit(ADC, adcTrigSource);
  59.     ADC_SetRegularGroupLength(ADC, 1);
  60.     ADC_SetRegularGroupSequence(ADC, 1, ADC_CHANNEL_AD16_BANDGAP); ///set ADC_CHANNEL_AD16_BANDGAP for AD Sample
  61.     ADC_ChannelSampleTimeSel(ADC, ADC_CHANNEL_AD16_BANDGAP, ADC_SampleTime_215Cycle);
  62.     ADC_Cmd(ADC, ADC_ENABLE);

  63. #ifdef TSENSOR_CALI_ENABLE
  64.     TsensorCali = *((uint32_t*)0x40003050);
  65.     VbandgapRT = (uint8_t)(TsensorCali & 0x1F);
  66.     VtsensorRT = (uint8_t)((TsensorCali >> 5) & 0xFF);
  67.     RTERR = (uint8_t)((TsensorCali >> 13) & 0x3F);
  68.     printf("[ADC]TsensorCali is %u %u %u %u\r\n", TsensorCali, VbandgapRT, VtsensorRT, RTERR);

  69.     /* BG calibration */
  70.     if (VbandgapRT >> 4)
  71.     {
  72.         bgVol = 1200 - (VbandgapRT & 0xF);
  73.     }
  74.     else
  75.     {
  76.         bgVol = 1200 + (VbandgapRT & 0xF);
  77.     }

  78.     /* Vtsensor calibration */
  79.     if (VtsensorRT >> 7)
  80.     {
  81.         vt25Vol = 720 - (VtsensorRT & 0x7F) * 0.5;
  82.     }
  83.     else
  84.     {
  85.         vt25Vol = 720 + (VtsensorRT & 0x7F) * 0.5;
  86.     }

  87.     /* Temperature calibration */
  88.     if (RTERR >> 5)
  89.     {
  90.         vt25Temprature = 25 - (RTERR & 0x0F) * 0.5;
  91.     }
  92.     else
  93.     {
  94.         vt25Temprature = 25 + (RTERR & 0x0F) * 0.5;
  95.     }  
  96. #else
  97.     bgVol   = 1200;
  98.     vt25Vol = 720;
  99.     vt25Temprature = 25;
  100. #endif

  101.     for (bIndex = 0; bIndex < 8; bIndex++)
  102.     {
  103.          ADC_SoftwareStartRegularConvCmd(ADC, 1);
  104.          while (!ADC_GetIntFlag(ADC, ADC_FLAG_EOC));
  105.          bandGapTmp[bIndex] = ADC_GetRegularConversionValue(ADC);
  106.     }
  107.    
  108.     bandGapAVG = ADC_Average(bandGapTmp , 8);

  109.     referVol = 4096.0 * bgVol / bandGapAVG;
  110.    
  111.     ADC_SetRegularGroupSequence(ADC, 1, ADC_CHANNEL_AD17_TEMPSENSOR);
  112.     ADC_ChannelSampleTimeSel(ADC, ADC_CHANNEL_AD17_TEMPSENSOR, ADC_SampleTime_215Cycle);
  113.     udelay(5);

  114.     ADC_SoftwareStartRegularConvCmd(ADC, ADC_ENABLE);
  115.     while (!ADC_GetIntFlag(ADC, ADC_FLAG_EOC));
  116.     adcVal = ADC_GetRegularConversionValue(ADC);
  117.     TsensorVol = (adcVal / 4096.0) * referVol;
  118.     temperatureVal = (vt25Vol - TsensorVol) / 1.629 + vt25Temprature;
  119.    
  120.     printf("[ADC]Tsensor temperature:%f\r\n", temperatureVal);
  121.     return temperatureVal;
  122. }
复制代码
误差嘛,我也没有严格的测试过,但是对比直接通过数据手册的参数计算,感觉误差确实要小一点。

使用特权

评论回复
| 2020-1-10 20:25 | 显示全部楼层
           

使用特权

评论回复
| 2020-1-10 20:25 | 显示全部楼层
赞一个!!!      

使用特权

评论回复
| 2020-1-10 20:25 | 显示全部楼层
谢谢版主。           

使用特权

评论回复
| 2020-1-10 20:25 | 显示全部楼层
是均值滤波吗?         

使用特权

评论回复
| 2020-1-10 20:25 | 显示全部楼层
这个不稳定是怎么造成的?   

使用特权

评论回复
 楼主 | 2020-1-16 10:48 | 显示全部楼层
aspoke 发表于 2020-1-10 20:25
这个不稳定是怎么造成的?

每颗芯片出厂都会有误差,所以芯片出厂有在25°下校正过,我测试的时候本也没有严格的测定环境温度,只是大概的估计一下。

使用特权

评论回复
 楼主 | 2020-1-16 10:49 | 显示全部楼层

就是求了个平均数

使用特权

评论回复
| 2020-2-24 21:40 | 显示全部楼层
看代码,应该是去掉最大值和最小值,然后取了个平均,不过这样提升的精度需要实际测试的。

使用特权

评论回复
 楼主 | 2020-2-25 10:02 | 显示全部楼层
piteqiu 发表于 2020-2-24 21:40
看代码,应该是去掉最大值和最小值,然后取了个平均,不过这样提升的精度需要实际测试的。 ...

代码主要是引入了内部的校准。求平均值是因为采样都会有误差,通过平均值可以缩小误差

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表