基于单片机的恒温箱系统设计

news2024/12/29 2:44:19

  以前课设做的小温度传感系统,分享一下!

  想要直接用的可以去我资源界面下载,传送门。
  老规矩先上效果
请添加图片描述请添加图片描述

  本系统以AT89C52、DS18B20温度传感器、DS1302实时时钟、LCD1602液晶显示屏模块、蜂鸣器、固态继电器模块等元件构成一个自动恒温加热装置。
  温度控制的利用在许多的地方都有比较大的发展空间。随着现代电子信息技术的发展,许多质量好而且便宜的温度传感器被设计开发,在温度的检测控制得到了较大的利用。
  在此背景条件下,我们选择AT89C52最小系统为总控芯片设计出一个带声光报警系统的恒温箱系统,以DS18B20温度传感器和两个独立按键作为系统与外界的交互模块,可以通过独立按键模块对恒温系统的温度变化范围进行设置,当外界温度传感器的温度过低时,单片机将对其控制下的加热“热得快”进行一定占空比的供电,可以调节加热的速率,当温度过高时,会开启降温模块下的温控小风扇进行模拟降温,从而在一定程度上降低恒温箱的温度,迫使它回归正常的温度范围。

用到的元器件

  本系统以AT89C52、DS18B20温度传感器、DS1302实时时钟、LCD1602液晶显示屏模块、蜂鸣器、固态继电器模块等元件构成一个自动恒温加热装置。
  

  • AT89C52做本设计的主控芯片,主要处理来自外部信号检测,采集以及控制。

  AT89C52芯片的CPU的内核是8051,内含8K字节的的可反复擦写1000次的Flash存储器,片内含256字节的随机存取数据存储器(RAM), 相当于计算机的内存。STC89C52 是由宏晶科技公司生产的与工业标准 MCS-51 指令集和输出管脚相兼容的单片机。
(1)中央处理器(CPU)
中央处理器是单片机的核心,完成运算和控制功能。8051 的 CPU 能处理 8 位二进制数或代码。
(2)内部数据存储器(内部 RAM)
8051 芯片中共有 256 个 RAM 单元,但其中后 128 单元被专用寄存器占用,能作为寄存器供用户使用的只是前 128 单元,用于存放可读写的数据。因此通常所说的内部数据存储器就是指前 128 单元,简称内部 RAM。
(3)内部程序存储器(内部 ROM)
8051 共有 4KB 掩膜 ROM,用于存放程序、原始数据或表格,因此,称之为程序存储器,简称内部 ROM。
(4)定时/计数器
8051 共有两个 16 位的定时/计数器,以实现定时或计数功能,并以其定时或计数结果对计算机进行控制。
(5)并行 I/O 口
MCS-51 共有 4 个 8 位的 I/O 口(P0、P1、P2、P3),以实现数据的并行输入/输出。
(6)串行口
8051 单片机有一个全双工的串行口,以实现单片机和其它设备之间的串行数据传送。该串行口功能较强,既可作为全双工异步通信收发器使用,也可作为同步移位器使用。
(7)中断控制系统
8051 单片机的中断功能较强,以满足控制应用的需要。8051 共有 5 个中断源,即外中断两个,定时/计数中断两个,串行中断一个。全部中断分为高级和低级共两个优先级别。
(8) 时钟电路8051 芯片
  内部有时钟电路,但石英晶体和微调电容需外接。时钟电路为单片机产生时钟脉冲序列。系统允许的晶振频率一般为 6 MHz 和 12 MHz。
  从上述内容可以看出,MCS-51 虽然是一个单片机芯片,但作为计算机应该具有的基本部件它都包括,因此,实际上它已是一个简单的微型计算机系统了。

  • DS18B20温度传感器主要检测加热的实时温度,经单片机处理后显示在12864LCD液晶显示屏上。

  液晶(Liquid Crystal)是一种高分子材料,因为其特殊的物理、化学、光学特性,20 世纪中叶开始广泛应用在轻薄型显示器上。
  液晶显示器(Liquid Crystal Display, LCD)的主要原理是以电流刺激液晶分子产生点、线、面并配合背部灯管构成画面。为叙述简便,通常把各种液晶显示器都直接叫做液晶。
  各种型号的液晶通常是按照显示字符的行数或液晶点阵的行、列数来命名的。比如:1602 的意思是每行显示 16 个字符,一共可以显示两行;类似的命名还有 0801, 0802, 1601 等,这类液晶通常都是字符型液晶,即只能显示 ASCII 码字符,如数字、大小写字母、各种符号等。12232 液晶属于图形型液晶,她的意思是液晶由 122 列、32 行组成,即共有 122 X 32 个点来显示各种图形,我们可以通过程序控制这 122 X 32 个点中的任一个点显示或不显示。类似的命名还有12864, 19264, 192128, 320240 等,根据客户需要,厂家可以设计出任意数组合的点阵液晶。
  DDRAM地址与现实位置的对应关系:
在这里插入图片描述  读操作时序
在这里插入图片描述

  写操作时序
在这里插入图片描述
  时序参数
在这里插入图片描述

  • DS1302为实时钟芯片,做为系统显示时间用。电源电路经变压器变压后,再经7805稳压后为系统提供稳定的5V工作电压。
    在这里插入图片描述
      DS18B20数字温度计是DALLAS公司生产的1-Wire,即单总线器件,具有线路简单、体积小的特点。18B20 芯片形状同普通小功率三极管极为相似,因此用它来组成一个测温系统,线路简单,在一根通信线上,可以挂很多这样的数字温度计,十分方便。DS18B20是美国DALLAS公司新推出的一种可组网数字式温度传感器,与DS1820相似,DS18B20也能够直接读取被测物体的温度值。但是与DS1820相比,DS18B20的功能更强大些。它体积小,电压适用范围宽(35V),用户还可以通过编程实现912位的温度读数,即具有可调的温度分辨率,因此它的实用性和可靠性比同类产品更高。另外,DS18B20有多种封装可选,如TO-92, SOIC及CSP封装。
      DS18B20的内部测温电路中低温度系数振荡器的振荡频率受温度的影响很小,用于产生固定频率的脉冲信号送给减法计数器1,高温度系数振荡器随温度变化其振荡频率明显改变,所产生的信号作为减法计数器2的脉冲输入。它的内部还隐含着计数门,当计数门打开时,DS18B20就对低温度系数振荡器产生的时钟脉冲进行计数,进而完成温度测量。计数门的开启时间由高温度系数振荡器来决定,每次测量前,首先将-55℃所对应的基数分别置人减法计数器1和温度寄存器中,减法计数器1和温度寄存器被预置在-55℃所对应的一个基数值。减法计数器1对低温度系数振荡器产生的脉冲信号进行减法计数,当减法计数器1的预置值减到。时温度寄存器的值将加1,减法计数器1的预置将重新被装人,减法计数器1重新开始对低温度系数振荡器产生的脉冲信号进行计数,如此循环直到减法计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。图5-11中的斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正减法计数器的预置值,只要计数门仍未关闭就重复上述过程,直至温度寄存器值达到被测温度值,这就是DS18B20的测温原理。
    它的特点如下:
    (1)18b20 是单线温度传感器,广泛用于多点温度检测,因为他是数字信号,可直接将温度转化为串行数字信号供单片机处理,所以可以避免长距离误差;
    (2)电压范围在3.0-5.5V;测量温度在 -55°C+125°C,在10°C+85°C精度为±0.5°C
    (3)其中一种封装外形如同普通三极管,2 个电源引脚,一个信号接口,硬件 连接只需要一个10K电阻;
    (4)主要是程序部分,由于是单线采集,精度较高是采样时间比较长,接近 1S,所以重复采样的频率不能太高,不然会造成数据紊乱。

  • 固态继电器
      固态继电器(亦称固体继电器)英文名称为SolidState Relay,简称SSR。它是用半导体器件代替传统电接点作为切换装置的具有继电器特性的无触点开关器件,单相SSR为四端有源器件,其中两个输入控制端,两个输出端,输入输出间为光隔离,输入端加上直流或脉冲信号到一定电流值后,输出端就能从断态转变成通态。
      固态继电器使用场合:固态继电器目前已广泛应用于计算机外围接口装置,电炉加热恒温系统,照明舞台灯光控制系统,自动消防、保安系统等等。另外,在化工、煤矿等需防爆、防潮、防腐蚀场合中均有大量使用。
      固态继电器优缺点:固态继电器工作可靠,寿命长,无噪声,无火花,无电磁干扰,开关速度快,抗干扰能力强,且体积小,耐冲击,耐振荡,防爆、防潮、防腐蚀、能与TTL、DTL、HTL等逻辑电路兼容,以微小的控制信号达到直接驱动大电流负载。
    主要不足是存在通态压降(需相应散热措施),有断态漏电流,交直流不能通用,触点组数少。  另外,过电流、过电压及电压上升率、电流上升率等指标差。
      固态继电器按负载类型可分为交流型(AC-SSR)和直流型(DC-SSR)两类,两者不能混用。
    在这里插入图片描述

  • 蜂鸣器报警,用于系统温度超高报警用,超温指示灯当温度超出时闪烁。

  • 按键控制设置上下限温度的设置。启动/停止按键为开始启动加热和停止加热按键,每按一次可在开和关之间转换。

硬件总体设计

在这里插入图片描述

软件设计

  主程序设计,当系统上电后。系统首先进行系统初始化,完成对系统定时器的配置以及,液晶显示屏的初始化工作。然后进入循环检测控制程序,其中包括对温度的检测,以及对温度的控制,并且有LCD1602液晶实时显示当前系统信息。
在这里插入图片描述
  按键控制软件部分,是对温度上下限设置的操作。系统分为3个控制按键,分别为设置按键、加按键、减按键。“设置按键”是对当前系统状态以及当前设置项的切换。并且根据当前设置项的不同,通过“加按键”、“减按键”设置温度上、下限的值,从而控制系统温度的范围。
在这里插入图片描述  系统温度控制,是根据当前系统温度对比温度的上、下限值。从而控制系统加温及降温的控制操作,如图所示。并且通过蜂鸣器做报警提示处理,当温度超出温度上、下限时,蜂鸣器开始报警。
在这里插入图片描述
  单片机对DS18B20的访问流程是:先对DS18B20初始化,再进行ROM操作命令,最后才能对存储器操作,数据操作。
  DS18B20每一步操作都要遵循严格的工作时序和通信协议。如主机控制DS18B20完成温度转换这一过程,根据DS18B20的通讯协议,须经三个步骤:每一次读写之前都要对DS18B20进行复位,复位成功后发送一条ROM指令,最后发送RAM指令,这样才能对DS18B20进行预定的操作。
在这里插入图片描述

代码实现

#include<reg52.h>
#include<LCD1602.h>	//引用1602头文件
#include<DS18B20.h>	// 引用18B20头文件
#include<EEPROM.h>	//引用掉电存储头文件
sbit KEY1=P3^1;	   //定义按键
sbit KEY2=P3^2;	   
sbit KEY3=P3^3;	   
sbit beep=P1^4;	   //定义蜂鸣器
sbit jdq1=P1^0;	   //定义继电器1
sbit jdq2=P1^1;	   //定义继电器2
bit key2_flag=0;
bit key3_flag=0;
bit key4_flag=0;
bit key5_flag=0;
uchar xdata rec[36];
uchar sec1=0,sec2=0;	//定义按键长按延时变量
int DS;
char RH;
char RL;
uchar xdata rec_dat[16];
uchar i,j,nu;
uchar w=0;
uint tt,yy;
bit l=0;		//按键连按标志位
bit beep1=0;
void key(void);
//-------------------延时函数--------------------------
void delay(uint z)	 //延时
{
   uint x,y;
   for(x=z;x>0;x--)
      for(y=110;y>0;y--);
}
//---------------------------------------------------
void Timer0_Init() //初始化定时器  
{  

	tt=0;
	yy=0;
	TMOD=0x11;//设置定时器0为工作方式1
	TH0=(65536-10000)/256;
	TL0=(65536-10000)%256;
	TH1=(65536-10000)/256;
	TL1=(65536-10000)%256;
	EA= 1;//开总中断
	ET0=1;//开定时器0中断
	ET1=1;//开定时器1中断
	TR0=1;//启动定时器0
	TR1=1;//启动定时器1
}
//--------------掉电存储-------------------------
void write()
{
   	SectorErase(0x2000); //扇区擦除
	byte_write (0x2001,RH);
	byte_write (0x2002,RL);
}
void read()
{
	RH=byte_read(0x2001);
	RL=byte_read(0x2002);
}
//---------------------------------------------------
//--------------温度显示界面-----------------------
void show1()
{
	 LCD1602_write(0,0x80); 
	 LCD1602_writebyte("Temper:");	
	if(DS>=0)
	{
		if((DS/1000%10)>0)
			LCD1602_write(1,0x30+DS/1000%10);
		else
			LCD1602_writebyte(" "); 
		if((DS/100%10)>=0&&(DS/1000%10)>0)
			LCD1602_write(1,0x30+DS/100%10);
		else if((DS/100%10)>0&&(DS/1000%10)<=0)
			 LCD1602_write(1,0x30+DS/100%10);
		else
			LCD1602_writebyte(" "); 
		if((DS/10%10)>=0)
			LCD1602_write(1,0x30+DS/10%10);
		LCD1602_writebyte("."); 
		LCD1602_write(1,0x30+DS%10);
		LCD1602_write(1,0xdf);  
		LCD1602_writebyte("C"); 
	}		
	else if(DS*-1>=100)
	{
		LCD1602_write(0,0x87);  //从lcd1602第一行第八个位置开始显示
		LCD1602_writebyte("-");
	  	if((DS*-1)/100%10>0)
			LCD1602_write(1,0x30+(DS*-1)/100%10);
		else
			LCD1602_writebyte(" ");
		if(((DS*-1)/10%10)>=0&&((DS*-1)/100%10>0))
			LCD1602_write(1,0x30+(DS*-1)/10%10);
		else if(((DS*-1)/10%10)>0&&(DS*-1)/100%10<0)
			 	LCD1602_write(1,0x30+(DS*-1)/10%10);
		else
			LCD1602_writebyte(" ");
		LCD1602_writebyte("."); 
		LCD1602_write(1,0x30+(DS*-1)%10);
		LCD1602_write(1,0xdf);
		LCD1602_writebyte("C"); 	  
	}
	else
	{
		LCD1602_write(0,0x87);  //从lcd1602第一行第八个位置开始显示
		LCD1602_writebyte(" ");
		LCD1602_writebyte("-");
	  	LCD1602_write(1,0x30+(DS*-1)/10%10);
		LCD1602_writebyte("."); 
		LCD1602_write(1,0x30+(DS*-1)%10);
		LCD1602_write(1,0xdf);
		LCD1602_writebyte("C"); 	
	}	

	LCD1602_write(0,0x80+0x40);
	LCD1602_writebyte("H:");
	LCD1602_write(0,0x80+0x49);
	LCD1602_writebyte("L:");
	if(RH>=0)
	{
		LCD1602_write(0,0x80+0x42);
		if((RH/100%10)>0)
			LCD1602_write(1,0x30+RH/100%10);
		else
			LCD1602_writebyte(" "); 
		if((RH/10%10)>=0&&(RH/100%10)>0)
			LCD1602_write(1,0x30+RH/10%10);
		else if((RH/10%10)>0)
			LCD1602_write(1,0x30+RH/10%10);
		else
			LCD1602_writebyte(" "); 
		if((RH%10)>=0)
			LCD1602_write(1,0x30+RH%10);
	}
	if(RH<0)
	{
		LCD1602_write(0,0x80+0x42);
		LCD1602_writebyte("-"); 
		if(((RH*-1)/10%10)>0)
			LCD1602_write(1,0x30+(RH*-1)/10%10);
		else
			LCD1602_writebyte(" ");
		if(((RH*-1)/10%10)>=0&&((RH*-1)/10%10)>0)
			LCD1602_write(1,0x30+(RH*-1)%10);
		else
			LCD1602_write(1,0x30+(RH*-1)%10);  
	}
	if(RL>=0)
	{
		LCD1602_write(0,0x80+0x4b);
		if((RL/100%10)>0)
			LCD1602_write(1,0x30+RL/100%10);
		else
			LCD1602_writebyte(" "); 
		if((RL/10%10)>=0&&(RL/100%10)>0)
			LCD1602_write(1,0x30+RL/10%10);
		else if((RL/10%10)>0)
			LCD1602_write(1,0x30+RL/10%10);
		else
			LCD1602_writebyte(" "); 
		if((RL%10)>=0)
			LCD1602_write(1,0x30+RL%10);	
	}
	if(RL<0)
	{
	   	LCD1602_write(0,0x80+0x4b);
			LCD1602_writebyte("-"); 
		if(((RL*-1)/10%10)>0)
			LCD1602_write(1,0x30+(RL*-1)/10%10);
		else
			LCD1602_writebyte(" ");
		if(((RL*-1)/10%10)>=0&&((RL*-1)/10%10)>0)
			LCD1602_write(1,0x30+(RL*-1)%10);
		else
			LCD1602_write(1,0x30+(RL*-1)%10);  
	}
}		 		 
//---------------------------------------------------
//-----------------温度上下限调整------------------
void KEY()	   //温度上下限调整
{
//--------------------------------RH+-		
	w=0;
	w++;	  //W:是设置按键KEY1按下次数,KEY1按下一次W加一,按下三次后退出设置功能,退出KEY()函数,返回main()函数,执行主函数内的流程//	
	while(1)
	{
		show1();							//显示温度界面
		if(nu==1&&w==1)
		{
			LCD1602_write(0,0x80+0x42);
			LCD1602_writebyte(" "); 
			LCD1602_write(0,0x80+0x43);
			LCD1602_writebyte(" "); 
			LCD1602_write(0,0x80+0x44);
			LCD1602_writebyte(" "); 	
		}
		if(!KEY2)							//按键KEY2按下(数字加功能键)
		{
			if(key2_flag)			//按键按下标志位,只有按键松开才会置一
	  		 {
				key2_flag=0;			//清零,这样,就算按键一直按下,由于只有按键松开才会置一,所以这个函数只会执行一次
				 if( RH<125)   {RH++;} //数据加一
			}
			if(sec1==0)	   //这个变量只有在按键松开,才会一直是2,按键按下后会每隔1S减一
			 {			   //当等于0的时候,判断为长按,需要连加减
		    	if( RH<125)   {RH++;}	 //连加设定
		 	}
         key4_flag=1;  //按键按下才会置一												//温度上限RH加一		
		}
		 else  
	 	 {
		    key2_flag=1; sec1=2;   //赋值
			if(key4_flag==1) 	  //当确定按下键按下过,就执行这个函数
			 {
			   key4_flag=0;
			   write();		  //存储数据
			 }
		 }

		if(!KEY3)				   //与上述KEY2相同,不在阐述
		{
		if(key3_flag)
		{
		  key3_flag=0;
		  if( RH>(RL+1))   {RH--;}
		}
		
		if(sec2==0)
		 {
		  if( RH>(RL+1))   {RH--;}
		 }	
		  key5_flag=1;
		}
		else  
		{
		key3_flag=1; sec2=2;
		if(key5_flag==1) 
		 {
		   key5_flag=0;
		   write();	
		 }
		}
		if(KEY1==0)
		{	
			while(!KEY1);
			delay(10);
			while(!KEY1);
			w++;
			while(1)
			{
				show1();
				if(nu==1&&w==2)
				{
					LCD1602_write(0,0x80+0x4b);
					LCD1602_writebyte(" "); 
					LCD1602_write(0,0x80+0x4c);
					LCD1602_writebyte(" "); 
					LCD1602_write(0,0x80+0x4d);
					LCD1602_writebyte(" "); 
				}
					if(!KEY2)							//按键KEY2按下(数字加功能键)
				{
					if(key2_flag)			//按键按下标志位,只有按键松开才会置一
			  		 {
						key2_flag=0;			//清零,这样,就算按键一直按下,由于只有按键松开才会置一,所以这个函数只会执行一次
						 if( RL<(RH+1))   {RL++;} //数据加一
						 if(RL==RH)	   {RL--;}
					}
					if(sec1==0)	   //这个变量只有在按键松开,才会一直是2,按键按下后会每隔1S减一
					 {			   //当等于0的时候,判断为长按,需要连加减
				    	if( RL<(RH+1))   {RL++;}	 //连加设定
						if(RL==RH)	   {RL--;}
				 	}
		         key4_flag=1;  //按键按下才会置一												//温度上限RH加一		
				}
				 else  
			 	 {
				    key2_flag=1; sec1=2;   //赋值
					if(key4_flag==1) 	  //当确定按下键按下过,就执行这个函数
					 {
					   key4_flag=0;
					   write();		  //存储数据
					 }
				 }
				if(!KEY3)
				{
				if(key3_flag)
				{
				  key3_flag=0;
				  if( RL>(-55))   {RL--;}
				}
				
				if(sec2==0)
				 {
				  if( RL>(-55))   {RL--;}
				 }	
				  key5_flag=1;
				}
				else  
				{
				key3_flag=1; sec2=2;
				if(key5_flag==1) 
				 {
				   key5_flag=0;
				   write();	
				 }
				}
				if(KEY1==0)
				{	
					while(!KEY1);
					delay(10);
					while(!KEY1);
					w++;
				}
				if(w>=3)
					break;

			}
		}
		if(w>=3)
			break;
	}
	write();
}
//--------------------------------RL+-
//---------------------------------------------------
//-----------------------报警函数--------------------
void alert()
{
	if(DS<RH*10&&DS>RL*10)		 //如果当前温度高于设置最高温度RH,发光二极管点亮,蜂鸣器报警
		beep1=1;
	else			  //否则 发光二极管、蜂鸣器关闭
		beep1=0;
	if(DS<RL*10)		   // 当前温度低于设置最低温度RL,继电打开
		 jdq1=0;
	if(DS>=RH*10)		    // 当前温度高于设置最高温度RH,继电器关闭
	{
		jdq1=1;
		jdq2=0;
	}
	if(DS<RH*10)
		jdq2=1;
}
//---------------------------------------------------
//---------------------主界面------------------------
void main()
{ 
   	LCD1602_cls();   //lcd1602初始化
	Initial();		 //初始化DS18B20函数
	do
     {				 //调用读温度函数,这里是一个判断,因为温度传感器,第一次读数据会出来一个850,不是温度数据,所以滤掉这一个数据
	  DS=Temper();
     }
    while(DS==850);   
	Timer0_Init();	 //初始化定时器
	read();			 //读单片机内部EEPROM内存储的温度上下限的值
	show1();		//界面显示
//	cc=0;
//	dd=0;
//	l=0;
	if(RH<(-50)||RH>130||RL<(-50)||RL>130||RH<=RL)	 //如果从存储区读取的温度上下限RH、RL的值不对,就对它们从新赋值
	{
		RH=40;
		RL=10;
	}
	while(1)
	{
		show1();					  //打印界面
		alert();					  //进入报警程序,判断是否有触发状态
		if(KEY1==0)					  //按键一按下,进入上下限设置功能
		{	
			while(!KEY1);			 //等待按键起来
			delay(10);				 //延时消抖,可不要
			key();					 //进入按键设置
		}
	}	
}
void time_0() interrupt 1			   //定时器0
{
	TH0=(65536-10000)/256;			   //
	TL0=(65536-10000)%256;			   //重装载值100ms
	tt++;
	if(tt>=5)						   //每500ms读取一次DS18B20的值
	{						   
	  DS=Temper(); 
	}
	if(tt>=50)
	{
		tt=0;
		if(beep1==0)   beep=~beep;
	    else 		 beep=1;

		if(w==1||w==2)				  //闪烁标志位
		{
			nu=!nu;
		}
	}	 
}	 
void time1() interrupt 3				//定时器1的服务函数
{
	TH1=0x3C;
	TL1=0xb0;  
	yy++;
	if(yy>=20)						 //如果ms大于等于20,说明ms自加了20次,20*50=1000,也就是1S
	 {
	   yy=0; 						 //清零
	  if(sec1!=0) sec1--;			 //只要这两个数据不为零,都是每隔1S减一
	  if(sec2!=0) sec2--;
	 }
}#ifndef _DS18B20_H_
#define _DS18B20_H_

#define uchar unsigned char 
#define uint unsigned int


//温度IO
sbit DS1820_dat=P3^4;


void DS18B20_delay(uint T)	//短延时						   
{
	while(T--);
}

 
//初始化DS18B20函数
void Initial()			 
{
    DS1820_dat=1;
   	DS18B20_delay(8);		   
    DS1820_dat=0;
    DS18B20_delay(80);
    DS1820_dat=1;
    DS18B20_delay(15);
} 
 
void Input(uchar f)			//往DS18B20里面写数据,写一个字节
{
    uchar j;
    for (j=0;j<8;j++)
    {
        DS1820_dat=0;
        DS1820_dat=f&0x01;
        DS18B20_delay(10);
        DS1820_dat=1;
        f>>=1;
    }
}

uchar Output()		   //读取DS18B20数据,读一个字节
{
    uchar j,b;
    for (j=0;j<8;j++)
    {
        DS1820_dat=0;
        b>>=1;
        DS1820_dat=1;
        if (DS1820_dat)
        {
            b=b|0x80;
        }
        DS18B20_delay(10);
    }
    return(b);
}
int Temper()  //读取温度数据
{	  
	int Store;
	int Store_2,Store_1;
	Initial();				   //对 DS18B20 复位
	Input(0xcc);			  	//跳过 ROM
	Input(0x44);			   //启动温度转换
	Initial();				   //对 DS18B20 复位
	Input(0xcc);			   //跳过 ROM
	Input(0xbe);			   //读 RAM 命令
	Store_1=Output();		   //读温度的低字节
	Store_2=Output();	 	   //读温度的高字节	 
	Store_2=(Store_2*256)+Store_1;	   //合起来为温度的整数部分
	Store=(int) Store_2*0.625;
	return Store;
}

#endif//1602使用上比较简单,三步走,首先初始化,然后送要显示的地址,然后送显示数据即可


#ifndef _LCD1602_H_
#define _LCD1602_H_

#define uchar unsigned char 
#define uint unsigned int

#define LCD1602_dat P0	//数据并行口宏定义


sbit LCD1602_rs=P2^5;//IO 定义
sbit LCD1602_rw=P2^6;
sbit LCD1602_e=P2^7;


void LCD1602_delay(uint T)					  //延时函数
{
	while(T--);
}

/********************************************************************
* 名称 : LCD1602_write(uchar order,dat)
* 功能 : 1602写如数据函数
* 输入 : order为数据/命令切换变量 //0是命令 1是数据
*	: dat为数据/命令的发送数据
* 输出 : 无
***********************************************************************/
void LCD1602_write(uchar order,dat)				  //1602 一个字节  处理
{
    LCD1602_e=0;
    LCD1602_rs=order;
    LCD1602_dat=dat;
    LCD1602_rw=0;
    LCD1602_e=1;
    LCD1602_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 清屏 指令
	LCD1602_delay(1500);
	LCD1602_write(0,0x38);     // 功能设置 8位、5*7点阵
	LCD1602_delay(1500);
	LCD1602_write(0,0x0c);     //设置 光标   不显示开关、不显示光标、字符不闪烁
	LCD1602_write(0,0x06);
	LCD1602_write(0,0xd0);
	LCD1602_delay(1500);
}


#endif#ifndef _EEPROM52_H_
#define _EEPROM52_H_
#include <intrins.h>



//存储数据,我们用的是单片机里面自带的EEPROM,这个区域使用的流程就是
//确定使用那个扇区,然后把那个扇区数据擦除,然后写数据就行了
//读数据,直接读扇区地址
//存储区域是8位的,也就是说能够存下的最大数据是 255,而我们存的数据最大是9999,所以
//把数据拆开存   /256得到高位    %256得到低位
 
/*

例如

void memory()
 {
   	SectorErase(0x2000);
	byte_write (0x2002,pm_density_h/256);
	byte_write (0x2003,pm_density_h%256);
 }

void read_memory() 
 {
 
   pm_density_h=byte_read(0x2002)*256+byte_read(0x2003);
   if(pm_density_h>9999)
    {
	  pm_density_h=200;
	}
 }



*/






/********STC89C51扇区分布*******
第一扇区:1000H--11FF
第二扇区:1200H--13FF
第三扇区:1400H--15FF
第四扇区:1600H--17FF
第五扇区:1800H--19FF
第六扇区:1A00H--1BFF
第七扇区:1C00H--1DFF
第八扇区:1E00H--1FFF
*****************/

/********STC89C52扇区分布*******
第一扇区:2000H--21FF
第二扇区:2200H--23FF
第三扇区:2400H--25FF
第四扇区:2600H--27FF
第五扇区:2800H--29FF
第六扇区:2A00H--2BFF
第七扇区:2C00H--2DFF
第八扇区:2E00H--2FFF
*****************/
/********STC89C54扇区分布*******
第一扇区:08000H

*****************/



#define RdCommand 0x01 //定义ISP的操作命令
#define PrgCommand 0x02
#define EraseCommand 0x03 
#define Error 1
#define Ok 0
#define WaitTime 0x01 //定义CPU的等待时间
sfr ISP_DATA=0xe2;  //寄存器申明
sfr ISP_ADDRH=0xe3;
sfr ISP_ADDRL=0xe4;
sfr ISP_CMD=0xe5;
sfr ISP_TRIG=0xe6;
sfr ISP_CONTR=0xe7;

/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable(void)
{
	 EA = 0;       /* 关中断   */
	 ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
	 ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
	 ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
}
/* =============== 关闭 ISP,IAP 功能 ================== */
void ISP_IAP_disable(void)
{
	 ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
	 ISP_TRIG = 0x00;
	 EA   =   1;   /* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
void ISPgoon(void)
{
	 ISP_IAP_enable();   /* 打开 ISP,IAP 功能 */
	 ISP_TRIG = 0x46;  /* 触发ISP_IAP命令字节1 */
	 ISP_TRIG = 0xb9;  /* 触发ISP_IAP命令字节2 */
	 _nop_();
}
/* ==================== 字节读 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
	EA = 0;
	 ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */
	 ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
	 ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
	 ISP_CMD   = ISP_CMD | RdCommand; /* 写入读命令 */
	 ISPgoon();       /* 触发执行  */
	 ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
	 EA  = 1;
	 return (ISP_DATA);    /* 返回读到的数据 */
}
/* ================== 扇区擦除 ======================== */
void SectorErase(unsigned int sector_addr)
{
	 unsigned int iSectorAddr;
	 iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
	 ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
	 ISP_ADDRL = 0x00;
	 ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
	 ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
	 ISPgoon();       /* 触发执行  */
	 ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
}
/* ==================== 字节写 ======================== */
void byte_write(unsigned int byte_addr, unsigned char original_data)
{
	 EA  = 0;
//	 SectorErase(byte_addr);
	 ISP_ADDRH = (unsigned char)(byte_addr >> 8);  /* 取地址  */
	 ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
	 ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
	 ISP_CMD  = ISP_CMD | PrgCommand;  /* 写命令2 */
	 ISP_DATA = original_data;   /* 写入数据准备 */
	 ISPgoon();       /* 触发执行  */
	 ISP_IAP_disable();     /* 关闭IAP功能 */
	 EA =1;
}
		
#endif

编写不易,求个点赞!!!!!!!
“你是谁?”

“一个看帖子的人。”

“看帖子不点赞啊?”

“你点赞吗?”

“当然点了。”

“我也会点。”

“谁会把经验写在帖子里。”

“写在帖子里的那能叫经验贴?”

“上流!”
cheer!!!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/463907.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows下Qt程序打包简易流程

还记得刚工作那会儿在接触qt不久后想让编译出来的exe文件能够脱离环境运行&#xff0c;比如写个小软件能让其在其他人电脑上动起来&#xff0c;满足一下小小的虚荣心。当时好像挺麻烦的&#xff08;或许当时自己还是了解的太少&#xff09;&#xff0c;有个同事告诉了我一个办法…

NUMA详解

目录 NUMA简介 NUMA开启与关闭 查看系统是否支持 关闭方法 numactl --hardware介绍 没有安装numactl工具下查看NUMA架构节点数&#xff1a; 查看每个NUMA节点的CPU使用情况&#xff1a; 看每个NUMA节点的内存使用情况&#xff1a; 查看NUMA下指定进程的运行情况 创建…

企业如何选择一款适合自己的信息化管理系统?

信息化这个词近年来已经说“烂”了&#xff0c;在这个信息化快速发展的时代&#xff0c;企业信息化管理系统已经成为了企业发展的必要条件之一。 但是&#xff0c;随着市场上信息化产品的爆发式增长&#xff0c;企业在选择适合自己的信息化管理系统时&#xff0c;常常会感到眼…

博弈论又称对策论的入门及在军事博弈问题上的简单实战

学习知识要实时简单回顾&#xff0c;我把学习的博弈论简单梳理一下&#xff0c;方便入门与复习。 博弈论模型 博弈论简介 社会及经济的发展带来了人与人之间或团体之间的竞争及矛盾&#xff0c;应用科学的方法来解决这样的问题开始于 17 世纪的科学家&#xff0c;如 C.&#…

Etcd 可视化管理工具,GUI 客户端

Etcd Assistant——Etcd 可视化管理工具&#xff0c;GUI 客户端 下载地址&#xff1a;http://www.redisant.cn/etcd 主要功能&#xff1a; 支持多标签页&#xff0c;同时连接到多个集群以漂亮的格式显示JSON、XML、MessagePack、十六进制等数据格式浏览、创建、编辑、删除键…

blender的一些使用

导入一个glb文件 可能整体是一个模型 我是看视频 看到可以建筑模型分成了两部分&#xff08;顶面和侧面&#xff09; 然后就一直尝试 首先需要学会的是如何在blender 中修改材质 先按tab 进入编辑模式 选第三个面选择 然后选择一个面以后 选择材质 那个圆的 然后加号 新建…

IEEE旗下SCI审稿流程及状态详细解读 (附科协高质量IEEE期刊目录)~

能够成功发表一篇IEEE旗下SCI论文 (尤其是TRANS系列) 是很多电气电子工程、计算机及通信领域科研工作者的梦想。很多学者初次投稿IEEE后&#xff0c;会不停登录投稿系统查看状态&#xff0c;其实不必如此心急&#xff0c;只需掌握几个重要的时间节点&#xff0c;定期登录系统查…

想提高应用程序的用户满意度——APK体积包优化少不了

作者&#xff1a;子不语Any 前言 减少应用程序安装包的大小&#xff0c;不仅仅减少用户的网络数据流量&#xff0c;还减少了下载等待的时间。毋庸置疑&#xff0c;尽量减少程序安装包的大小是十分有必要的。 通常来说&#xff0c;减少程序安装包的大小有两条规律&#xff1a;…

springboot+vue.js高校教材教学资源平台设计与实现

基本事件流&#xff1a; 1&#xff09;用户进入用户注册界面&#xff0c;本用例开始&#xff1b; 2&#xff09;系统显示需要填写的注册信息表单&#xff1b; 3&#xff09;用户填入所有注册信息&#xff0c;点击提交后发送并审核&#xff1b; 4&#xff09;系统处理相应操作&a…

centos配置nacos集群

nacos配置集群 1.官方文档地址 https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html 2.环境准备 1.64 bit OS&#xff0c;支持 Linux/Unix/Mac/Windows。&#xff08;至少3台&#xff0c;或者通过修改端口在一台服务器 启动多个nacos进行测试&#xff09;。 2.64 bit …

*2.5 迭代法的收敛阶与加速收敛方法

学习目标&#xff1a; 了解迭代法的基本概念和原理。学习者需要理解迭代法的基本概念和原理&#xff0c;包括迭代过程、迭代格式、收敛性等基本概念。 熟练掌握迭代法的收敛阶和收敛速度。学习者需要了解迭代法的收敛阶和收敛速度&#xff0c;掌握如何计算迭代法的收敛阶和收敛…

linux系统防火墙开启放行其他端口

linux系统防火墙开启放行其他端口 弹性云主机防火墙放行对应端口 1、WDCP 系统端口放行&#xff1a; &#xff08;1&#xff09;3.2版本 登录wdcp面板后点击“安全管理”——“防火墙设置”——“快速添加”&#xff0c;如图填写端口&#xff08;协议默认都使用tcp&#xf…

Stable Diffusion-生成性AI的新范式

! 扩散模型&#xff08;Stable Diffusion)现在是生成图像的首选模型。由于扩散模型允许我们以提示( prompts)为条件生成图像&#xff0c;我们可以生成我们所选择的图像。在这些文本条件的扩散模型中&#xff0c;稳定扩散模型由于其开源性而最为著名。 在这篇文章中&#xff0…

LSTM//循环神经网络的个人理解

[TOP] LSTM/循环神经网络的理解 前言自省&#xff1a; 作为一名已经研究深度学习网络多年的研究员&#xff0c;虽曾多次浅尝LSTM这种网络&#xff0c;但是都没有花时间对其进行深刻解读。本文只谈对LSTM在逻辑思想上的理解&#xff0c;不进行技术解析。 1. 经典LSTM原理图 这…

Unlimited “使用GPT-4 ”!它来了!

备注本文末尾附录注册登录过程 平台介绍: 聊天机器Chat.fore人front.ai是一为款基于人主工智能的题聊天的机器人主平台,旨在帮菜助企,业提可以高客户服务质是量和一效率。该平款台利用自然语精言处理技术和机器致学习的算法,能够自牛动排回答客,户的问题,提供个性化的服…

TensorFlow高阶API和低阶API

TensorFlow提供了众多的API&#xff0c;简单地可以分类为高阶API和低阶API. API太多太乱也是TensorFlow被诟病的重点之一&#xff0c;可能因为Google的工程师太多了&#xff0c;社区太活跃了~当然后来Google也意识到这个问题&#xff0c;在TensorFlow 2.0中有了很大的改善。本文…

Markdown常用数学公式

1 行内公式 在两个美元符号中输入公式即可。 如$Em\times c^2$ 效果&#xff1a; E m c 2 Em\times c^2 Emc2&#xff08;注&#xff1a;\times是乘的意思&#xff09; 2 整行公式 在四个美元符号中输入公式&#xff0c;如果想要给公式后面添加编号&#xff0c;那么在公式…

windows安装mongodb6.x并设置用户名密码

安装教程 下载安装设置账号密码利用连接工具设置配置文件重新连接 下载 官网下载地址&#xff1a;点击去下载 安装 这工具很好用的&#xff0c;页面美观&#xff0c;设置账号密码也必不可少&#xff0c;推荐勾选。 设置账号密码 利用连接工具设置 必须选择一个库 use adm…

史上最全Maven教程(三)

文章目录 &#x1f525;Maven工程测试_Junit使用步骤&#x1f525;Maven工程测试_Junit结果判定&#x1f525;Maven工程测试_Before、After&#x1f525;依赖冲突调解_最短路径优先原则&#x1f525;依赖冲突调解_最先声明原则&#x1f525;依赖冲突调解_排除依赖、锁定版本 &a…

onnx手动操作001:onnx.helper

使用onnx.helper可以进行onnx的制造组装操作&#xff1a; 对象描述ValueInfoProto 对象张量名、张量的基本数据类型、张量形状算子节点信息 NodeProto算子名称(可选)、算子类型、输入和输出列表(列表元素为数值元素)GraphProto对象用张量节点和算子节点组成的计算图对象ModelP…