找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4440|回复: 4
收起左侧

基于RS-485总线的单片机温控系统程序Proteus仿真设计

  [复制链接]
ID:860602 发表于 2020-12-18 23:10 | 显示全部楼层 |阅读模式
1. 采用DS18B20数字温度传感器对两处进行温度的实时测量,通过LCD1602进行显示,并通过RS-485总线上传到主机。
2. 当温度超过设定值时能够报警,同时启动相关降温设备。
3. 主机通过按键和无线遥控能够对温度报警上限值及时间进行设置。
4. 能够对重要数据进行保存。                             
二、设计方案
主机和从机选用STC89C52单片机,通过RS-485总线进行数据通信。主机采用LCD2002显示各从机的温度和当前时间,根据按键或无线遥控的输入命令对控制温度上限值、温度报警值和时间进行设置,并通过RS-485总线传递温度报警值给从机和读取从机温度。从机通过DS18B20采集现场温度,利用LCD1602进行显示,通过RS-485总线接收温度报警值,同时上传温度检测值给主机。
整个系统主要分3大块(主机、从机1和从机2)和十二个模块。(1)主机键盘部分,用来实现输入和设定温度等工作;(2)主机LCD1602显示电路;(3)主机单片机最小系统;(4)主机时钟电路;(5)主机存储电路;(6)主机继电器输出控制电路;(7)主机蜂鸣器报警电路;(8)主机RS-485通信部分;(9)从机RS-485通信部分;(10)从机单片机最小系统;(11)从机LCD1602显示部分;(12)从机温度检测电路。从机1和从机2硬件电路一样,都包括第9模块到第12模块。整个系统方案如图10-1所示。

图10-1 系统方案框图

三、硬件设计
系统原理图如图10-2和图10-3所示,对应仿真图如图10-4所示。
图10-2 主机电路原理图
图10-3 从机电路原理图
图10-4 整个系统仿真图
从图10-4仿真图可以看出从机1当前的温度值为42.0℃,从机2当前的温度为34.0℃,温度报警上限温度值为39.0℃,主机与从机显示温度一致,说明Proteus仿真是完全正确的。
1.主机键盘。调整按键8个,其中S2、S3、S4和S5是手动按键,分别为设置键、加键、减键、退出键。通过调整按键可以对温度上限值、时间、星期、年月日的调整状态。
2.主机LCD显示电路。主机通过LCD1602液晶显示从机1和从机2实时采集的温度值、时间和日期。
3. 主机单片机最小系统。主机单片机最小系统是电路的控制中心,主要包括单片机、时钟电路和复位电路。
4.主机时钟电路。
采用DS1302实时时钟芯片进行年、月、日、时、分、秒刷新。可以通过按键调整时间,并具有系统掉电后启用备用电池向DS1302继续供电的功能,使用户不必每次上电调整时间。
5.主机存储电路。AT24C02用于存储用户设定的温度上限值和其他重要数据。
6.主机继电器输出控制电路。当温度大于等于用户设定的上限值时,P20和P21输出低电平,通过三极管VT1和VT2驱动继电器吸合,控制电扇通风降温,同时继电器接通指示灯亮。
7.主机蜂鸣器报警电路。当温度大于等于用户设定的上限值时,主机蜂鸣器报警。

8.主机RS-485通信部分。RS-485通信芯片选用的是SN65HVD3082ED,收发使能端由主机P3.7进行控制,R2用于防止末端信号发射,J5和J6为通信接口。
9.从机RS-485通信部分。RS-485通信芯片选用的是SN65HVD3082ED,收发使能端由主机P3.7进行控制,R2用于防止末端信号发射,J2和J3为通信接口。
10. 从机单片机最小系统。主要包括单片机、时钟电路、复位电路、电源接口和LED指示、ISP下载。
11.从机LCD1602显示部分。第一行显示主机发来的温度上限值,第二行显示从机1所在位置的温度值和下限值。
12. 从机温度检测电路。通过DS18B20进行温度采集,数据端口DQ连接到单片机的P3.3。
四、软件设计
1. RS-485总线通信协议
主机STC89C52采用查询方式,从机STC89C52采用中断方式,具体协议如下:
(1)主机STC89C52发送查询地址。
(2)从机STC89C52都接收查询地址,并与本从机地址比较,若一样则发送从机地址、采集温度十位、采集温度个位、采集温度小数位和累加和校验。
(3)主机STC89C52接收数据。
(4)主机STC89C52发送温度上限报警值十位、温度上限报警值个位。
(5)从机STC89C52接收温度上限报警值命令。
(6)主机STC89C52未查询完所有的STC89C52,则返回(1)继续查询下一个从机。
(7)通信速率9600bps,数据帧格式:一位起始位,9位数据位,一位停止位,即串行口工作于方式3。
(8)主机发送从机地址和温度上限值采用奇校验(每帧数据的第8位(即D7)为奇校验位);主机接收从机发送的匹配地址和采集到的温度值时采用累加和校验。
(9)从机机接收主机发送的从机地址和温度上限值采用奇校验(每帧数据的第8位(即D7)为奇校验位);从机发送匹配地址和采集到的温度值时采用累加和校验。
2.主机程序设计
(1)主机主程序
主机主流程图如图10-5所示。当工作状态标志为1时,进入参数调整;否则进入正常工作状态。
图10-5主机主程序流程图
(2)液晶显示功能程序
图10-6  主机液晶显示界面
主机LCD1602液晶显示从机1和从机2实时采集的温度值、时间和日期。如图10-6所示。从机1温度为28.3℃,从机2温度为28.7℃,温度上限为30℃、下限为28℃,当前日期为5月16日17点47分。
(3)DS1302实时时钟功能程序
采用DS1302实时时钟芯片进行年、月、日、时、分、秒刷新。可以通过按键调整或者无线遥控调整时间,并具有系统掉电后启用备用电池向DS1302继续供电的功能,使用户不必每次上电调整时间。
(4)AT24C02 掉电存储功能程序。用于存储用户设定的温度上限值。
(5)蜂鸣器报警功能程序。当温度大于等于用户设定的上限值时,主机蜂鸣器报警。
(6)继电器输出控制程序。当温度大于等于用户设定的上限值时,P20和P21输出低电平,通过三极管VT1和VT2驱动继电器吸合,控制电扇通风降温,同时继电器接通指示灯亮。
(7) 按键键盘程序
                      图10-7  按键键盘布局
按键功能如图10-7所示,当set键按下时进入调整模式,并且可以通过set键切换进入对温度上限值、时间、星期、年月日的调整状态。当进入某种调整状态时其对应值会快速闪烁,通过up键或者down键进行调整。调整完毕后按下out键保存并退出调整模式。
(8)主机通信程序
主机通信流程图如图10-8所示。在数据发送时,采用奇校验校验;在接收数据时,使用累加和校验。
      
      图10-8 主机通信流程图       图10-9从机通信流程图
3.从机程序设计
(1)从机通信程序设计。从机通信程序流程图如图10-9所示。
(2)从机主程序设计。从机主程序流程图如图10-10所示。首先进行系统初始化,然后关中断读取DS18B20中温度值,读完温度值后,开中断,调用温度决策函数。

图10-10从机主程序流程图
五、实物照片
系统实物照片如图10-11所示。
图10-11 实物照片
六、设计制作要点
1.STC89C52单片机多机通信实现的原理。 因多机通信是在方式2和方式3下进行,因此SM2位主要用于方式2和方式3。当串行口以方式2或方式3接收时,如SM2 =1,则只有当接收到的第9位数据(RB8)为“1”,才将接收到的前8位数据送入SBUF,并置位RI产生中断请求;否则,将接收到的前8位数据丢弃。而当SM2=0时,则不论第9位数据为“0”还是为“1”,都将前8位数据装入SBUF中,并产生中断请求。
2. 单片机晶振频率建议选择11.0592MHz。
3. 通信芯片建议选择TI公司的SN65HVD3082ED,尽量不要选择MAX485(国产)。

单片机源程序如下:
  1. #include<reg52.h>  //调用52单片机库
  2. #include"1602.h"   //调用LCD1602库
  3. #include"ds18b20.h"   //调用ds18b20温度传感器
  4. #define uint unsigned int
  5. #define uchar unsigned char
  6. uchar hour,min,sec,count,hour1,hour2,  //定义小时 分钟 秒 对应的十位个位 以及 count计数
  7. sec1,sec2,min1,min2;

  8. sbit speaker=P2^1;                  //定义蜂鸣器
  9. sbit key1=P1^0;                          //最低温度设置
  10. sbit key2=P1^1;              //最高温度设置
  11. sbit key3=P1^2;       //连接切换模式的备用开关 P33和P12口短接 用于切换模式和退出报警中断


  12. sbit keyh=P1^5;  //校时
  13. sbit keym=P1^6;  //校分
  14. sbit keys=P1^7;  //校秒
  15. //定义时间按键

  16. uint  tem;                                  //定义采集温度
  17. int htem,htem2,time,time2,x,y,z,dot,dot2,maxtem,mintem;                          //定义温度十位数、个位数、小数,以及其三种模式的标记值
  18. int cnt1=1,cnt2=1,cnt3=1,cnt4=1,cnt5=1,cnt6=1,cnt7=1;                  //定义计数变量
  19. int i;
  20. uchar mode=0;                          //定义模式变量
  21. uchar code t3[]={"  H/L=0/1:     C"};    //显示调最值温度的十位
  22. uchar code t4[]={"O/D:           C"};    //显示调最值温度的个位/小数位字模
  23. uchar code table2[]={  
  24. '0','1','2','3','4','5','6','7','8','9',':'};   //显示时间的字模
  25. uchar code t5[]={"Max         . CD"};         //显示最高温度的字模
  26. uchar code t6[]={"Min         . CD"};         //显示最低温度的字模


  27. //延时函数
  28. void delay1(uint i)
  29. {
  30.         while(i--);        
  31. }



  32. //显示函数1  初始显示
  33. void display(uint dat,uchar add)
  34. {
  35. uchar bai,shi ,ge;
  36. bai=dat/100;
  37. shi=dat%100/10;
  38. ge=dat%10;                                                                                   
  39. writelcd_cmd(add);
  40. writelcd_dat(bai+0x30);
  41. writelcd_dat(shi+0x30);
  42. writelcd_cmd(add+3);
  43. writelcd_dat(ge+0x30);
  44. }

  45. void lcd_min()   //定义最小温度显示
  46. {
  47.         uchar l;
  48.         
  49. writelcd_cmd(0x38);   //初始化屏那迤粱
  50. delay(5);
  51. writelcd_cmd(0x38);
  52. delay(5);
  53. writelcd_cmd(0x38);
  54. writelcd_cmd(0x08);
  55. writelcd_cmd(0x01);
  56. writelcd_cmd(0x06);
  57. writelcd_cmd(0x0c);
  58. writelcd_cmd(0x80);
  59.         
  60.                 writelcd_cmd(0xc0);
  61.                                                 for(l=0;l<16;l++)                  //依次读取t6并显示
  62.                                                 {
  63.                                         writelcd_dat(t6[l]);
  64.                                                 }
  65.                                                 
  66.                                                 display(mintem,0xca);
  67.                                                 delay1(5000000000);   //延时显示
  68. }

  69. void lcd_max()  //定义最大温度显示
  70. {
  71.         uchar k;
  72.         writelcd_cmd(0x38);   //初始化屏幕清屏
  73. delay(5);
  74. writelcd_cmd(0x38);
  75. delay(5);
  76. writelcd_cmd(0x38);
  77. writelcd_cmd(0x08);
  78. writelcd_cmd(0x01);
  79. writelcd_cmd(0x06);
  80. writelcd_cmd(0x0c);
  81. writelcd_cmd(0x80);
  82.         writelcd_cmd(0xc0);
  83.                                                 for(k=0;k<16;k++)                  //依次读取t5并显示
  84.                                                 {
  85.                                         writelcd_dat(t5[k]);
  86.                                                 }
  87.                                                 display(maxtem,0xca);
  88.                                                 delay1(5000000000);
  89. }

  90. void write_Char(unsigned char a,unsigned char b,unsigned char dat) //显示时间程序母程序 定位
  91. {      
  92. if (b == 0)   
  93.     {      
  94.     writelcd_cmd(0x80 + a);      
  95.     }      
  96. else   
  97.     {      
  98.     writelcd_cmd(0xC0 + a);      
  99.     }         
  100. writelcd_dat(dat);   
  101. }   

  102. void display4(uchar hour1,uchar hour2,uchar min1,uchar min2,uchar sec1,uchar sec2)    //显示时间子程序  取值
  103. {     

  104.    
  105.     write_Char(4,0,table2[hour1]);                    //显示小时
  106.     write_Char(5,0,table2[hour2]);  
  107.     write_Char(6,0,table2[0x0a]);                   //显示冒号
  108.     write_Char(7,0,table2[min1]);                    //分钟
  109.     write_Char(8,0,table2[min2]);  
  110.     write_Char(9,0,table2[0x0a]);                    //显示冒号
  111.     write_Char(10,0,table2[sec1]);                    //秒
  112.     write_Char(11,0,table2[sec2]);
  113.         
  114.   
  115. }  


  116. //显示函数2  调最值温度低十位 在LCD上排显示
  117. void display2(uint dat,uchar add)
  118. {
  119. uchar bai,shi ;
  120. bai=dat/100;
  121. shi=dat%100/10;
  122. //ge=dat%10;                                                                                   
  123. writelcd_cmd(add);
  124. writelcd_dat(shi+0x30);
  125. writelcd_dat(bai+0x30);
  126. writelcd_cmd(add+3);
  127. //writelcd_dat(ge+0x30);
  128. }


  129. //显示函数3  调最值温度的个位/小数 在LCD下排显示
  130. void display3(uint dat,uchar add)
  131. {
  132. uchar ge;
  133. //bai=dat/100;
  134. //shi=dat%100/10;
  135. ge=dat%10;                                                                                   
  136. writelcd_cmd(add);
  137. //writelcd_dat(shi+0x30);
  138. //writelcd_dat(bai+0x30);
  139. //writelcd_cmd(add+3);
  140. writelcd_dat(ge+0x30);
  141. }


  142. //按键扫描函数
  143. void keyscan()
  144. {  uchar i,j;  //定义i/j
  145.    writelcd_cmd(0x80);  //显示函数表示以此显示t3字模里面的字符
  146.    for(i=0;i<16;i++)
  147.    {writelcd_dat(t3[i]);}
  148.    writelcd_cmd(0xc0);
  149.    for(j=0;j<16;j++)   //显示函数表示以此显示t4字模里面的字符
  150.    {writelcd_dat(t4[j]);}
  151.   
  152.    while(mode!=0)  //当mode不为0时
  153.    {
  154. display2(htem,0x8b);  //显示调十位        
  155. display3(time,0xca);   //显示调个位小数位
  156.                  
  157.    while(mode!=0)
  158.    {
  159.            switch(mode)  //切换模式case语句循环 5个模式 5个循环 6个变量 初始模式为0 切换后对应地方的光标闪烁
  160.            {
  161.                         
  162.            case 1:writelcd_cmd(0xc0+10);writelcd_cmd(0x0f);break;  //调个位
  163.            case 2:writelcd_cmd(0x80+11);writelcd_cmd(0x0f);break;  //调十位
  164.                  case 3:writelcd_cmd(0xc0+10);writelcd_cmd(0x0f);break;  //调小数位                                 
  165.                  case 4:lcd_max();break;                                  //显示最大温度
  166.                  case 5:lcd_min();break;  //显示最小温度
  167.            default:mode=0;break;
  168.            }
  169.                  
  170.           if(key2==0&&mode==1)  //模式为1 key2为0时 调最高位的个位
  171.           {
  172.                         delay(50);  //按键消抖
  173.             y=0;display3(y,0x80);writelcd_cmd(0xca+11);   //max one 在左上角显示0 表示调最高温度
  174.                   
  175.                   if(key2==0)
  176.                 {  
  177.                         delay(10);  //十个循环 对应0-9数字
  178.                    cnt1++;  //计数+1
  179.                    while(key2==0);
  180.                    switch(cnt1%11)  //按键到10以后清零
  181.                    {
  182.                         case 1:time=0;display3(time,0xca);writelcd_cmd(0xca+11);break;                           //在0xca的地方显示个位值 光标闪烁
  183.                   case 2:time=1;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  184.             case 3:time=2;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  185.             case 4:time=3;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  186.                         case 5:time=4;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  187.                         case 6:time=5;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  188.                         case 7:time=6;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  189.                         case 8:time=7;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  190.                         case 9:time=8;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  191.                         case 10:time=9;display3(time,0xca);writelcd_cmd(0xca+11);break;                        
  192.                         
  193.                         default:break;        
  194.                    }        
  195.                 }
  196.           }
  197.                 if(key1==0&&mode==1)  //类似 最低个位
  198.           {
  199.                         delay(50);
  200.             y=1;display3(y,0x80);writelcd_cmd(0xca+11);  //min one 在左上角显示1 表示调最低温度
  201.                   
  202.                   if(key1==0)
  203.                 {  
  204.                         delay(10);
  205.                    cnt4++;
  206.                    while(key1==0);
  207.                    switch(cnt4%11)
  208.                    {
  209.                         case 1:time2=0;display3(time2,0xca);writelcd_cmd(0xca+11);break;         
  210.                   case 2:time2=1;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  211.             case 3:time2=2;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  212.             case 4:time2=3;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  213.                         case 5:time2=4;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  214.                         case 6:time2=5;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  215.                         case 7:time2=6;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  216.                         case 8:time2=7;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  217.                         case 9:time2=8;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  218.                         case 10:time2=9;display3(time2,0xca);writelcd_cmd(0xca+11);break;                        
  219.                         
  220.                         default:break;        
  221.                    }        
  222.                 }
  223.           }
  224.           if(key2==0&&mode==2)  //最高十位
  225.           {
  226.           delay(10);
  227.                         x=00;display2(x,0x80);writelcd_cmd(0x80+11);  //max ten 在左上角显示00 表示调最高
  228.           if(key2==0)
  229.                   {
  230.                    cnt2++;
  231.                    while(key2==0);
  232.                    switch(cnt2%11)
  233.                    {
  234.                                 
  235.                     case 1:htem=00;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  236.                     case 2:htem=10;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  237.                     case 3:htem=20;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  238.                           case 4:htem=30;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  239.                     case 5:htem=40;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  240.                     case 6:htem=50;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  241.                     case 7:htem=60;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  242.                     case 8:htem=70;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  243.                     case 9:htem=80;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  244.                     case 10:htem=90;display2(htem,0x8b);writelcd_cmd(0x80+11);break;                  
  245.                                  
  246.         
  247.                                 
  248.                     default:break;
  249.                    }
  250.                   }
  251.                         

  252.           }
  253.                 if(key1==0&&mode==2)
  254.           {
  255.           delay(10);
  256.                         x=10;display2(x,0x80);writelcd_cmd(0x80+11); //min ten 在左上角显示10表示 调最低
  257.           if(key1==0)
  258.                   {
  259.                    cnt3++;
  260.                    while(key1==0);
  261.                    switch(cnt3%11)
  262.                    {
  263.                                 
  264.                     case 1:htem2=00;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                  
  265.                     case 2:htem2=10;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                  
  266.                     case 3:htem2=20;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                  
  267.                           case 4:htem2=30;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                  
  268.                     case 5:htem2=40;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                  
  269.                     case 6:htem2=50;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                  
  270.                     case 7:htem2=60;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                 
  271.                     case 8:htem2=70;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                  
  272.                     case 9:htem2=80;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                 
  273.                     case 10:htem2=90;display2(htem2,0x8b);writelcd_cmd(0x80+11);break;                 
  274.                         
  275.                                 
  276.                     default:break;
  277.                    }
  278.                   }
  279.                         

  280.           }
  281.                 if(key2==0&&mode==3)  //最高小数
  282.           {
  283.                         delay(50);
  284.                           z=00;display2(z,0x80);writelcd_cmd(0xca+11); //max dot
  285.                   
  286.                   if(key2==0)
  287.                 {  
  288.                         delay(10);
  289.                    cnt5++;
  290.                    while(key2==0);
  291.                    switch(cnt5%11)
  292.                    {
  293.                         case 1:dot=0;display3(dot,0xca);writelcd_cmd(0xca+11);break;         
  294.                   case 2:dot=1;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  295.             case 3:dot=2;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  296.             case 4:dot=3;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  297.                         case 5:dot=4;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  298.                         case 6:dot=5;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  299.                         case 7:dot=6;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  300.                         case 8:dot=7;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  301.                         case 9:dot=8;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  302.                         case 10:dot=9;display3(dot,0xca);writelcd_cmd(0xca+11);break;                        
  303.                         
  304.                         default:break;        
  305.                    }        
  306.                 }
  307.           }
  308.                 if(key1==0&&mode==3)  //最低小数
  309.           {
  310.                         delay(50);
  311.                            z=10;display2(z,0x80);writelcd_cmd(0xca+11);   //min dot
  312.                   
  313.                   if(key1==0)
  314.                 {  
  315.                         delay(10);
  316.                    cnt6++;
  317.                    while(key1==0);
  318.                    switch(cnt6%11)
  319.                    {
  320.                         case 1:dot2=0;display3(dot2,0xca);writelcd_cmd(0xca+11);break;         
  321.                   case 2:dot2=1;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  322.             case 3:dot2=2;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  323.             case 4:dot2=3;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  324.                         case 5:dot2=4;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  325.                         case 6:dot2=5;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  326.                         case 7:dot2=6;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  327.                         case 8:dot2=7;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  328.                         case 9:dot2=8;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  329.                         case 10:dot2=9;display3(dot2,0xca);writelcd_cmd(0xca+11);break;                        
  330.                         
  331.                         default:break;        
  332.                    }        
  333.                 }
  334.           }
  335.                
  336.                 if(mode==4)  //模式4 显示最大温度
  337.           {
  338.                         maxtem=htem*10+time*10+dot;
  339.                         lcd_max();                        
  340.           }
  341.                
  342.                 if(mode==5)  //最低温度
  343.           {
  344.                         mintem=htem2*10+time2*10+dot2;
  345.                         lcd_min();                    
  346.           }
  347.                
  348.    }
  349.   }
  350.   lcd_init();  //模式为0时执行LCD初始化函数
  351. }




  352. //中断初始化函数
  353. void init()
  354. {
  355.   lcd_init();                   //lcd初始化
  356.    speaker=1;  //蜂鸣器口默认高电平
  357.    mode=0;  //模式默认0
  358.    htem=80;  //最高温度默认80
  359.    time=0;
  360.         htem2=10;  //最低温度默认10
  361.         time2=0;
  362.         dot=0;
  363.         dot2=0;
  364.         EA=1;                                //总中断开启
  365.    EX1=1;                                //外部中断1允许
  366.    ET1=1;                                //定时器1允许
  367.    TMOD=0X01;                        //定时中断1,模式1
  368.    IT1=1;                                //中断1 下降沿触发
  369.    TH1=0Xee;                        //定时中断1 0.5us
  370.    TL1=0X00;
  371.          TR1=0;  //定时中断1默认关闭
  372.         
  373.           count=0;    //时间计数默认为0
  374.     hour=00;    //小时00
  375.     min=00;    //分钟00
  376.     sec=00;    //秒00
  377.      
  378.     TH0=(65536-50000)/256;    //内部中断T0初始化
  379.     TL0=(65536-50000)%256;   
  380.     TR0=1;    //内部中断T0开启
  381.     ET0=1;  
  382.         
  383. }



  384. //主函数
  385. void main()
  386. {  
  387.   P1=0xe7;     //初始P1口,P14,P13为低电平 使S1 S5 S9 S14 S15 S16变为接地的普通开关 S9与P33短接 用于切换模式和退出报警中断
  388.          init();                  //中断初始化
  389.         
  390.         

  391.         while(1)
  392.         {  
  393.                 if(mode!=0)                  //当模式不为0
  394.                 {keyscan();}                  //执行按键扫描 以及调温度的程序

  395.              else if(mode==0)                  //模式为0时
  396.                 {
  397.                                 delay(100);
  398.                     tmpchange();                  //在ds18b20取数据
  399.                         tem=tmp();                         //温度值获取 为整数 且小数位实际上是个位 如35.5摄氏度对应的值是355
  400.                         
  401.         if(keyh==0)                 //当S14闭合时 实现小时加一  
  402.         {  
  403.             delay(5);  
  404.             if(keyh==0)  
  405.             {     
  406.                 if(hour!=23)    hour++;                    //hour=23后清零
  407.                 else            hour=0;  
  408.             }  
  409.             while(!keyh);                       //检测松手      
  410.               
  411.         }  
  412.   
  413.         if(keym==0)              //实现分钟加一  
  414.         {  
  415.             delay(5);  
  416.             if(keym==0)  
  417.             {     
  418.                 if(min!=59)                    //59后清零
  419.                 {  
  420.                     min++;  
  421.                 }  
  422.                 else   
  423.                 {  
  424.                     min=0;  
  425.                 }  
  426.             }  
  427.             while(!keym);       //松手检测  
  428.               
  429.         }  
  430.   
  431.         if(keys==0)             //实现秒加一  
  432.         {  
  433. ……………………

  434. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
基于RS-485总线的无线遥控温控系统设计.zip (9.66 MB, 下载次数: 124)
回复

使用道具 举报

ID:417546 发表于 2020-12-19 20:00 | 显示全部楼层
好评,谢谢分享
回复

使用道具 举报

ID:285380 发表于 2021-6-7 21:08 | 显示全部楼层
多么好的例程,稍微修改能干很多事。
回复

使用道具 举报

ID:285380 发表于 2021-6-14 11:31 | 显示全部楼层
大家注意了   压缩包里面   主机.c里面1602和485的引脚定义是错的。proteus文件里面   485要删除120欧姆的电阻。
回复

使用道具 举报

ID:99525 发表于 2022-5-25 12:27 | 显示全部楼层
Proteus8.9下测试了下,485无信号,删了120欧电阻也没用,不知道楼主的proteus是哪个版本的!代码里面错误比较多,修正后重新编译了也没用。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表