立即注册 登录
返回首页

uid:186154的个人空间

日志

51单片机温度控制

热度 1已有 398 次阅读2017-4-5 11:13 | 单片机

  1. #include<reg51.h>  
  2. #include<intrins.h>  
  3. #define uint unsigned int   
  4. #define uchar unsigned char  
  5.   
  6. /*LCD1602显示模块*/  
  7. /*用于PROTUES仿真 
  8. #define LCD1602_DATAPINS P2  
  9. sbit LCD1602_RS=P3^0;    
  10. sbit LCD1602_RW=P3^1;                                      
  11. sbit LCD1602_E=P3^2;      */  
  12.   
  13.   
  14. #define LCD1602_DATAPINS P0  
  15. sbit LCD1602_RS=P2^6;  
  16. sbit LCD1602_RW=P2^5;                                       
  17. sbit LCD1602_E=P2^7;  
  18.   
  19. /*按键调节模块*/  
  20. sbit k1=P1^1;//功能键  
  21. sbit k2=P1^2;//加  
  22. sbit k3=P1^3;//减   
  23. void keyscan();  
  24. void key1_switch();  
  25. void key2_add();  
  26. void key3_minus();  
  27.   
  28. uchar k_num;  
  29. void LCD1602_SetTemp(uchar add,uchar dat);  
  30. uchar high=90,low=10,set_t=30,set_d=2;//这里的数据类型可能有问题!!  
  31.   
  32. /*其他模块接口*/  
  33. sbit DSPORT=P3^7//温度传感器单总线端  
  34. sbit SPEAKER=P1^5;//蜂鸣器  
  35. sbit RELAY=P1^4;//继电器  
  36. sbit COOLER=P1^7;//降温装置  
  37.   
  38. /*LCD1602相关函数*/  
  39. void Delay1us(uint a);  
  40. void LCD1602_WriteCom(uchar com);//LCD1602写入8位命令子函数   
  41. void LCD1602_WriteData(uchar dat);        
  42. void LCD1602_Init();//LCD1602初始化子程序                         
  43. void LCD1602_ShowTemp(int temp);  
  44.   
  45. /*DS18B20温度传感器相关函数*/  
  46. void  Delay15us(uchar aa);  
  47. uchar Ds18b20Init();  
  48. void  Ds18b20WriteByte(uchar dat);  
  49. uchar Ds18b20ReadByte();  
  50. void  Ds18b20SwitchTemp();  
  51. int   Ds18b20ReadTemp();  
  52.   
  53. float temp_max=125.00,temp_min=-55.00;  
  54. uchar ii=0,jj=0,kk=0;  
  55. uchar words_h[2]={"H="};  
  56. uchar words_l[2]={"L="};  
  57. uchar words_s[4]={"Set="};  
  58. void Sound();  
  59. void Temp_control(int temp);  
  60. uchar count=0;//用来解决主程序执行太快,按键光标来不及显示的问题  
  61.   
  62. void Temp_control(int temp)  
  63. {     
  64.     unsigned int kk=400;  
  65.     uchar set_h,set_l;  
  66.     set_h=set_t+set_d;  
  67.     set_l=set_t-set_d;  
  68.       
  69.         if (temp<=set_h&&temp>=set_l) //设定温度范围之内  
  70.         {  
  71.               RELAY = 0//继电器断开  
  72.              COOLER=0;//风扇关闭  
  73.         }  
  74.         else   
  75.         {     
  76.             TR0=0;  
  77.               
  78.             while (kk--)  
  79.             {         
  80.             Sound();  
  81.             }  
  82.             RELAY = 1//继电器打开,外电路(常开触电)闭合加热  
  83.             if (temp>=set_h)//温度过高  
  84.             {  
  85.                 RELAY = 0//继电器断开  
  86.                  COOLER=1;//打开  
  87.             }  
  88.             TR0=1;  
  89.         }  
  90. }  
  91.   
  92. /*其他模块相关函数*/  
  93. void Sound()//蜂鸣器  
  94. {        
  95.     SPEAKER=1;  
  96.     Delay15us(40);  
  97.     SPEAKER=0;  
  98.     Delay15us(40);  
  99. }  
  100.   
  101. void Delay1us(uint a)  
  102. {  
  103.     uint b,c;  
  104.     for(c=a;c>0;c--)  
  105.         for(b=110;b>0;b--);  
  106. }  
  107.   
  108. void LCD1602_WriteCom(uchar com)      //写入命令  
  109. {  
  110.     LCD1602_E=0;  
  111.     LCD1602_RS=0;//0就写指令  
  112.     LCD1602_RW=0//0就是写  
  113.     LCD1602_DATAPINS=com;  
  114.     Delay1us(10);  
  115.     LCD1602_E=1;  
  116.     Delay1us(10);  
  117.     LCD1602_E=0;  
  118. }  
  119.              
  120. void LCD1602_WriteData(uchar dat)           //写入数据  
  121. {  
  122.     LCD1602_E=0;  
  123.     LCD1602_RS=1;  
  124.     LCD1602_RW=0;  
  125.     LCD1602_DATAPINS=dat;  
  126.     Delay1us(10);  
  127.     LCD1602_E=1;  
  128.     Delay1us(10);  
  129.     LCD1602_E=0;  
  130. }  
  131.   
  132. void LCD1602_Init()          //LCD初始化子程序  
  133. {  
  134. //  uint num;  
  135.     LCD1602_WriteCom(0x38);  //开显示  
  136.     LCD1602_WriteCom(0x0f);  //开显示不显示光标  
  137.     LCD1602_WriteCom(0x06);  //写一个指针加1  
  138.     LCD1602_WriteCom(0x01);  //清屏  
  139.     LCD1602_WriteCom(0x80);  //设置数据指针起点  
  140.   
  141.     LCD1602_WriteCom(0x80+0x0B);  
  142.     for (ii=0;ii<2;ii++)  
  143.     {     
  144.             LCD1602_WriteData(words_h[ii]);  
  145.     }  
  146.     LCD1602_SetTemp(13,high);  
  147.   
  148.     LCD1602_WriteCom(0x80+0x40);  
  149.     for (kk=0;kk<4;kk++)  
  150.     {     
  151.             LCD1602_WriteData(words_s[kk]);  
  152.     }  
  153.     LCD1602_SetTemp(4+0x40,set_t);  
  154.     LCD1602_WriteCom(0x80+0x47);  
  155.   
  156.     LCD1602_WriteData(0x23);  //显示正负号  
  157.   
  158.     LCD1602_WriteCom(0x80+0x48);  
  159.     LCD1602_WriteData(0x30+set_d);  
  160.               
  161.     LCD1602_WriteCom(0x80+0x4B);  
  162.     for (jj=0;jj<2;jj++)  
  163.     {     
  164.     LCD1602_WriteData(words_l[jj]);  
  165.     }  
  166.     LCD1602_SetTemp(13+0x40,low);  
  167.   
  168.       
  169.     TMOD=0X01;  
  170.     TH0=(65536-50000)/256;  
  171.     TL0=(65536-50000)%256;  
  172.     EA=1;//总中断  
  173.     ET0=1;  
  174.     TR0=1;   
  175. }  
  176.   
  177. void  Delay15us(uchar aa)  
  178. {  
  179.     do{  
  180.     _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();  
  181.     _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();  
  182.     aa--;  
  183.     }while(aa);  
  184.       
  185. }  
  186.   
  187. /*DS18B20温度传感器相关函数*/  
  188. uchar Ds18b20Init()  
  189. {  
  190.     uchar flag;  
  191.     DSPORT=0;     //总线拉低  
  192.     Delay15us(40);//延时480~960us  
  193.     DSPORT=1;  
  194.     Delay15us(2);  
  195.     flag=DSPORT;  
  196.     Delay15us(6);//Ds18b20发出应答信号,延时60~240us  
  197.     Delay15us(25);  
  198.     return  flag;  
  199. }   
  200.   
  201.   
  202. uchar Ds18b20ReadByte()  
  203. {  
  204.     uchar byte,bi;   
  205.     uint i;  
  206.     for (i=0;i<8;i++)  
  207.     {  
  208.         DSPORT=0;  
  209.         _nop_();_nop_();_nop_();_nop_(); //保持低电平至少1us,但不能低于15us  
  210.         DSPORT=1;  
  211.         bi= DSPORT;//读取一位数据,循环8次为一个字节  
  212.         byte = (byte >> 1) | (bi << 7);//将byte左移一位,然后与上右移7位后的bi,8次合成一个字节  
  213.         Delay15us(4);  
  214.   
  215.     }  
  216.     return  byte;  
  217. }   
  218.   
  219. void  Ds18b20WriteByte(uchar dat)  
  220. {  
  221.      uint i;  
  222.      for (i=0;i<8;i++)  
  223.      {  
  224.         DSPORT=0;_nop_();  
  225.         DSPORT=dat&0x01;//一位一位得读,从最低位开始  
  226.         Delay15us(5);  
  227.         DSPORT=1;_nop_();  
  228.         dat>>=1;  
  229.      }  
  230. }   
  231. void  Ds18b20SwitchTemp()  
  232. {  
  233.         Ds18b20Init();  
  234.         Delay15us(7);  
  235.         Ds18b20WriteByte(0xcc);//跳过ROM指令  
  236.         Ds18b20WriteByte(0x44);//启动温度转换指令  
  237. }   
  238. int   Ds18b20ReadTemp()  
  239. {  
  240.     int temp=0;  
  241.     uchar temp_h,temp_l;      
  242.     Ds18b20SwitchTemp();  
  243.     Ds18b20Init();  
  244.     Delay1us(1);  
  245.     Ds18b20WriteByte(0xcc);  //跳过ROM操作命令  
  246.     Ds18b20WriteByte(0xbe);  //发送读取温度命令  
  247.     temp_l = Ds18b20ReadByte();     //读取温度值共16位,先读低字节  
  248.     temp_h = Ds18b20ReadByte();       
  249.     temp= temp_h;  
  250.     temp<<=8;  
  251.     temp|= temp_l;  
  252.     return temp;  
  253. }   
  254.   
  255. void LCD1602_ShowTemp(int temp)  
  256. {  
  257.     float tt;  
  258.     uchar show[5]={0,0,0,0,0};  
  259.     if (temp<0)//温度为负  
  260.     {  
  261.         LCD1602_WriteCom(0x80);     //写地址 80表示初始地址  
  262.         LCD1602_WriteData('-');         //显示负  
  263.         temp=temp-1;temp=~temp;tt=temp; temp=tt*0.0625*100;  
  264.           
  265.     }  
  266.     else//温度为正  
  267.     {  
  268.         LCD1602_WriteCom(0x80);     //写地址 80表示初始地址  
  269.         LCD1602_WriteData('+');         //显示正  
  270.         tt=temp;              
  271.         temp=tt*0.0625*100;  
  272.           
  273.     }  
  274.       
  275.     show[0]=temp/10000;  
  276.     show[1]=temp%10000/1000;  
  277.     show[2]=temp%1000/100;  
  278.     show[3]=temp%100/10;  
  279.     show[4]=temp%10;  
  280.   
  281.     LCD1602_WriteCom(0x82);  
  282.     LCD1602_WriteData('0'+show[0]); //百位   
  283.   
  284.     LCD1602_WriteCom(0x83);  
  285.     LCD1602_WriteData('0'+show[1]); //十位   
  286.   
  287.     LCD1602_WriteCom(0x84);  
  288.     LCD1602_WriteData('0'+show[2]); //个位   
  289.   
  290.     LCD1602_WriteCom(0x85);  
  291.     LCD1602_WriteData('.');  
  292.   
  293.     LCD1602_WriteCom(0x86);  
  294.     LCD1602_WriteData('0'+show[3]); //十分位  
  295.   
  296.     LCD1602_WriteCom(0x87);  
  297.     LCD1602_WriteData('0'+show[4]); //百分位  
  298.   
  299.     LCD1602_WriteCom(0x88);   
  300.     LCD1602_WriteData(0xdf);  
  301.   
  302.     LCD1602_WriteCom(0x89);   
  303.     LCD1602_WriteData('C');  
  304.     LCD1602_WriteCom(0x0C);  
  305.   
  306.     temp=temp/100;  
  307.     Temp_control(temp);  
  308.       
  309. }  
  310. void key1_switch()//功能切换  
  311. {  
  312.     uchar set_h,set_l;  
  313.     set_h=set_t+set_d;  
  314.     set_l=set_t-set_d;  
  315.     //k1键指令  
  316.     if(k1==0)     
  317.     {  
  318.         Delay1us(10);//延时消抖  
  319.             if(k1==0)  
  320.             {     
  321.                 k_num++;  
  322.                 while(!k1); //按键没有松开  
  323.   
  324.                 if(k_num==1)  
  325.                 {  
  326.                     TR0=0//关掉计时器,使得光标得以显示  
  327.                     LCD1602_WriteCom(0x80+0x46);  
  328.                     LCD1602_WriteCom(0x0f);   
  329.                     Delay15us(6);  
  330.                 }  
  331.                 if(k_num==2)  
  332.                 {  
  333.                     LCD1602_WriteCom(0x80+0x48);  
  334.                     LCD1602_WriteCom(0x0f);   
  335.                     Delay15us(6);  
  336.                 }  
  337.                 if(k_num==3)  
  338.                 {  
  339.                     LCD1602_WriteCom(0x80+0x0F);  
  340.                     LCD1602_WriteCom(0x0f);   
  341.                     Delay15us(6);  
  342.                 }  
  343.                 if(k_num==4)  
  344.                 {  
  345.                     LCD1602_WriteCom(0x80+0x4F);  
  346.                     LCD1602_WriteCom(0x0f);   
  347.                     Delay15us(6);  
  348.                 }  
  349.                 if(k_num==5)  
  350.                 {  
  351.                     k_num=0;  
  352.                       
  353.                     LCD1602_WriteCom(0x0C);//光标不显示                    
  354.                     if (high<low)  //用来default  
  355.                     {  
  356.                          high=90;  
  357.                          low=40;//恢复默认值  
  358.                     }  
  359.   
  360.                      if(set_h>high||set_l<low)  
  361.                      {  
  362.                          high=90;  
  363.                          low=10;//恢复默认值   
  364.                           set_t=30;  
  365.                           set_d=2;//恢复默认值  
  366.                      }  
  367.                      TR0=1;//计时器重新打开,使得屏幕得以刷新  
  368.                 }  
  369.             }  
  370.   
  371.     }  
  372. }  
  373. void key2_add()//功能加  
  374. {  
  375.         if(k_num!=0)  
  376.         {  
  377.             if(k2==0)  
  378.             {  
  379.                 Delay1us(5);  
  380.                 if(k2==0)  
  381.                 {  
  382.                     while(!k2);  
  383.                     if(k_num==1)  
  384.                     {  
  385.                         set_t++;  
  386.                         if (set_t>=high)  
  387.                           set_t=high;  
  388.                           LCD1602_SetTemp(4+0x40,set_t);  
  389.                           LCD1602_WriteCom(0x80+0x46);                                        
  390.                     }  
  391.                     if(k_num==2)  
  392.                     {  
  393.                         set_d++;  
  394.                         if (set_d>9)  
  395.                           set_d=0;  
  396.                         LCD1602_WriteCom(0x80+0x48);  
  397.                         LCD1602_WriteData(0x30+set_d);  
  398.                         LCD1602_WriteCom(0x80+0x48);                                          
  399.                     }  
  400.                     if(k_num==3)  
  401.                     {  
  402.                         high++;  
  403.                         if (high>=temp_max)  
  404.                           high=0;  
  405.                           LCD1602_SetTemp(13,high);  
  406.                           LCD1602_WriteCom(0x80+0x0F);  
  407. //                        LCD1602_WriteCom(0x80+0x40+8);                                          
  408.                     }  
  409.                     if(k_num==4)  
  410.                     {  
  411.                         low++;  
  412.                         if (low>=temp_max)  
  413.                          low=0;  
  414.                           LCD1602_SetTemp(13+0x40,low);  
  415.                           LCD1602_WriteCom(0x80+0x4F);  
  416. //                        LCD1602_WriteCom(0x80+0x40+13);                             
  417.                     }  
  418.                 }  
  419.             }  
  420.         }  
  421. }  
  422.   
  423. void key3_minus()//功能减  
  424. {  
  425.         if(k_num!=0)  
  426.         {  
  427.             if(k3==0)  
  428.             {  
  429.                 Delay1us(5);  
  430.                 if(k3==0)  
  431.                 {  
  432.                     while(!k3);  
  433.                     if(k_num==1)  
  434.                     {  
  435.                         if (set_t<=0)  
  436.                         set_t=high+1;  
  437.                         set_t--;  
  438.   
  439.                           LCD1602_SetTemp(4+0x40,set_t);  
  440.                           LCD1602_WriteCom(0x80+0x46);                                        
  441.                     }  
  442.                     if(k_num==2)  
  443.                     {  
  444.                         if (set_d<=0)  
  445.                          set_d=10;  
  446.                         set_d--;  
  447.   
  448.                         LCD1602_WriteCom(0x80+0x48);  
  449.                         LCD1602_WriteData(0x30+set_d);  
  450.                         LCD1602_WriteCom(0x80+0x48);                                          
  451.                     }  
  452.                     if(k_num==3)  
  453.                     {  
  454.                         if (high<0)  
  455.                          high=temp_max;  
  456.                         high--;  
  457.                           LCD1602_SetTemp(13,high);  
  458.                           LCD1602_WriteCom(0x80+0x0F);  
  459. //                        LCD1602_WriteCom(0x80+0x40+8);                                          
  460.                     }  
  461.   
  462.                     if(k_num==4)  
  463.                     {  
  464.                         if (low<=0)  
  465.                         low=high;  
  466.                         low--;  
  467.   
  468.                           LCD1602_SetTemp(13+0x40,low);  
  469.                           LCD1602_WriteCom(0x80+0x4F);  
  470. //                        LCD1602_WriteCom(0x80+0x40+16);                             
  471.                     }  
  472.                 }  
  473.             }  
  474.         }     
  475. }  
  476. void keyscan()//按键检测  
  477. {  
  478.       key1_switch();  
  479.       key2_add();  
  480.       key3_minus();  
  481. }  
  482.   
  483. void LCD1602_SetTemp(uchar add,uchar dat)//数码管制定位置显示  
  484. {  
  485.       uchar head,body,end;  
  486.       head=dat/100;  
  487.       body=dat%100/10;  
  488.       end=dat%10;  
  489.       LCD1602_WriteCom(0x80+add);  
  490.       LCD1602_WriteData(0x30+head);  
  491.       LCD1602_WriteData(0x30+body);  
  492.       LCD1602_WriteData(0x30+end);  
  493. }  
  494.   
  495.   
  496. void main()  
  497. {  
  498.   
  499.     LCD1602_Init();  
  500.     while(1)  
  501.     {  
  502.         keyscan();                
  503.     }  
  504. }  
  505. void timer0() interrupt 1  
  506. {  
  507.     TH0=(65536-50000)/256;  
  508.     TL0=(65536-50000)%256;  
  509.     count++;  
  510.         if (count==10)//让温度每0.5s刷新一次  
  511.         {  
  512.             count=0;  
  513.             LCD1602_ShowTemp(Ds18b20ReadTemp());  
  514.         }  
  515. }  
1

路过

鸡蛋

鲜花

握手

雷人

刚表态过的朋友 (1 人)

评论 (0 个评论)

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

Powered by 单片机教程网

返回顶部