找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8020|回复: 12
打印 上一主题 下一主题
收起左侧

51单片机温控系统程序(电机模拟风扇 可调上下限)Proteus仿真 DS18B20+LCD1602显示

  [复制链接]
跳转到指定楼层
楼主
本文是基于STC89C52单片机的温度控制系统,主要由主控模块、显示模块及外围电路几个部分组成。
通过DS18B20检测外部温度,通过LCD1602显示,按键可调节上下限。当温度超过上限或低于下限,蜂鸣器均会报警。当温度超过上限时,电机会开始工作,模拟风扇,起到降温作用。LED灯电路模拟家用电灯,由两个开关对其进行控制。
该温控系统可以模拟简易智能家居系统,希望可以给各位有所帮助,本人能力有限,做的较为简单,如果做的不好,或者存在错误,还请指出,谢谢啦。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)



整体电路仿真




温度未超上下限,电机不工作,蜂鸣器不报警


Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)


温度超过上限,电机工作,蜂鸣器报警(视频无法上传,见谅)

单片机代码如下:
  1. #include<reg52.h>
  2. #include"stdio.h"

  3. #define uint unsigned int
  4. #define uchar unsigned char

  5. typedef unsigned char uint8;
  6. typedef unsigned int uint16;

  7. sbit beep = P1^7;  //定义蜂鸣器IO口

  8. sbit LED1 = P1^0;  //定义灯IO口
  9. sbit LED2 = P1^1;
  10. sbit k1 = P1^2;  //定义灯开关IO口
  11. sbit k2 = P1^3;

  12. sbit MOTOR = P1^4;  //定义电机
  13. sbit BUTTON_RUN = P1^5;  //定义电机启动按钮
  14. sbit BUTTON_STOP = P1^6;  //定义电机关闭按钮

  15. sbit RS = P2^7;
  16. sbit RW = P2^6;
  17. sbit EN = P2^5;
  18. sbit K1 = P2^0;
  19. sbit K2 = P2^1;  //加
  20. sbit K3 = P2^2;  //减
  21. sbit DQ = P2^3;  //DS18B20数据端

  22. //void delay(uint xms);
  23. void motor_run();
  24. void motor_stop();

  25. void LED1_SWITCH();
  26. void LED2_SWITCH();

  27. void init();

  28. void delay(uint16 time);
  29. void lcd_init();  //LCD1602初始化
  30. void lcd_order(uint8 date);  //向LCD1602写一个指令
  31. void lcd_data(uint8 date);  //向LCD1602写一个指令
  32. void write_1602(uint8 add,uint8 daa);  //写数据

  33. void display();  //显示温度

  34. uint8 DS18B20_init();  //DS18B20初始化
  35. void DS18B20_write(uint8 date);  //向DS18B20中写入一个数据
  36. uint8 DS18B20_read();  //从DS18B20中读一个数据并返回
  37. void DS18B20_check();  //启动DS18B20进行温度采集,并返回当前温度

  38. void KEY();  //修改报警范围

  39. long tmp = 0;  //存储温度值
  40. long t_h = 37,t_l = 10;  //温度上限 温度下限

  41. bit tmp_hb = 0;  tmp_lb = 0;  //温度上下限调节指示变量

  42. void judge();  //判断报警

  43. uint8 hodometer[] = "  H:00   L:00  ";
  44. uint8 temp[]=           "  wendu:00.00   ";
  45. uint16 ji = 0;
  46. uint8 ku = 0;  //标志位

  47. void main()
  48. {
  49.         init();
  50.         lcd_init();  //LCD1602初始化
  51.         DS18B20_init();  //DS18B20初始化
  52.         DS18B20_write(0xcc);  //跳过序列号
  53.         DS18B20_write(0x44);  //启动温度转换
  54.         write_1602(4,t_h);
  55.         write_1602(12,t_l);
  56.         while(1)
  57.         {               
  58.                 LED1_SWITCH();
  59.                 LED2_SWITCH();
  60.                 motor_run();
  61.                 motor_stop();
  62.                 DS18B20_check();  //从DS18B20中读取温度
  63.                 display();
  64.                 KEY();
  65.                 judge();
  66.         }
  67. }

  68. void write_1602(uint8 add,uint8 daa)
  69. {
  70.         lcd_order(0x80+add);
  71.         lcd_data(0x30+daa/10);
  72.         lcd_data(0x30+daa%10);
  73. }

  74. void judge()  //判断是否在报警范围
  75. {
  76.         if(tmp<(t_l*1000)||tmp>(t_h*1000)&&t_l>=0)
  77.         {
  78.                 beep = 0;
  79.                 delay(10);
  80.                 MOTOR = 1;
  81.         }
  82.         else if(t_l<0&&tmp>(t_h*1000))
  83.         {
  84.                 beep = 1;
  85.                 MOTOR = 0;
  86.         }
  87.         else
  88.         {
  89.                 beep = 1;
  90.                 MOTOR = 0;
  91.         }
  92. }

  93. void KEY()
  94. {
  95.         uint8 jj;
  96.         uint8 i = 0;
  97.         beep = 1;
  98.         if(K1==0)
  99.         {
  100.                 while(!K1);
  101.                 while(1)
  102.                 {
  103.                         lcd_order(0x0f);  //开启光标显示
  104.                         lcd_order(0x80+5);  //光标显示位置
  105.                         if(K2==0)  //判断加按键按下
  106.                         {
  107.                                 while(K2==0);  //等待按键释放
  108.                                         t_h++;  //温度上限加1
  109.                                         write_1602(4,t_h);  //显示温度上限
  110.                         }
  111.                         if(K3==0)  //判断减按键按下
  112.                         {
  113.                                 while(K3==0);  //等待按键释放
  114.                                 if(t_h>t_l)  //判断温度上限大于温度下限
  115.                                         t_h--;
  116.                                 write_1602(4,t_h);  //显示温度上限
  117.                         }
  118.                         if(K1==0)
  119.                         {
  120.                                 while(K1==0);
  121.                                 while(1)
  122.                                 {
  123.                                         lcd_order(0x0f);
  124.                                         lcd_order(0x80+13);
  125.                                         if(K2==0)
  126.                                         {
  127.                                                 while(K2==0);
  128.                                                 if(t_l<t_h&&t_l>=0)
  129.                                                 {
  130.                                                         lcd_order(0x80+11);
  131.                                                         lcd_data(' ');
  132.                                                         t_l++;
  133.                                                         write_1602(12,t_l);
  134.                                                 }
  135.                                                 else
  136.                                                 {
  137.                                                         t_l++;
  138.                                                         jj =~ t_l;
  139.                                                         write_1602(12,jj);
  140.                                                 }
  141.                                         }
  142.                                         if(K3==0)
  143.                                         {
  144.                                                 while(K3==0);
  145.                                                 if(t_l>(-50))
  146.                                                 {
  147.                                                         t_l--;
  148.                                                         if(t_l<0)
  149.                                                                 jj =~ t_l;
  150.                                                 }
  151.                                                 if(t_l>=0)
  152.                                                 {
  153.                                                         lcd_order(0x80+11);
  154.                                                         lcd_data(' ');
  155.                                                         write_1602(12,t_l);
  156.                                                 }
  157.                                                 if(t_l<0)
  158.                                                 {
  159.                                                         write_1602(12,jj);
  160.                                                         lcd_order(0x80+11);
  161.                                                         lcd_data('-');
  162.                                                 }
  163.                                         }
  164.                                         if(K1==0)
  165.                                         {
  166.                                                 while(K1==0);
  167.                                                 goto loop;
  168.                                         }
  169.                                 }
  170.                         }
  171.                 }
  172.         }
  173.         loop:beep = 1;
  174. }

  175. //void delay(uint xms)  //延时
  176. //{
  177. //        uint i,j;
  178. //        for(i=xms;i>0;i--)
  179. //                for(j=110;j>0;j--) ;
  180. //}

  181. void delay(uint16 time)
  182. {
  183.         while(time--);
  184. }

  185. void lcd_init()
  186. {
  187.         uint8 i;
  188.         RW = 0;
  189.         lcd_order(0x38);  //设置显示光标功能
  190.         delay(100);
  191.         lcd_order(0x0e);  //显示开及光标设置
  192.         delay(100);
  193.         lcd_order(0x06);  //显示光标移动设置
  194.         delay(100);
  195.         lcd_order(0x01);  //显示清屏
  196.         delay(100);
  197.         lcd_order(0x80);
  198.         for(i=0;i<16;i++)
  199.                 lcd_data(hodometer[i]);
  200. }

  201. void lcd_order(uint8 date)  //LCD1602写指令
  202. {
  203.         RS = 0;  //选择写指令
  204.         RW = 0;  //使能初始化
  205.         P0 = date;  //发送指令
  206.         EN = 1;  //开使能
  207.         delay(100);  //延时
  208.         EN = 0;  //关使能
  209. }

  210. void lcd_data(uint8 date)  //LCD1602写数据
  211. {
  212.         RS = 1;  //选择写数据
  213.         RW = 0;  //使能初始化
  214.         P0 = date;  //发送指令
  215.         EN = 1;  //开使能
  216.         delay(100);  //延时
  217.         EN = 0;  //关使能
  218. }

  219. uint8 DS18B20_init()
  220. {
  221.         uint8 ans;
  222.         DQ = 1;
  223.         delay(1);
  224.         DQ = 0;
  225.         delay(100);
  226.         DQ = 1;
  227.         delay(6);
  228.         ans = DQ;
  229.         delay(100);
  230.         if(!ans)
  231.                 return 1;
  232.         else
  233.                 return 0;
  234. }

  235. void DS18B20_write(uint8 date)
  236. {
  237.         uint8 i;
  238.         DQ = 1;
  239.         delay(1);
  240.         for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位发送出来
  241.         {
  242.                 DQ = 0;
  243.                 if(date&0x01)  //从低到高取出数据的每位
  244.                         DQ = 1;
  245.                 else
  246.                         DQ = 0;
  247.                 delay(10);
  248.                 DQ = 1;
  249.                 date >>= 1;
  250.                 delay(1);
  251.         }
  252. }

  253. uint8 DS18B20_read()
  254. {
  255.         uint8 i,date = 0;
  256.         DQ = 1;  //释放总线
  257.         delay(1);
  258.         for(i=0;i<8;i++)  //根据时序将数据从低到高一位一位接收
  259.         {
  260.                 DQ = 0;
  261.                 date >>= 1;
  262.                 DQ = 1;
  263.                 if(DQ)
  264.                         date |= 0x80;  //将data的一位置1
  265.                 delay(8);
  266.                 DQ = 1;
  267.                 delay(1);
  268.         }
  269.         return date;  //返回读出的数
  270. }

  271. void DS18B20_check()
  272. {
  273.         uint8 date1,date2;
  274.         float ta;
  275.         if(DS18B20_init())
  276.         {
  277.                 DS18B20_write(0xcc);  //跳过序列号
  278.                 DS18B20_write(0x44);  //启动温度转换
  279.                 DS18B20_init();  //复位
  280.                 DS18B20_write(0xcc);  //跳过序列号
  281.                 DS18B20_write(0xbe);  //启动读取温度
  282.                 date1 = DS18B20_read();  //读取两个温度字节
  283.                 date2 = DS18B20_read();
  284.                 tmp = date2;
  285.                 tmp <<= 8;
  286.                 tmp = tmp|date1;
  287.                 ta = tmp*0.0625;
  288.                 tmp = ta*1000;
  289.         }
  290. }

  291. void display()
  292. {
  293.         uint8 i;
  294.         temp[8] = 0x30+tmp/10000;
  295.         temp[9] = 0x30+tmp/1000%10;
  296.         temp[11] = 0x30+tmp/100%10;
  297.         temp[12] = 0x30+tmp/10%10;
  298.         temp[13] = 0x30+tmp%10;
  299.         lcd_order(0x80+0x40);
  300.         for(i=0;i<16;i++)
  301.                 lcd_data(temp[i]) ;
  302. }

  303. void init()  //初始化函数
  304. {
  305.         BUTTON_RUN = 1;  
  306.         BUTTON_STOP = 1;
  307.         MOTOR = 0;
  308.         beep = 0;
  309.         delay(50);
  310. }

  311. void motor_run()  //打开电机
  312. {
  313.         if(BUTTON_RUN==0)
  314.         {
  315.                 delay(10);
  316.                 if(BUTTON_RUN==0)
  317.                 {
  318.                         while(1)
  319.                         {
  320.                                 MOTOR = 1;
  321.                                 if(BUTTON_STOP==0)
  322.                                 {
  323.                                         delay(5);
  324.                                         if(BUTTON_STOP==0)
  325.                                         {
  326.                                                 break;
  327.                                         }
  328.                                 }
  329.                         }
  330.                 }
  331.         }
  332. }

  333. void motor_stop()  //关闭电机
  334. {
  335.         if(BUTTON_STOP==0)
  336.         {
  337.                 delay(10);
  338.                 if(BUTTON_STOP==0)
  339.                 {
  340.                                 MOTOR = 0;
  341.                 }
  342.         }
  343. }

  344. void LED1_SWITCH()  //LED1开关
  345. {
  346.         if(k1==0)
  347.                 LED1 = 0;
  348.         else if(k1==1)
  349.                 LED1 = 1;
  350. }

  351. void LED2_SWITCH()  //LED2开关
  352. {
  353.         if(k2==0)
  354.                 LED2 = 0;
  355.         else if(k2==1)
  356.                 LED2 = 1;
  357. }




复制代码

如果写的不好,还请见谅
文件里的原理图可能并不完全适配,还请各位仔细检查,谢谢啦

我的公众号:HFrankie
我同样会在上面发布单片机相关内容,还请各位朋友、大佬,可以关注关注,如果我写的有问题,或者有什么建议都可以提醒我,谢谢啦

Keil代码+原理图PCB+Proteus仿真下载:
TemperatureControl.7z (1009.76 KB, 下载次数: 628)

评分

参与人数 2黑币 +80 收起 理由
huangyuxin + 30
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏30 分享淘帖 顶8 踩
回复

使用道具 举报

沙发
ID:1038361 发表于 2022-7-5 09:03 | 只看该作者
作者关于这篇温控实验有没有上实验箱
回复

使用道具 举报

板凳
ID:1038361 发表于 2022-7-5 10:16 | 只看该作者
博主能烧录吗
回复

使用道具 举报

地板
ID:1054486 发表于 2022-11-28 20:52 | 只看该作者
感谢博主分享挺好
回复

使用道具 举报

5#
ID:1019544 发表于 2022-11-30 17:32 | 只看该作者
感谢楼主,真的是太棒了
回复

使用道具 举报

6#
ID:1049969 发表于 2022-12-11 20:11 | 只看该作者
不愧是你  多谢楼主
回复

使用道具 举报

7#
ID:824664 发表于 2023-3-14 08:55 | 只看该作者
谢谢分享,实验学习,很有参考价值、
回复

使用道具 举报

8#
ID:1067614 发表于 2023-3-30 12:44 | 只看该作者
为什么蜂鸣器在温度低于37度时还会断断续续报警呢?
回复

使用道具 举报

9#
ID:81441 发表于 2023-4-2 15:05 | 只看该作者
感谢分享,可以仿真,实验板上也能正常运行!
回复

使用道具 举报

10#
ID:1096137 发表于 2023-10-18 16:45 | 只看该作者
这个好,很仔细
回复

使用道具 举报

11#
ID:1112098 发表于 2024-3-27 23:45 | 只看该作者
请问为什么我改了一下引脚,就有错误了
回复

使用道具 举报

12#
ID:1115400 发表于 2024-4-6 10:42 | 只看该作者
为什么我的仿真在38度一下电机还是再转
回复

使用道具 举报

13#
ID:1115568 发表于 2024-4-6 19:44 | 只看该作者

感谢楼主,真的是太棒了,不哦错
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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