采用如下的NTC测温电路进行温度测量。
将电源电压经过固定电阻以及NTC电阻分压送入单片机进行A/D转换之后。
单片机程序从A/D模块读到数值,根据其与真实温度之间的关系,将其转换为真实温度。

NTC测温电路原理图
NTC电阻Rt的阻值与温度的关系为:
NTC的电阻阻值与温度的关系
以12位的A/D为例,转换得到的数值AD与电阻Rt的关系为:
A/D值与电阻的关系
大多数工程师根据这两个公式自然而然推导出了温度与A/D值之间的关系式。
温度求解公式
得到这个公式以后,工程师很高兴,高中所学的数学知识总算是没有还给老师。
高兴之余,就埋头敲了以下的C语言,所幸C语言的math库支持浮点数运算,还能做倒数和对数运算。
#define B 3950.0 //温度系数
#define TN 298.15 //额定温度(绝对温度加常温:273.15+25)
#define RN 10 // 额定阻值(绝对温度时的电阻值10k)
#define BaseVol 3.30 //ADC基准电压
float Get_Tempture(U16 adc)
{
float RV,RT,Tmp;
RV=BaseVol/4096.0(float)adc;//ADC为10位ADC,求出NTC电压:RV=ADCValu/1024BaseVoltag
RT=RV10/(BaseVol-RV);//求出当前温度阻值 (BaseVoltage-RV)/R16=RV/RT;
Tmp=1/(1/TN+(log(RT/RN)/B))-273.15; //RT = RN expB(1/T-1/TN)
return Tmp;
}
编译之后,并没有报错,烧写到单片机,温度显示也很正确。
然后,产品就出货了。
到了客户手上,时不时出现了按键响应慢、通信出现误码等问题。
大部分单片机没有硬件浮点运算器,做浮点数运算时会花费大量的时间。
而对数运算也多转换为幂级数展开进行运算,涉及到大量的乘法运算。
即使cortex-M3系列处理器有单指令周期的乘法器,上述运行可以也要几毫秒时间。
对于没有硬件乘法器的单片机,比如PIC16系列的单片机,以及几毛钱一片的OTP的单片机,做上述运算估计得耗费几十秒时间。
大部分程序员编写代码时没有时间片以及分时处理的概念,一个耗时操作闭着眼晴就执行到底。
到最后主程序忙不过来了,就把需要即时处理的代码一股脑放在中断程序里面处理。
最后,整个软件时间性差,时不时会出现丢数据,无响应等情况。
编写软件一定要结合平台考虑时间复杂度和空间复杂度,
必须要根据产品的功能合理安排时间和空间,以便做到最佳性能。
对于A/D值到温度的转换,最快速的方法是通过查表加分段线性插值处理。
我们可以把 0度-100度对应的AD值存到一个10016bit的const 表。
将得到的A/D数值从这个表中找到对应的区域。
在这个区域进行线性插值,得到相应的数值。代码如下:
#define AD_TEMP_RANGE_NUM 101
#define AD_TEMP_VALUE_MAX 3739
#define AD_TEMP_VALUE_MIN 1241
#define AD_TEMP_TEMP_MAX 1000
#define AD_TEMP_TEMP_MIN 0
///10K B= 3980
const U16 adrange[AD_TEMP_RANGE_NUM] =
{
3740,
3723,
3705,
3687,
3668,
3648,
3628,
3607,
3585,
3563,
3541,
3517,
3493,
3469,
3444,
3418,
3392,
3365,
3338,
3310,
3282,
3253,
3224,
3194,
3164,
3134,
3103,
3072,
3040,
3009,
2976,
2944,
2912,
2879,
2846,
2813,
2780,
2746,
2713,
2680,
2647,
2613,
2580,
2547,
2514,
2481,
2448,
2416,
2384,
2352,
2320,
2288,
2257,
2226,
2195,
2165,
2135,
2106,
2077,
2048,
2020,
1992,
1964,
1937,
1910,
1884,
1858,
1833,
1808,
1784,
1760,
1737,
1714,
1691,
1669,
1647,
1626,
1605,
1585,
1565,
1546,
1527,
1508,
1490,
1472,
1455,
1438,
1422,
1406,
1390,
1374,
1360,
1345,
1331,
1317,
1303,
1290,
1277,
1265,
1252,
1240
};
U16 temp;
advalue = AD_GET_VAL(0);
if(advalue >= AD_TEMP_VALUE_MAX)
{
temp = AD_TEMP_TEMP_MIN;
}
else if(advalue < AD_TEMP_VALUE_MIN)
{
temp = AD_TEMP_TEMP_MAX;
}
else
{
for(j = 0; j< (AD_TEMP_RANGE_NUM - 1); j++)
{
if((advalue[i] < adrange[j])
&& (advalue[i] >= adrange[j + 1]))
{
uchDiff = adrange[j] - adrange[j + 1];
uchData = adrange[j] - advalue[i];
uiData = uchData 10;
uiData = uiData + (uchDiff >> 1);
uchData = uiData / uchDiff;
uiData = j 10;
temp= uiData + uchData;
break;
}
}
}
带个转换过程在72MHz的主频时,耗时大概在几个us。
该程序可以进一步优化,改为二分法查找。