基于RC充放电的NTC热敏电阻测温试验
- 格式:doc
- 大小:117.00 KB
- 文档页数:7
基于RC充放电的NTC热敏电阻测温试验 利用单片机I/O口使用RC充放电原理进行温度测量,前提是单片机的I/O口应有高阻功能,若为AT89C51/AT89C2051系列单片机其I/O口为准双向口无高阻功能;所以,需加一只三极管进行高阻功能扩展。下图中RK为10K精密电阻(精度为1%),RT为10K精度为1%的NTC热敏电阻,C1为0.1uf的瓷片电容。其中电阻和电容的选择应更据单片机的时钟频率及RC充放电时间常数进行选择;选择方法是在保证RK与RT和C1之间的充放电时间常数不能大于单片机内部的定时器的最大定时时间,若无法达到要求,则需降低单片机的时钟频率。本文提供了一种电路非常简单,且易于实现,并且适用于几乎所有类型的单片机。其电路原理图如下所示:
图中: P1.0、P1.1和P1.2是单片机的3个I/O脚; RK为100k的精密电阻; RT为100K-精度为1%的热敏电阻; R1为100Ω的普通电阻,若单片机的I/O口灌入电流大于20mA则R1可用导线代替; C1为0.1μ的瓷片电容。
其工作原理为: 1.先将P1.0、P1.1、P1.2都设为低电平输出,使C1放电至放完。 2.将P1.1、P1.2设置为输入状态,P1.0设为高电平输出,通过RK电阻对C1充电,单片机内部计时器清零并开始计时,检测P1.2口状态,当P1.2口检测为高电平时,即C1上的电压达到单片机高电平输入的门嵌电压时,单片机计时器记录下从开始充电到P1.2口转变为高电平的时间TK。 3.将P1.0、P1.1、P1.2都设为低电平输出,使C1放电至放完。 4.再将P1.0、P1.2设置为输入状态,P1.1设为高电平输出,通过RT电阻对C1充电,单片机内部计时器清零并开始计时,检测P1.2口状态,当P1.2口检测为高电平时,单片机计时器记录下从开始充电到P1.2口转变为高电平的时间TT。 5.从电容的电压公式:
可以得到:TK/RK=TT/RT,即 RT=(TT/TK)×RK 通过单片机计算得到热敏电阻RT的阻值。并通过查表法可以得到温度值。 从上面所述可以看出,该测温电路的误差来源于以下几个方面:单片机的定时器精度,RK电阻的精度,热敏电阻RT的精度,而与单片机的输出电压值、门嵌电压值、电容精度无关。因此,适当选取热敏电阻和精密电阻的精度,单片机的工作频率够高,就可以得到较好的测温精度。当单片机选用4MHz的工作频率,RK、RT均为1%精度的电阻时,温度误差可以做到小于1℃。如果P1.2具有外部上升沿中断的功能,程序可以更简单,效果更好。 本试验使用AT89C2051单片机,利用了AT89C2051的P1.0或P1.1脚无上拉电阻的特点,否则需I/O口具有高阻功能的单片机或在放电回路加入一只二极管才能实现。
原理图如下:
图2 本图使用了内部比较器 注意:电路中的P1.2与P1.3应对调连接,即P1.2控制热敏电阻充电,P1.3控制固定电阻充电。若采用比较器则比较器同相输入端的分压电阻供电应使用精密稳压电源(如TL431等),令外RC充放电回路也应采用精密稳压电源供电,否则,显示的温度值将在很大范围内跳变,这是由于电压波动造成的,可以在单片机供电电路中加一个精密稳压器件。由于AT89C2051的I/O口为准双向口无高阻态功能,所以加入三极管来实现高阻态。 图3 使用I/O口 程序如下:
/****************************************************************************************** 本程序利用I/O口的阀值电压来代替电压比较器进行RC充电时间的计算 ******************************************************************************************/
#include sbit over=P1^1; //用于检测充电电压 sbit CLK=P1^7; //MAX7219时钟信号线 sbit LD=P1^6; //数据加载线 sbit DIN=P1^5; //数据输入线 unsigned char code disp_table[]={0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b, 0x77,0x1f,0x4e,0x3d,0x01,0x00}; //非译码方式时的共阴数码管显示编码,0~9,E,o,r,d,-,息灭 unsigned int code temp_table1[]={2953,3092,3238,3392,3554,3726,3908,4099,4302,4516,4743,4983,5237, 5507,5792,6095,6416,6756,7118,7502,7910,8348,8804,9295,9818,10374,10966,11598,12272,12991,13759, 14579,15455,16392,17394,18467,19616,20847,22167,23583,25000}; //负温度查表值(-1~-40) unsigned int code temp_table2[]={2822,2697,2579,2467,2360,2259,2163,2071,1984,1901,1823,1748,1676, 1608,1543,1482,1423,1366,1313,1262,1213,1166,1122,1079,1038,1000,962,927,893,860,829,799,771,743, 717,692,668,644,622,601,580,561,542,524,507,490,474,458,444,429,416,402,390,377,366,354,343,333, 323,313,303,294,286,277,269,261}; //0~66度查表值 unsigned char code temp_table3[]={253,246,239,232,226,219,213,207,201,196,190,185,180,175,171,166, 162,157,153,149,145,142,138,134,131,128,124,121,118,115,112,110,107,104,102,99,97,95,93,90,88,86, 84,82,80,79,77,75,73,72,70,69,67,66,64,63,61,60,59,57,56,55,50}; //67~127度查表值 void w_max7219(unsigned char addr,unsigned char wdata); //向MAX7219写数据函数声明 void init_max7219(); //MAX7219初始化函数声明 void timer_ms(unsigned char tim); //毫秒级延时函数声明 void temp_ntc(); //NTC热敏电阻测温函数声明
/****************************************************************************************** 函数名称:main 函数说明:主函数 入口参数: 出口参数: 其 它: ******************************************************************************************/ main() { TMOD=0x01; //设置T0的工作模式 init_max7219(); //MAX7219初始化函数 m1: temp_ntc(); //NTC热敏电阻测温函数 goto m1; }
/****************************************************************************************** 函数名称:temp_ntc 函数说明:NTC热敏电阻测温函数 入口参数: 出口参数: 其 它: ******************************************************************************************/ void temp_ntc() { bit flag; unsigned char j,t,bw,sw,gw; unsigned int rt,temp; float c=0,a,b; for(j=0;j<10;j++) { P1=0xf1; //放电 timer_ms(5); //延时等待电放完 TH0=0x00; //定时器T0清零 TL0=0x00; P1=0xfb; //使用RK冲电 TR0=1; //启动T0计时 while(over==0); //等待P1.1口变为高电平 TR0=0; P1=0xf1; //放电 b=(TH0<<8)|TL0; //读取冲电时间 TH0=0x00; TL0=0x00; P1=0xf1; //放电 timer_ms(5); P1=0xf7; //使用热敏电阻冲电 TR0=1; while(over==0); TR0=0; a=(TH0<<8)|TL0; P1=0xf1; c=c+(a/b); //累加10测量结果 } rt=((c/10)*10)*100; //先除以10求平均值,再乘以10求传感器电阻值,并放大100倍以便查表求出温度值。 if(rt>2822) //判断热敏电阻值是否在0度以下,否则跳转并继续比较 { flag=0; //负温度,并将标志位清零 for(j=1;j<=40;j++) //查表求出温度值 { temp=temp_table1[j]; if(rt<=temp) break; //条件满足则退出循环 } if(rt!=temp) j--; t=j; //保存温度值 } else if(rt>253) //判断热敏电阻值是否在0~66度之间,否则跳转并继续比较 { flag=1; //正温度,并将标志位置1 for(j=0;j<=65;j++) { temp=temp_table2[j]; if(rt>=temp) break; } if(rt!=temp) j--; t=j; } else if(rt>50) //判断热敏电阻值是否在67~127度之间,否则为热敏电阻短路 { flag=1; for(j=0;j<=63;j++) { temp=temp_table3[j]; if(rt>=temp) break; } if(rt!=temp) j--; t=66+j; } else t=0; //热敏电阻短路时显示0 /*******正负温度显示处理程序*******/