找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5405|回复: 10
收起左侧

单片机智能温控器+源程序+仿真

  [复制链接]
ID:265818 发表于 2017-12-24 12:10 | 显示全部楼层 |阅读模式
智能温控器+源程序+仿真,这里面的程序问题已经调好了的,可以直接下载运行。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
c.png v.png

单片机源程序如下:
  1. /************************************************************************
  2.            烟叶烘烤过程温湿度报警系统

  3. 系统描述:在LCD1602上实时显示时钟,温度,湿度,系统运行时间。利用ds18b20
  4.                   检测当前温度,通过和设定参数的比较,给ISD1420发出报警脉冲,通过
  5.           功率放大器LM386 驱动喇叭报警。




  6. *************************************************************************/

  7. #include<reg51.h>
  8. #include<intrins.h>
  9. #include <absacc.h>
  10. #define uchar unsigned char
  11. #define uint   unsigned int

  12. #define BUSY  0x80                               //lcd忙检测标志
  13. #define DATAPORT P0                              //定义P0口为LCD通讯端口
  14. #define PLAYE_ADDR XBYTE[0XBFFF]                 //语音报警地址

  15. sbit RED_ALARM=P1^0;                                                    //红色指示灯
  16. sbit WRITE_ALARM=P1^1;                                          //白色指示灯
  17. sbit GREEN_ALARM=P1^2;                                          //绿色指示灯
  18. sbit P1_4=P1^4;                                                    //时钟调整
  19. sbit P1_5=P1^5;                                                 //时钟加
  20. sbit P1_6=P1^6;                                                 //时钟减

  21. sbit DQ = P1^7;                                                 //定义ds18b20通信端口
  22. sbit LCM_RS=P2^0;                                                                //数据/命令端
  23. sbit LCM_RW=P2^1;                                                                //读/写选择端
  24. sbit LCM_EN=P2^2;                                               //LCD使能信号
  25. sbit ad_busy=P3^2;                                              //adc中断方式接口
  26. sbit RECLED_EOC=P3^5;                                           //ISD1420放音结束查询标志
  27. sbit OUT=P3^7;

  28. uchar ad_data;                                                  //ad采样值存储                                               
  29. uchar seconde=0;                                                //定义并初始化时钟变量
  30. uchar minite=0;
  31. uchar hour=12;
  32. uchar mstcnt=0;
  33. uchar temp1,temp2,temp;                                     //温度显示变量
  34. uchar t,set;
  35. uchar T;
  36. bit ON_OFF;
  37. bit outflag;

  38. uchar code str0[]={"---  :  :  ---OF"};
  39. uchar code str1[]={"SET:  C SA:  . C"};

  40. void delay_LCM(uint);                                                                                                     //LCD延时子程序
  41. void initLCM( void);                                                                                                       //LCD初始化子程序
  42. void lcd_wait(void);                                                                                                      //LCD检测忙子程序
  43. void WriteCommandLCM(uchar WCLCM,uchar BusyC);                              //写指令到ICM子函数
  44. void WriteDataLCM(uchar WDLCM);                                             //写数据到LCM子函数
  45. void DisplayOneChar(uchar X,uchar Y,uchar DData);                           //显示指定坐标的一个字符子函数
  46. void DisplayListChar(uchar X,uchar Y,uchar code *DData);                    //显示指定坐标的一串字符子函数
  47. void init_timer0(void);                                                                                               //定时器初始化
  48. void displayfun1(void);
  49. void displayfun2(void);
  50. void displayfun3(void);
  51. void displayfun4(void);
  52. void keyscan(void );                                                                                            //键盘扫描子程序
  53. void set_adj(void);
  54. void inc_key(void);
  55. void dec_key(void);
  56. void delay_18B20(unsigned int i);
  57. void Init_DS18B20(void) ;
  58. uchar ReadOneChar(void);
  59. void WriteOneChar(unsigned char dat);
  60. void ReadTemperature(void);
  61. void ad0809(void);
  62. void playalarm(void);


  63. /*********延时K*1ms,12.000mhz**********/

  64. void delay_LCM(uint k)
  65. {
  66.     uint i,j;
  67.     for(i=0;i<k;i++)
  68.     {
  69.         for(j=0;j<60;j++)
  70.                 {;}
  71.     }
  72. }   
  73. /**********写指令到ICM子函数************/

  74. void WriteCommandLCM(uchar WCLCM,uchar BusyC)
  75. {
  76.     if(BusyC)lcd_wait();
  77.         DATAPORT=WCLCM;
  78.     LCM_RS=0;                   // 选中指令寄存器
  79.     LCM_RW=0;                       // 写模式       
  80.     LCM_EN=1;   
  81.         _nop_();   
  82.         _nop_();
  83.         _nop_();
  84.     LCM_EN=0;  
  85. }

  86. /**********写数据到LCM子函数************/

  87. void WriteDataLCM(uchar WDLCM)
  88. {
  89.     lcd_wait( );            //检测忙信号   
  90.         DATAPORT=WDLCM;
  91.     LCM_RS=1;               // 选中数据寄存器
  92.     LCM_RW=0;                   // 写模式
  93.     LCM_EN=1;
  94.     _nop_();
  95.         _nop_();
  96.         _nop_();
  97.     LCM_EN=0;
  98. }

  99. /***********lcm内部等待函数*************/

  100. void lcd_wait(void)
  101. {
  102.     DATAPORT=0xff;             
  103.         LCM_EN=1;
  104.     LCM_RS=0;                          
  105.     LCM_RW=1;                          
  106.     _nop_();
  107.     while(DATAPORT&BUSY)
  108.         {  LCM_EN=0;
  109.            _nop_();
  110.            _nop_();
  111.            LCM_EN=1;
  112.            _nop_();
  113.            _nop_();
  114.            }
  115.            LCM_EN=0;
  116.        
  117. }

  118. /**********LCM初始化子函数***********/

  119. void initLCM( )
  120. {   
  121.         DATAPORT=0;       
  122.         delay_LCM(15);
  123.         WriteCommandLCM(0x38,0);    //三次显示模式设置,不检测忙信号
  124.     delay_LCM(5);
  125.     WriteCommandLCM(0x38,0);
  126.     delay_LCM(5);
  127.     WriteCommandLCM(0x38,0);
  128.     delay_LCM(5);

  129.     WriteCommandLCM(0x38,1);    //8bit数据传送,2行显示,5*7字型,检测忙信号
  130.     WriteCommandLCM(0x08,1);    //关闭显示,检测忙信号
  131.     WriteCommandLCM(0x01,1);    //清屏,检测忙信号
  132.     WriteCommandLCM(0x06,1);    //显示光标右移设置,检测忙信号
  133.     WriteCommandLCM(0x0c,1);    //显示屏打开,光标不显示,不闪烁,检测忙信号
  134. }

  135. /****************显示指定坐标的一个字符子函数*************/

  136. void DisplayOneChar(uchar X,uchar Y,uchar DData)
  137. {
  138.     Y&=1;
  139.     X&=15;
  140.     if(Y)X|=0x40;               //若y为1(显示第二行),地址码+0X40
  141.     X|=0x80;                    //指令码为地址码+0X80
  142.     WriteCommandLCM(X,0);
  143.     WriteDataLCM(DData);
  144. }

  145. /***********显示指定坐标的一串字符子函数***********/

  146. void DisplayListChar(uchar X,uchar Y,uchar code *DData)
  147. {
  148.     uchar ListLength=0;
  149.     Y&=0x01;
  150.     X&=0x0f;
  151.     while(X<16)
  152.     {
  153.         DisplayOneChar(X,Y,DData[ListLength]);
  154.         ListLength++;
  155.         X++;
  156.     }
  157. }

  158. /***********ds18b20延迟子函数(晶振12MHz )*******/

  159. void delay_18B20(unsigned int i)
  160. {
  161.         while(i--);
  162. }

  163. /**********ds18b20初始化函数**********************/

  164. void Init_DS18B20(void)
  165. {
  166.          unsigned char x=0;
  167.          DQ = 1;          //DQ复位
  168.          delay_18B20(8);  //稍做延时
  169.          DQ = 0;          //单片机将DQ拉低
  170.          delay_18B20(80); //精确延时 大于 480us
  171.          DQ = 1;          //拉高总线
  172.          delay_18B20(14);
  173.          x=DQ;            //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  174.          delay_18B20(20);
  175. }

  176. /***********ds18b20读一个字节**************/  

  177. unsigned char ReadOneChar(void)
  178. {
  179.         uchar i=0;
  180.         uchar dat = 0;
  181.         for (i=8;i>0;i--)
  182.          {
  183.                   DQ = 0; // 给脉冲信号
  184.                   dat>>=1;
  185.                   DQ = 1; // 给脉冲信号
  186.                   if(DQ)
  187.                   dat|=0x80;
  188.                   delay_18B20(4);
  189.          }
  190.         return(dat);
  191. }

  192. /*************ds18b20写一个字节****************/  

  193. void WriteOneChar(uchar dat)
  194. {
  195.         unsigned char i=0;
  196.         for (i=8; i>0; i--)
  197.         {
  198.                   DQ = 0;
  199.                 DQ = dat&0x01;
  200.             delay_18B20(5);
  201.                 DQ = 1;
  202.             dat>>=1;
  203. }
  204. }

  205. /**************读取ds18b20当前温度************/

  206. void ReadTemperature(void)
  207. {
  208.         unsigned char a=0;
  209.         unsigned char b=0;
  210.         unsigned char t=0;

  211.         Init_DS18B20();
  212.         WriteOneChar(0xCC);            // 跳过读序号列号的操作
  213.         WriteOneChar(0x44);         // 启动温度转换

  214.         delay_18B20(100);       // this message is wery important

  215.         Init_DS18B20();
  216.         WriteOneChar(0xCC);         //跳过读序号列号的操作
  217.         WriteOneChar(0xBE);         //读取温度寄存器等(共可读9个寄存器) 前两个就是温度

  218.         delay_18B20(100);

  219.         a=ReadOneChar();            //读取温度值低位
  220.         b=ReadOneChar();                   //读取温度值高位
  221.         temp1=b<<4;
  222.         temp1+=(a&0xf0)>>4;
  223.         temp2=a&0x0f;

  224.     temp=((b*256+a)>>4);    //当前采集温度值除16得实际温度值


  225. }

  226. /***************液晶显示子函数1正常显示*****************/

  227. void displayfun1(void)
  228. {       
  229.         WriteCommandLCM(0x0c,1);                                            //显示屏打开,光标不显示,不闪烁,检测忙信号       
  230.         DisplayListChar(0,0,str0);       
  231.         DisplayListChar(0,1,str1);       
  232.                                                                                                       
  233.         DisplayOneChar(3,0,hour/10+0x30);                    //液晶上显示小时
  234.         DisplayOneChar(4,0,hour%10+0x30);

  235.         DisplayOneChar(6,0,minite/10+0x30);                        //液晶上显示分
  236.         DisplayOneChar(7,0,minite%10+0x30);
  237.        
  238.         DisplayOneChar(9,0,seconde/10+0x30);            //液晶上显示秒
  239.         DisplayOneChar(10,0,seconde%10+0x30);

  240.         DisplayOneChar(4,1,T/10+0x30);                            //液晶上显示设定的温度
  241.         DisplayOneChar(5,1,T%10+0x30);

  242.            DisplayOneChar(11,1,temp1/10+0x30);         //液晶上显示测得的温度  
  243.         DisplayOneChar(12,1,temp1%10+0x30);
  244.         DisplayOneChar(14,1,temp2/10+0x30);

  245.         if(ON_OFF==0)                                                      //若温控标志为0
  246.         {
  247.                 DisplayOneChar(14,0,0x4f);                           // 液晶上显示不控温的标志
  248.                 DisplayOneChar(15,0,0x46);
  249.         }
  250.         else
  251.         {
  252.                 DisplayOneChar(14,0,0x4f);                           // 液晶上显示控温的标志
  253.                 DisplayOneChar(15,0,0x4e);
  254.                 if(outflag==1)
  255.                     DisplayOneChar(0,0,0x7c);                          
  256.             else
  257.                         DisplayOneChar(0,0,0xef);
  258.         }

  259.        
  260. }
  261. /************液晶显示子函数2***************/

  262. void displayfun2(void)
  263. {
  264.         WriteCommandLCM(0x0c,1);                     //显示屏打开,光标不显示,不闪烁,检测忙信号       
  265.         DisplayListChar(0,0,str0);       
  266.         DisplayListChar(0,1,str1);       
  267.                
  268.         DisplayOneChar(6,0,minite/10+0x30);
  269.         DisplayOneChar(7,0,minite%10+0x30);
  270.        
  271.         DisplayOneChar(9,0,seconde/10+0x30);
  272.         DisplayOneChar(10,0,seconde%10+0x30);

  273.         DisplayOneChar(4,1,T/10+0x30);                          
  274.         DisplayOneChar(5,1,T%10+0x30);

  275.            DisplayOneChar(11,1,temp1/10+0x30);         
  276.         DisplayOneChar(12,1,temp1%10+0x30);
  277.         DisplayOneChar(14,1,temp2/10+0x30);

  278.            WriteCommandLCM(0x0f,1);                                            //显示屏打开,光标显示,闪烁,检测忙信号       
  279.     DisplayOneChar(3,0,hour/10+0x30);
  280.         DisplayOneChar(4,0,hour%10+0x30);
  281. }

  282. /**************液晶显示子函数3*****************/

  283. void displayfun3(void)
  284. {
  285.         WriteCommandLCM(0x0c,1);                                    //显示屏打开,光标不显示,不闪烁,检测忙信号       
  286.         DisplayListChar(0,0,str0);       
  287.         DisplayListChar(0,1,str1);       
  288.        
  289.         DisplayOneChar(3,0,hour/10+0x30);
  290.         DisplayOneChar(4,0,hour%10+0x30);

  291.         DisplayOneChar(9,0,seconde/10+0x30);
  292.         DisplayOneChar(10,0,seconde%10+0x30);

  293.         DisplayOneChar(4,1,T/10+0x30);                          
  294.         DisplayOneChar(5,1,T%10+0x30);

  295.            DisplayOneChar(11,1,temp1/10+0x30);         
  296.         DisplayOneChar(12,1,temp1%10+0x30);
  297.         DisplayOneChar(14,1,temp2/10+0x30);

  298.    
  299.         WriteCommandLCM(0x0f,1);                                            //显示屏打开,光标显示,闪烁,检测忙信号
  300.         DisplayOneChar(6,0,minite/10+0x30);
  301.         DisplayOneChar(7,0,minite%10+0x30);

  302. }

  303. /**************液晶显示子函数4 *****************/

  304. void displayfun4(void)
  305. {
  306.         WriteCommandLCM(0x0c,1);                                    //显示屏打开,光标不显示,不闪烁,检测忙信号       
  307.         DisplayListChar(0,0,str0);       
  308.         DisplayListChar(0,1,str1);       
  309.        
  310.         DisplayOneChar(3,0,hour/10+0x30);
  311.         DisplayOneChar(4,0,hour%10+0x30);

  312.         DisplayOneChar(6,0,minite/10+0x30);
  313.         DisplayOneChar(7,0,minite%10+0x30);

  314.         DisplayOneChar(9,0,seconde/10+0x30);
  315.         DisplayOneChar(10,0,seconde%10+0x30);

  316.        
  317.            DisplayOneChar(11,1,temp1/10+0x30);         
  318.         DisplayOneChar(12,1,temp1%10+0x30);
  319.         DisplayOneChar(14,1,temp2/10+0x30);

  320.    
  321.         WriteCommandLCM(0x0f,1);                                            //显示屏打开,光标显示,闪烁,检测忙信号
  322.         DisplayOneChar(4,1,T/10+0x30);                          
  323.         DisplayOneChar(5,1,T%10+0x30);

  324. }

  325. /**************键盘扫描子函数******************/

  326. void keyscan(void)
  327. {
  328.         uchar xx;                                           //局部变量
  329.         P1=0xff;
  330.         if(P1!=0xff)
  331.           {
  332.             delay_LCM(30);
  333.                 if(P1!=0xff)
  334.                   {       
  335.                         xx=P1;
  336.                         switch(xx)                                                       // 根据按键状态,调用不同的子函数
  337.                         {
  338.                                 case 0xfe:set_adj();       break;               
  339.                                 case 0xfd:inc_key();       break;               
  340.                                 case 0xfb:dec_key();       break;               
  341.                                 case 0xf7:ON_OFF=!ON_OFF;  break;
  342.                                 default:break;
  343.                         }
  344.                   }
  345.                
  346.           }
  347.   
  348. }

  349. /**************设定工作模式子函数****************/

  350. void set_adj(void)
  351. {
  352.         delay_LCM(100);
  353.         set++;
  354.     if(set>=4)set=0;
  355.                
  356. }

  357. /****************按键加法子函数******************/

  358. void inc_key(void)
  359. {
  360.         delay_LCM(100);
  361.                
  362.         switch(set)
  363.         {
  364.                 case 0:if(P2==0xf7)ON_OFF=!ON_OFF;       break;
  365.                 case 1:hour++;   if(hour>=23)hour=23;    break;
  366.                 case 2:minite++; if(minite>=59)minite=59;break;
  367.                 case 3:T++;if(T>=99)T=99;                                 break;
  368.                 default:break;
  369.         }
  370.                
  371. }

  372. /****************按键减法子函数*****************/

  373. void dec_key(void)
  374. {
  375.         delay_LCM(100);
  376.        
  377.         switch(set)
  378.         {
  379.                    case 0:if(P2==0xf7)ON_OFF=!ON_OFF;    break;
  380.                 case 1:hour--;  if(hour<=0)hour=0;    break;
  381.                 case 2:minite--;if(minite<=0)minite=0;break;
  382.                 case 3:T--;if(T<=1)T=1;                                  break;
  383.                 default:break;
  384.         }
  385.                
  386. }

  387. /***************定时器t0初始化*******************/

  388. void init_timer0(void)
  389. {
  390.          TMOD=0x01;                                  //time0为定时器,方式1
  391.      TH0=0x3c;                                   //预置计数初值
  392.      TL0=0xb0;
  393.      EA=1;                                                                  
  394.      ET0=1;                                                                                                 
  395.      TR0=1;                         
  396. }

  397. /***********定时器t0中断子函数**************/

  398. void timer0(void) interrupt 1 using 0          //定时器0方式1,50ms中断一次
  399. {
  400.      TH0=0x3c;
  401.      TL0=0xb0;
  402.      mstcnt++;
  403.      if(mstcnt>=20 )  {seconde++; mstcnt=0; }
  404.          if(seconde>=60)  {minite++;  seconde=0;}
  405.          if(minite>=60 )  {hour++;    minite=0; }
  406.          if(hour>=24   )  {hour=0;}
  407.          keyscan( );                               //按键扫描
  408. }

  409. /*****************系统报警子函数***************************/
  410. /*查询ISD1420_RECLED管脚的放音结束标志EOC,瞬间的低电平*/
  411. /*调试时基本正确,但是,会发生突发的不稳定的报警*/
  412. /**********************************************************/

  413. ……………………

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

所有资料51hei提供下载:
智能温控器.zip (141.03 KB, 下载次数: 138)
回复

使用道具 举报

ID:6633 发表于 2017-12-24 17:30 | 显示全部楼层
好东东,学习了,谢谢
回复

使用道具 举报

ID:293792 发表于 2018-4-2 08:21 | 显示全部楼层
贴主,下了你的文件,用protues仿真发现DS18B20 不能正常工作,protues没问题,开其他的文件倒是可以正常工作,为什么。
回复

使用道具 举报

ID:304318 发表于 2018-4-13 13:53 来自手机 | 显示全部楼层
谢谢大神分享
回复

使用道具 举报

ID:314339 发表于 2018-4-23 20:12 来自手机 | 显示全部楼层
谢谢分享,感谢楼主
回复

使用道具 举报

ID:316971 发表于 2018-4-26 14:07 | 显示全部楼层
谢谢分享,值得学习
回复

使用道具 举报

ID:412814 发表于 2018-11-8 07:10 | 显示全部楼层
感谢楼主分享,下载了慢慢研究一下。
回复

使用道具 举报

ID:47652 发表于 2019-5-11 14:04 | 显示全部楼层
正好用得上,谢谢楼主
回复

使用道具 举报

ID:243394 发表于 2019-7-12 18:07 | 显示全部楼层
谢谢分享,值得学习
回复

使用道具 举报

ID:512926 发表于 2020-6-16 12:48 | 显示全部楼层

谢谢分享,值得学习
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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