基于51单片机的热敏电阻测温设计

1、设计需求及目标

具有温度上下限范围,并可以手动调整;

  1. 初始化后显示温度信息与上下限信息;

  2. 模数转换芯片使用分辨率10位以上A/D芯片;

  3. 采用液晶显示;

2、设计思路及方案

本设计以51系列单片机STC89C52为控制核心,以液晶显示模块、键盘为人机接口,负温度系数热敏电阻器(NTC)为采样传感器,实现了一个基于51单片机的热敏电阻测温设计。

3、 主要代码

#include<reg52.h>				 //头文件
#include<intrins.h>
#include"eeprom52.h"		  //调用STC89C52单片机的EEPROM控制程序
#include "math.h"
#define uchar unsigned char		 //宏定义
#define uint unsigned int		 //宏定义
#define LCD1602_dat P0			 //LCD1602的数据传输IO口


sbit LCD1602_rs=P2^5;//LCD1602命令数据控制IO
sbit LCD1602_rw=P2^6; //LCD1602读写IO控制
sbit LCD1602_e=P2^7;  //数据脉冲输入
sbit beep=P2^0;	 //蜂鸣器IO
sbit led_1=P1^5; //超上限指示灯
sbit led_2=P1^6;//超下限指示灯

sbit key_1=P3^5;  //设置按键
sbit key_2=P3^6;//加按键
sbit key_3=P3^7;//减按键


sbit TCL2543_EOC  = P1^0; 	//转换结束标志IO口
sbit TCL2543_CLK  = P1^1;	//I/O时钟输入
sbit TCL2543_ADIN = P1^2;	 //串行数据输入端
sbit TCL2543_DOUT = P1^3;  //串行数据输出端
sbit TCL2543_CS   = P1^4;	 //片选脚IO


float zhi;	//暂存读取的输入变量

int temp;	//读取DS18B20的温度数据
char temp_h,temp_l;	//温度上下限制存储变量
uchar state,ms;	   //系统设置项变量、50ms定时变量

bit s1,beep1;	//设置闪烁标志位、报警标志位

void delay(uint T)		//系统延时程序
{
	while(T--);
}

// 其中 port 为通道: 通道0:port = 0x01 通道1:port = 0x02 通道2:port = 0x04 ... 
//    片子操作文本地址    http://wenku.baidu.com/link?url=WTp8rj93fYDbqM6kYbynkqTrI5MGQFQGtgk6aDrMMdfcB0K2Q9HIrVOs-SSSCLUMOKLOS31ENJAadBSdrVMHg_YxXPYcXWC7T0rb-rINptW
uint read2543(unsigned char port) //读取TCL2543对应模拟输入口的AD数据,并返回数据 
{  
	unsigned int i;  //上电时,EOC=“1”,CS=“1” 
	uint ad_value=0;  
	TCL2543_CLK=0;   
	TCL2543_CS=0;   //使能TCL2543片选
	TCL2543_EOC=1;   
	port<<=4;   
	for(i=0;i<12;i++)      //读取12位的模拟量的数字数据
	{  
		if(TCL2543_DOUT) ad_value|=0x01;  //前次转换结果的MSB即A11位数据输出到Dout供读数  
		TCL2543_ADIN=(bit)(port&0x80);    
		TCL2543_CLK=1;    //
		_nop_();  
		_nop_();    
		_nop_();  
		TCL2543_CLK=0;    
		_nop_();    
		_nop_();  
		_nop_();  
		port=port<<1;  
		ad_value=ad_value<<1;   
	}
	TCL2543_CS=1;   //锁定片子
	ad_value=ad_value>>1;   
	return ad_value;  	//返回读取的AD值
}
/********************************************************************
* 名称 : LCD1602_write(uchar order,dat)
* 功能 : 1602写如数据函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void LCD1602_write(uchar order,dat)				  //1602 一个字节  处理
{
    LCD1602_e=0;
    LCD1602_rs=order;
    LCD1602_dat=dat;
    LCD1602_rw=0;
    LCD1602_e=1;
    delay(1);
    LCD1602_e=0;																								     
}
/********************************************************************
* 名称 : LCD1602_writebye(uchar *prointer)
* 功能 : 1602写入数据函数  指针式
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void LCD1602_writebyte(uchar *prointer)				   //1602 字符串    处理
{
    while(*prointer!='\0')
    {
        LCD1602_write(1,*prointer);
        prointer++;
    }
}
/********************************************************************
* 名称 : LCD1602_cls()
* 功能 : 初始化1602液晶 
* 输入 : 无
* 输出 : 无
***********************************************************************/
void LCD1602_cls()									 //1602 初始化
{
	LCD1602_write(0,0x01);     //1602 清屏 指令
	delay(1500);
	LCD1602_write(0,0x38);     // 功能设置 8位、5*7点阵
	delay(1500);
	LCD1602_write(0,0x0c);     //设置 光标   不显示开关、不显示光标、字符不闪烁
	LCD1602_write(0,0x06);
	LCD1602_write(0,0xd0);
	delay(1500);
}

/********************************************************************
* 名称 : show()
* 功能 : LCD1602液晶显示程序 
* 输入 : 无
* 输出 : 无
***********************************************************************/
void show()			//显示数据
{

		LCD1602_write(0,0x80);		   //显示位置设定
		LCD1602_writebyte("Temp:");		//显示当前温度值
		if(temp>=0)			 //显示温度整数部分
		{
		   	if(temp>999)LCD1602_write(1,0x30+temp/1000%10);	   
			else LCD1602_writebyte(" ");
			if(temp>99)LCD1602_write(1,0x30+temp/100%10);
			else LCD1602_writebyte(" ");
			LCD1602_write(1,0x30+temp/10%10);
			LCD1602_writebyte(".");
		   	LCD1602_write(1,0x30+temp%10);
		}else
		{
			LCD1602_writebyte("-");	  //显示温度负数部分
			if(temp*-1>99)LCD1602_write(1,0x30+(temp*-1)/10%10);
			else LCD1602_writebyte(" ");
			LCD1602_write(1,0x30+(temp*-1)%10);	
			LCD1602_writebyte(".");
		   	LCD1602_write(1,0x30+temp%10);
		}
		LCD1602_write(1,0xdf);
		LCD1602_writebyte("C  ");



	 	LCD1602_write(0,0xC0);	 //第二行显示温度上下限值
		LCD1602_writebyte("H:");
		if(state==1&&s1==1)		  //对应设置项设置时闪烁控制   //上限
		{
			LCD1602_writebyte("   ");
		}else					   //显示上限值
		{
			if(temp_h>=0)
			{
			   	if(temp_h>99)LCD1602_write(1,0x30+temp_h/100%10);
				else LCD1602_writebyte(" ");
				if(temp_h>9)LCD1602_write(1,0x30+temp_h/10%10);
				else LCD1602_writebyte(" ");
				LCD1602_write(1,0x30+temp_h%10);
			}else
			{
				LCD1602_writebyte("-");
				if(temp_h*-1>9)LCD1602_write(1,0x30+(temp_h*-1)/10%10);
				else LCD1602_writebyte(" ");
				LCD1602_write(1,0x30+(temp_h*-1)%10);	
			}
		}
		LCD1602_write(1,0xdf);
		LCD1602_writebyte("C L:");
		if(state==2&&s1==1)	  //对应设置项设置时闪烁控制   //下限
		{
			LCD1602_writebyte("   ");
		}else
		{
			if(temp_l>=0)		  //显示下限值
			{
			   	if(temp_l>99)LCD1602_write(1,0x30+temp_l/100%10);
				else LCD1602_writebyte(" ");
				if(temp_l>9)LCD1602_write(1,0x30+temp_l/10%10);
				else LCD1602_writebyte(" ");
				LCD1602_write(1,0x30+temp_l%10);
			}else
			{
				LCD1602_writebyte("-");
				if(temp_l*-1>9)LCD1602_write(1,0x30+(temp_l*-1)/10%10);
				else LCD1602_writebyte(" ");
				LCD1602_write(1,0x30+(temp_l*-1)%10);	
			}
		}
		LCD1602_write(1,0xdf);
		LCD1602_writebyte("C");
	
}

/********************************************************************
* 名称 : proc()
* 功能 : 系统指示灯与报警处理
* 输入 : 无
* 输出 : 无
***********************************************************************/
void proc()
{
	if(temp>temp_h*10)	 //如果当前温度高于上限温度
	{
		led_1=0; 	 //对应指示灯点亮
	}else			//否则  熄灭
	{
		led_1=1; 	
	}
	if(temp<temp_l*10)	//如果当前温度低于下限温度 
	{
		led_2=0;	  //对应指示灯点亮
	}else			  //否则  熄灭
	{
		led_2=1;	
	}

	if(temp>temp_h*10||temp<temp_l*10)	 //如果当前温度 值不处于  上下限温度之间  这报警标志位值1   反之  置0   
	{
		beep1=1;  //开始报警
	}else
	{
		beep1=0;  //停止报警
	}
}

/********************************************************************
* 名称 : key()
* 功能 : 系统控制按键控制检测程序
* 输入 : 无
* 输出 : 无
***********************************************************************/
void key()
{

	if(!key_1)	//判断按键是否按下
	{
		delay(888);	 //延时去抖
		if(!key_1)	//再次判断按键是否按下
		{
			state=(state+1)%3;		//切换设置项
			while(!key_1);		   //按键判断释放
		}
	}
	if(state!=0)		//如果系统非设置状态   则 
	{
		if(!key_2)		//判断按键是否按下//如果加按键按下  
		{
			delay(888);	   //延时去抖
			if(!key_2)	//再次判断按键是否按下
			{
				while(!key_2) show();  //按键判断释放
				switch(state) //判断当前设置项
				{
					case 1:				  //如果是上限设置
					if(temp_h<99)temp_h++;
					SectorErase(0x2000);	 //保存上限值
					byte_write(0x2000,temp_h);
					break;
					case 2:		     //如果是下限设置
					if(temp_h>temp_l+1)temp_l++;	
					SectorErase(0x2200);	 //保存上限值
					byte_write(0x2200,temp_l);
					break;
				}
			}
		}
		if(!key_3)	//判断按键是否按下  如果减按键按下
		{
			delay(888);	 //延时去抖
			if(!key_3)	 //再次判断按键是否按下
			{
				while(!key_3) show();  //按键判断释放
				switch(state)	 //判断当前设置项
				{
					case 1:			     //如果是上限设置
					if(temp_h>temp_l+1)temp_h--;
					SectorErase(0x2000);	 //保存上限值
					byte_write(0x2000,temp_h);
					break;
					case 2:			   //如果是下限设置
					if(temp_l>-40)temp_l--;
					SectorErase(0x2200);	 //保存上限值
					byte_write(0x2200,temp_l);
					break;

				}
			}
		}
	}
}


/********************************************************************
* 名称 : float TempCalculate(float Rx,float B,float Revise,float BasicRx)
* 功能 : 根据当前热敏电阻的阻值、以及参数、通过Sin曲线求出当前系统的温度值  并返回浮点型的温度值
* 输入 : 无
* 输出 : 无
***********************************************************************/
float TempCalculate(float Rx,float B,float Revise,float BasicRx){
/*

Rx:  热敏电阻当前阻值
B:   热敏电阻参数B值
Revise:  校正温度
BasicRx:  热敏电阻25度时电阻(标称电阻数值)


返回: 摄氏度

*/  


    Rx = Rx / BasicRx;
    
    Rx = log(Rx);
    
    Rx = (Rx) / B;
    
    Rx = Rx + 0.003356;
    Rx = 1 / Rx;
    Rx = Rx - 273.13;  
    Rx = Rx + Revise;
    
    
    return Rx;
  
}
/********************************************************************
* 名称 : void main()
* 功能 : 系统主程序
* 输入 : 无
* 输出 : 无
***********************************************************************/
void main()
{
	float Rad;	 //生成运算暂存变量
	LCD1602_cls();//LCD1602初始化程序调用
	TMOD=0x01;	 //定时器0初始化配置
	TH0=0x4c;
	TL0=0x00;	 //定时初值赋值
	ET0=1;		//定时器0中断打开
	TR0=1;	   //打开定时器0
	EA=1;		//打开总中断
	temp_h=byte_read(0x2000);  //读取EEPROM中存储的温度上下限值
	temp_l=byte_read(0x2200);
	if(temp_h>99||temp_l>99||temp_l>=temp_h) //判断读取的温度上下限值是否错误  如果是  则重新赋值
	{
		temp_h=30;
		temp_l=10;
	}
	while(1)
	{
		zhi=(float)read2543(0)/819.0;  //计算电压值
		Rad=zhi/((5.0-zhi)/10000.0);   //计算热敏电阻当前阻值
		temp=(int)((temp * 0.5) + (TempCalculate(Rad,3950.0,0,10000.0) * 0.5)*10);//求出当前系统的当前温度
		show();		 //显示函数
		key();		 //按键处理程序
		proc();		 //超限处理程序
	}
}

/********************************************************************
* 名称 : void UART_1() interrupt 1 
* 功能 : 定时器0中断服务程序
* 输入 : 无
* 输出 : 无
***********************************************************************/
void UART_1() interrupt 1 
{
	TH0=0x4c;	//重新赋值
	TL0=0x00;
	ms++;	  //50ms定时变量计时
	if(ms%5==0)	  //区分250ms定时
	{
		s1=!s1;		//闪烁标志位切换
		if(beep1==1) beep=!beep;  //判断报警标志位是否报警   
		else	beep=1;
	}

	if(ms>19)	//1s定时
	{
		ms=0;		
	}
} 

完整资料:

https://market.m.taobao.com/app/idleFish-F2e/widle-taobao-rax/page-detail?wh_weex=true&wx_navbar_transparent=true&id=614761731864&ut_sk=1.WUpxx7gpwUoDAMmnnrBIzAno_12431167_1585215931516.Copy.detail.614761731864.1828622527&forceFlush=1

发布了23 篇原创文章 · 获赞 7 · 访问量 326

猜你喜欢

转载自blog.csdn.net/weixin_41017942/article/details/105123920