logo资料库

基于RC充放电的NTC热敏电阻测温试验.doc

第1页 / 共7页
第2页 / 共7页
第3页 / 共7页
第4页 / 共7页
第5页 / 共7页
第6页 / 共7页
第7页 / 共7页
资料共7页,全文预览结束
基于 RC 充放电的 NTC 热敏电阻测温试验 利用单片机 I/O 口使用 RC 充放电原理进行温度测量,前提是单片机的 I/O 口应有高阻功能,若为 AT89C5 1/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 充电时间的计算 ******************************************************************************************/ //用于检测充电电压 //MAX7219 时钟信号线 //数据加载线 //数据输入线 #include sbit over=P1^1; sbit CLK=P1^7; 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}; 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}; 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, //非译码方式时的共阴数码管显示编码,0~9,E,o,r,d,-,息灭 //负温度查表值(-1~-40)
//0~66 度查表值 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}; 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}; void w_max7219(unsigned char addr,unsigned char wdata); void init_max7219(); void timer_ms(unsigned char tim); void temp_ntc(); //向 MAX7219 写数据函数声明 //NTC 热敏电阻测温函数声明 //MAX7219 初始化函数声明 //毫秒级延时函数声明 //67~127 度查表值 /****************************************************************************************** 函数名称:main 函数说明:主函数 入口参数: 出口参数: 其 它: ******************************************************************************************/ main() { TMOD=0x01; init_max7219(); temp_ntc(); goto m1; //设置 T0 的工作模式 //MAX7219 初始化函数 //NTC 热敏电阻测温函数 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++) { //延时等待电放完 //定时器 T0 清零 //使用 RK 冲电 //启动 T0 计时 //等待 P1.1 口变为高电平 //放电 P1=0xf1; timer_ms(5); TH0=0x00; TL0=0x00; P1=0xfb; TR0=1; while(over==0); 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; if(rt>2822) { //先除以 10 求平均值,再乘以 10 求传感器电阻值,并放大 100 倍以便查表求出温度值。 //判断热敏电阻值是否在 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 度之间,否则跳转并继续比较 //正温度,并将标志位置 1 flag=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
if(flag==1) { //正温度 bw=t/100; sw=(t%100)/10; gw=(t%100)%10; if(bw==0) { //取出显示用的百位数据 //取出显示用的十位数据 //取出显示用的个位数据 //判断百位和十位是否为 0,是则不显示 bw=0x0f; if(sw==0) sw=0x0f; //写入使 LED 熄灭的段码 } } else { //负温度 bw=0x0e; sw=t/10; gw=t%10; if(sw==0) { //百位显示负号 //取出显示用的十位数据 //取出显示用的个位数据 //判断十位是否为 0,是则百位不显示,十位显示负号 sw=0x0e; bw=0x0f; //"-" //熄灭 } } w_max7219(0x01,disp_table[bw]); w_max7219(0x02,disp_table[sw]); w_max7219(0x03,disp_table[gw]); } //向 MAX7219 第一位写显示数据,从左起 //向 MAX7219 第二位写显示数据 //向 MAX7219 第三位写显示数据 /********************************************************************************************** 函数名称:init_max7219 函数功能:MAX7219 初始化 入口参数: 出口参数: 其 它: **********************************************************************************************/ void init_max7219() { w_max7219(0x0a,0x07); w_max7219(0x0b,0x02); w_max7219(0x09,0x00); w_max7219(0x0c,0x01); w_max7219(0x0f,0x00); timer_ms(2); } //显示亮度,取值范围 0~f //8 位扫描显示,取值范围 0~0x07 //译码方式,0x00 为不译码,0xff 为译码 //操作方式,0x00 为低功耗模式,0x01 为正常操作模式 //显示状态,0x00 为正常显示,0x01 为显示测试 /********************************************************************************************* 函数名称:w_max7219 函数功能:向 MAX7219 写入数据 入口参数:addr MAX7219 内部寄存器地址,wdata 写入内部寄存器的操作数值 出口参数:
它: 其 *********************************************************************************************/ void w_max7219(unsigned char addr,unsigned char wdata) { unsigned char temp,i=1,j,k; LD=0; while(i<16) { //先写入 MAX7219 内部寄存器地址,再向内部寄存器写入操作数值 if(i<8) temp=addr; else temp=wdata; for(j=0;j<8;j++) { //先发送数据的最高位 //时钟频率高的单片机需曾加延时时间,此处为 12MHz CLK=0; if((temp&0x80)==0x80) DIN=1; else DIN=0; for(k=5;k>0;k--); CLK=1; for(k=5;k>0;k--); temp<<=1; } i+=8; } LD=1; } /*------------------------------------------------------------------------------------------- 函数名称: timer_ms 函数说明: 1ms 延时子程序 入口参数: tim 为接收主调传来需延时的毫秒数,取值范围 1~256,定时时间 1~256ms 出口参数: 其 它: ------------------------------------------------------------------------------------------*/ void timer_ms(unsigned char tim) { unsigned char i; while(tim--) { for(i=0;i<200;i++); //延时 1ms } }
分享到:
收藏