找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机恒温控制程序与Proteus仿真电路图 18b20采集继电器电机执行 代码注释很详细

  [复制链接]
跳转到指定楼层
楼主
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)


制作出来的恒温控制电路实物图如下:

电路原理图,我加了7805就不需要双电源了,PCB版没有
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


元件清单:
0.1uF(104)瓷片电容    1    C3
10K 碳膜电阻    4    R2, R9, R10,R5
12.00MHz 晶体振荡器    1    CRY1
1N4007 二极管    2    D1, D2
0.47uF(1uF) 电解电容    1    CE1
100uF(220uF) 电解电容    1    CE2
22pF 瓷片电容    2    C1, C2
4.7K 碳膜电阻    1    R3
1K 碳膜电阻    4    R4, R6, R7, R8
5K 电位器     1    RP1
5V DC蜂鸣器    1    BZ1
S8550三极管    1    Q1
6x6轻触按键    4    S1,S2,S3,S4
DS18B20 温度传感器    1    J1
SRD-05VDC 继电器    2    RELAY1, RELAY2
LCD1602 液晶屏    1    LCD1
IDC-3P 2.54mm 单排排针    1    J1
IDC-16P 2.54mm 单排排针    1    LCD1
S9014 三极管    2    Q2, Q3
STC89C52 单片机    1    IC1
XH-2P 2.54mm插座    1    J2
KF25-6P-7.62mm 接线座    1    J6
红色LED    2    LD2,LD3, LD4
绿色LED    1    LD1
万能板(洞洞板)    1   
锡线    1份   
连线    1份   

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uint unsigned int
  4. #define uchar unsigned char

  5. sbit DQ=P2^3;//ds18b20与单片机连接口

  6. sbit RS=P2^5;//液晶控制线接口
  7. sbit RW=P2^6;
  8. sbit EN=P2^7;



  9. uchar data disdata[5];
  10. uint tvalue,CurrentT=0;//温度值
  11. uchar tflag;//温度正负标志

  12.                
  13. #define LCD_BUS P0

  14. sbit SetKey = P2^2;//设置按键
  15. sbit UpKey  = P2^1; //加按键
  16. sbit DnKey  = P2^0;//减按键
  17. sbit BEEP   = P2^4;//蜂鸣器

  18. sbit Heat  = P1^0;//加热继电器控制
  19. sbit Cool   = P1^1;//降温继电器控制


  20. unsigned char AlarmTempLow=10,AlarmTempTop=40,Set=0;







  21. void delayms(uint ms)                 //延时xx毫秒
  22. {
  23.          uchar i;
  24.         while(ms--)
  25.         {
  26.                  for(i=0;i<120;i++);
  27.         }
  28. }



  29. void command(uint com)         //LCD写指令
  30. {
  31.    RS=0;                                  //RS为0
  32.    LCD_BUS=com;          //装载指令
  33.    delayms(5);                 //延时5ms
  34.    EN=1;                                 //LCD使能
  35.    delayms(5);                //延时5ms
  36.    EN=0;                                //LCD不使能
  37. }

  38. void write_dat(uchar dat)          //LCD写数据
  39. {
  40.    RS=1;                                        //RS为1
  41.    LCD_BUS=dat;                //装载数据
  42.    delayms(5);                         //延时5ms
  43.    EN=1;                                         //LCD使能
  44.    delayms(5);                         //延时5ms
  45.    EN=0;                                         //LCD不使能
  46. }

  47. void writestring(uchar x,uchar y,uchar *s) //LCD 写字符串
  48. {     
  49.         if (y == 0)  command(0x80 + x);     //表示第一行
  50.          else         command(0xC0 + x);      //表示第二行
  51.       
  52.          while (*s)                         //判断是否字符串的结尾
  53.          {     
  54.      write_dat( *s);    //显示当前字符
  55.                  s ++;                             //字符串地址加1
  56.          }
  57. }

  58. void writeChar(uchar x,uchar y,uchar s) //LCD 写字符串
  59. {     
  60.         if (y == 0)  command(0x80 + x);     //表示第一行
  61.          else         command(0xC0 + x);      //表示第二行
  62.       
  63.          {     
  64.      write_dat( s);    //显示当前字符
  65.          }
  66. }


  67. void LCD_Initial()                //LCD初始化
  68. {

  69.    EN=0;                                  //LCD不使能
  70.    RW=0;                                  //RW为0
  71.    command(0x38);                //发送初始化指令
  72.    command(0x0c);                //发送初始化指令
  73.    command(0x06);          //发送初始化指令
  74.    command(0x01);          //发送初始化指令
  75.    command(0x80+0x02);        //发送LCD初始位置
  76. }


  77. /*************************DS1820程序****************************/
  78. void delay_18B20(unsigned int i)//延时1微秒
  79. {
  80.    while(i--);
  81. }

  82. void ds1820rst(void)/*ds1820复位*/
  83. {
  84.         unsigned char x=0;
  85.         DQ = 1;          //DQ复位
  86.         delay_18B20(4); //延时
  87.         DQ = 0;          //DQ拉低
  88.         delay_18B20(100); //精确延时大于480us
  89.         DQ = 1;          //拉高
  90.         delay_18B20(40);
  91. }

  92. uchar ds1820rd(void)/*读数据*/
  93. {
  94.         unsigned char i=0;
  95.         unsigned char dat = 0;
  96.         for (i=8;i>0;i--)
  97.         {   
  98.                 DQ = 0; //给脉冲信号
  99.                 dat>>=1;
  100.                 DQ = 1; //给脉冲信号
  101.                 if(DQ)
  102.                 dat|=0x80;
  103.                 delay_18B20(10);
  104.         }
  105.    return(dat);
  106. }

  107. void ds1820wr(uchar wdata)/*写数据*/
  108. {
  109.         unsigned char i=0;
  110.    for (i=8; i>0; i--)  //写一个字节数据到DS18B20
  111.    {
  112.                 DQ = 0;
  113.                 DQ = wdata&0x01;  //写一位数据
  114.                 delay_18B20(10);  //延时
  115.                 DQ = 1;     //拉高数据线
  116.                 wdata>>=1;//准备下一位
  117.    }
  118. }

  119. unsigned int Read_Temperature(void)/*读取温度值并转换*/
  120. {
  121.         uchar a,b;
  122.         ds1820rst();   
  123.         ds1820wr(0xcc);//*跳过读序列号*/
  124.         ds1820wr(0x44);//*启动温度转换*/
  125.         ds1820rst();   
  126.         ds1820wr(0xcc);//*跳过读序列号*/
  127.         ds1820wr(0xbe);//*读取温度*/
  128.         a=ds1820rd();  //读取低位数据
  129.         b=ds1820rd();  //读取高位数据
  130.         tvalue=b;   
  131.         tvalue<<=8;
  132.         tvalue=tvalue|a;//取得16位数据
  133.    if(tvalue<0x0fff)   tflag=0;  //判断是否正温度
  134.    else   {tvalue=~tvalue+1;tflag=1;} //负温度,数据取反,温度标志位为1
  135.         tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
  136.         CurrentT=tvalue;//保存当前温度
  137.         return(tvalue);//返回温度值
  138. }

  139. void Display_Temperature()                //显示温度
  140. {
  141.         uchar flagdat;
  142.    disdata[0]=tvalue/1000+0x30;//百位数
  143.    disdata[1]=tvalue%1000/100+0x30;//十位数
  144.    disdata[2]=tvalue%100/10+0x30;//个位数
  145.    disdata[3]=tvalue%10+0x30;//小数位
  146.    
  147.    if(tflag==0)   flagdat=0x20;//正温度不显示符号
  148.    else   flagdat=0x2d;//负温度显示负号:-
  149.         if(tflag==1)
  150.         {
  151.                 writeChar(10,0,flagdat);//显示符号位
  152.                 writeChar(11,0,disdata[0]);//显示百位
  153.                 writeChar(12,0,disdata[1]);//显示十位
  154.                 writeChar(13,0,disdata[2]);//显示个位
  155.                 writeChar(14,0,0X2E);//显示小数点
  156.                 writeChar(15,0,disdata[3]);//显示小数位
  157.         }
  158.         else
  159.         {
  160.                 writeChar(10,0,disdata[0]);//显示百位
  161.                 writeChar(11,0,disdata[1]);//显示十位
  162.                 writeChar(12,0,disdata[2]);//显示个位
  163.                 writeChar(13,0,0X2e);//显示小数点
  164.                 writeChar(14,0,disdata[3]);//显示小数位
  165.                 writeChar(15,0,' ');//显示小数位
  166.         }
  167. }

  168. void SetFun(void) //进入设置参数子函数
  169. {
  170.         unsigned char i1=0,i2=0,i3=0,i4=0,i5=0,i6=0;
  171.         if(SetKey==0)  //设置按键
  172.         {
  173.                 delayms(20);   //延时防抖
  174.                 if(SetKey==0)  //设置按键
  175.                 {
  176.                         if(Set<2)        Set++;   //设置按键次数累计
  177.                         else Set=0;
  178.                 }
  179.                 switch(Set) //根据设置按键次数,指向对应设置位置
  180.                 {
  181.                         case 0:  writestring(0,1," ");writestring(8,1," ");break;//清除设置符号
  182.                         case 1:        writestring(0,1,">");writestring(8,1," ");break;//指向设置下限
  183.                         case 2:        writestring(0,1," ");writestring(8,1,">");break;//指向设置上限
  184.                 }
  185.                 while(SetKey==0);//等待按键松开
  186.         }
  187.         
  188.         if((UpKey==0)&&(Set!=0))//加按键按下
  189.         {
  190.                 delayms(20);//延时防抖
  191.                 if(UpKey==0)//加按键按下
  192.                 {
  193.                         switch(Set)//根据设置按键次数,设置上下限
  194.                         {
  195.                                 case 1:        if(AlarmTempLow<99) AlarmTempLow++;else AlarmTempLow=99; break;//设置下限
  196.                                 case 2:        if(AlarmTempTop<99) AlarmTempTop++;else AlarmTempTop=99; break;//设置上限
  197.                         }
  198.                         i1 = AlarmTempLow/100;          //获得下限温度值的百位
  199.                    i2 = AlarmTempLow%100/10;         //获得下限温度值的十位
  200.                         i3 = AlarmTempLow%10;                 //获得下限温度值的个位
  201.                         
  202.                         i4 = AlarmTempTop/100;          //获得上限温度值的百位
  203.                    i5 = AlarmTempTop%100/10;         //获得上限温度值的十位
  204.                         i6 = AlarmTempTop%10;                 //获得上限温度值的个位
  205.                         writestring(5,1,"   ");    //清除之前的内容
  206.                         writestring(13,1,"     ");//清除之前的内容
  207.                         if(i1!=0)        writeChar(5,1,i1+'0');//在第二行第5位 ,显示下限温度值的百位
  208.                         if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');//在第二行第5位 ,显示下限温度值的十位
  209.                         if(i1!=0) writeChar(6,1,i2+'0');//在第二行第6位 ,显示下限温度值的十位
  210.                         if((i1==0)&&(i2==0))        writeChar(5,1,i3+'0');//在第二行第5位 ,显示下限温度值的个位
  211.                         else if((i1==0)&&(i2!=0))        writeChar(6,1,i3+'0');//在第二行第6位 ,显示下限温度值的个位
  212.                         if((i1!=0))         writeChar(7,1,i3+'0');//在第二行第7位 ,显示下限温度值的个位
  213.                         
  214.                         if(i4!=0)        writeChar(13,1,i4+'0');//在第二行第13位 ,显示上限温度值的百位
  215.                         if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');//在第二行第13位 ,显示上限温度值的十位
  216.                         if(i4!=0) writeChar(14,1,i5+'0');//在第二行第14位 ,显示上限温度值的十位
  217.                         if((i4==0)&&(i5==0))        writeChar(13,1,i6+'0');//在第二行第13位 ,显示上限温度值的个位
  218.                         else if((i4==0)&&(i5!=0))        writeChar(14,1,i6+'0');//在第二行第14位 ,显示上限温度值的个位
  219.                         if((i4!=0)) writeChar(15,1,i6+'0');//在第二行第15位 ,显示上限温度值的个位
  220.                         while(UpKey==0);//等待按键松开
  221.                 }
  222.         }
  223.         
  224.         if((DnKey==0)&&(Set!=0))//减按键
  225.         {
  226.                 delayms(20);
  227.                 if(DnKey==0)//减按键
  228.                 {
  229.                         switch(Set)//根据设置按键次数,设置上下限
  230.                         {
  231.                                 case 1:        if(AlarmTempLow>0) AlarmTempLow--;else AlarmTempLow=0; break;//设置下限
  232.                                 case 2:        if(AlarmTempTop>0) AlarmTempTop--;else AlarmTempTop=0; break;//设置上限
  233.                         }
  234.                         i1 = AlarmTempLow/100;          //获得下限温度值的百位
  235.                    i2 = AlarmTempLow%100/10;         //获得下限温度值的十位
  236.                         i3 = AlarmTempLow%10;                 //获得下限温度值的个位
  237.                         
  238.                         i4 = AlarmTempTop/100;          //获得上限温度值的百位
  239.                    i5 = AlarmTempTop%100/10;         //获得上限温度值的十位
  240.                         i6 = AlarmTempTop%10;                 //获得上限温度值的个位
  241.                         writestring(5,1,"   ");    //清除之前的内容
  242.                         writestring(13,1,"     ");//清除之前的内容
  243.                         if(i1!=0)        writeChar(5,1,i1+'0');//在第二行第5位 ,显示下限温度值的百位
  244.                         if((i1==0)&&(i2!=0)) writeChar(5,1,i2+'0');//在第二行第5位 ,显示下限温度值的十位
  245.                         if(i1!=0) writeChar(6,1,i2+'0');//在第二行第6位 ,显示下限温度值的十位
  246.                         if((i1==0)&&(i2==0))        writeChar(5,1,i3+'0');//在第二行第5位 ,显示下限温度值的个位
  247.                         else if((i1==0)&&(i2!=0))        writeChar(6,1,i3+'0');//在第二行第6位 ,显示下限温度值的个位
  248.                         if((i1!=0))         writeChar(7,1,i3+'0');//在第二行第7位 ,显示下限温度值的个位
  249.                         
  250.                         if(i4!=0)        writeChar(13,1,i4+'0');//在第二行第13位 ,显示上限温度值的百位
  251.                         if((i4==0)&&(i5!=0)) writeChar(13,1,i5+'0');//在第二行第13位 ,显示上限温度值的十位
  252.                         if(i4!=0) writeChar(14,1,i5+'0');//在第二行第14位 ,显示上限温度值的十位
  253.                         if((i4==0)&&(i5==0))        writeChar(13,1,i6+'0');//在第二行第13位 ,显示上限温度值的个位
  254.                         else if((i4==0)&&(i5!=0))        writeChar(14,1,i6+'0');//在第二行第14位 ,显示上限温度值的个位
  255.                         if((i4!=0)) writeChar(15,1,i6+'0');//在第二行第15位 ,显示上限温度值的个位
  256.                         
  257.                         while(DnKey==0);
  258.                 }
  259.         }
  260. }



  261. void Alarm(void)//报警子函数
  262. {
  263.         if((CurrentT>=(AlarmTempTop*10))||(CurrentT<=(AlarmTempLow*10))||(tflag==1)) //超出设定范围
  264.                 {
  265.                         BEEP=0;//启动报警
  266.                 }
  267.                 else //在设定范围内
  268.                 {
  269.                         BEEP=1;//取消报警
  270.                 }
  271. }
  272. ……………………

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


全部资料51hei下载地址(dsn文件 仿真是用Proteus7.5画的):
恒温控制.7z (3.38 MB, 下载次数: 210)

评分

参与人数 1黑币 +90 收起 理由
admin + 90 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:424598 发表于 2021-7-16 17:10 来自手机 | 只看该作者
楼主发贴专业,收藏,有空改成带屏蔽测温的。感谢分享
回复

使用道具 举报

板凳
ID:983990 发表于 2021-11-27 09:44 | 只看该作者
楼主我这显示DS18b20的数据错误是咋回事
回复

使用道具 举报

地板
ID:440028 发表于 2022-1-6 08:58 | 只看该作者
数据资料比较详细,这5分应该是值
回复

使用道具 举报

5#
ID:795562 发表于 2022-1-27 22:27 | 只看该作者
这个很有指导意义
回复

使用道具 举报

6#
ID:336378 发表于 2022-3-16 08:13 | 只看该作者
不是pid控制的。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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