找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机温控风扇程序

[复制链接]
跳转到指定楼层
楼主
ID:531648 发表于 2019-5-27 08:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include < reg51.h >
  2. #include < intrins.h >

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

  5. //#define lcddata P0
  6. #define lcddata P1
  7. sbit dj=P3^3;
  8. sbit LCDRS=P2^7;              
  9. sbit LCDRW=P2^6;            
  10. sbit LCDEN=P2^5;            
  11. sbit key1=P3^5;//控制温度
  12. sbit key2=P3^6;//温度加1
  13. sbit key3=P3^7;//温度减1
  14. void write_com(uchar com);
  15. void zdyzfxs();
  16. unsigned char code   mytab[8] = {0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00} ;
  17. sbit DQ = P3^4;//定义DS18B20端口DQ
  18. bit presence;           //ds18b20 DQ被拉低 信号0允许,1禁止
  19. uint cc,cc2;//变量cc中保存读出的温度值
  20. float cc1;
  21. uchar flag;//温度值正负,1负0正
  22. uint shang,xia;//对比温度暂存变量
  23. uchar dang;//档位显示
  24. uchar flagg;
  25. uchar d1,d2,d3;//显示数据暂存变量
  26. void write_com(uchar com);

  27. uchar code cdis0[ ] = "CHECKING";
  28. uchar code cdis1[ ] = "  on   " ;
  29. uchar code cdis5[ ] = "wendu: ";
  30. uchar  cdis2[ ] = "+00.00";
  31. uchar  cdis9[ ] = "00";
  32. uchar  cdis10[ ] = "00";
  33. uchar  cdis11[ ] = "0";
  34. uchar code cdis6[ ] = "H:";
  35. uchar code cdis7[ ] = "L:";
  36. uchar code cdis8[ ] = "dang:";
  37. uchar code cdis3[ ] = " DS18B20   BUSY " ;
  38. uchar code cdis4[ ] = "   PLEASE CHECK  " ;

  39. unsigned char data   temp_data[2] = {0x00,0x00} ;
  40. //----------------------------------
  41. void delaylcd(uint z)
  42. {uchar x,y;
  43. for(x=z;x>0;x--)
  44.   {for(y=110;y>0;y--);
  45.   }
  46. }
  47. /*lcd1602初始化        */
  48. void lcd_init(void)
  49. {
  50. LCDRW=0;                 //低电平为写
  51. LCDEN=0;
  52. write_com(0x38);                 //使用8位数据开关,显示两行,使用5*7字形

  53. write_com(0x0c);                //显示器开,光标关,字符不闪烁         0x0e 光标开

  54. write_com(0x06);           //字符不动,光标自动右移动一位

  55. write_com(0x01);          //清屏
  56. }

  57. /*写命令to lcd        */
  58. /**********************************/
  59. void write_com(uchar com)//写命令
  60. {
  61.   LCDRW=0;         //低电平为写
  62.   LCDRS=0;         //低电平为命令选择
  63.   lcddata=com;
  64.   delaylcd(5);
  65.   LCDEN=1;
  66.   delaylcd(5);
  67.   LCDEN=0;
  68. }

  69. /*写数据to lcd             */
  70. /**********************************/
  71. void write_data(uchar  date)
  72. {
  73. LCDRW=0;  //低电平为写
  74. LCDRS=1;  //高电平为数据选择
  75. lcddata=date;
  76. delaylcd(5);
  77. LCDEN=1;
  78. delaylcd(5);
  79. LCDEN=0;
  80. }

  81. /*设定显示位置             */
  82. /********************************/
  83. void lcd_pos(uchar pos)
  84. {                                    //第一行第几列直接写pos为几,第二行pos从0x40开始
  85.    write_com(pos | 0x80) ;   //数据指针=80+地址变量
  86. }
  87. /*自定义字符写入CGRAM      */
  88. /*********************************/
  89. void mywritetab()  
  90. {  
  91.      unsigned char i ;
  92.      write_com(0x40) ;             //写CGRAM
  93.      for(i=0;i<8;i++)
  94.          {write_data(mytab[i]);}                                                                                                                                                                                                                                                                                                                                                
  95. }

  96. /*******************************ds18b20*******************************************/
  97. /*ms级别      */
  98. void ddelay(uint ms)
  99. {
  100. uint i;
  101. uchar j;
  102. for(i=0;i<ms;i++)
  103.    for(j=0;j<250;j++)
  104.    {
  105.     _nop_();          //一个机器周期,1us
  106.            _nop_();          //适用于精度高的
  107.         _nop_();
  108.     _nop_();
  109.    }
  110. }
  111. /*us级延时,延时时间约4+2*i*/
  112. void Delayus(uchar i)
  113. {
  114.   while(--i);
  115. }
  116. /*复位,每次读写之前都要进行复位*/
  117. /**********************************/
  118. bit ow_reset(void)
  119. {
  120. DQ = 1 ;       //DQ复位
  121. Delayus(8) ;     //稍做延时

  122. DQ = 0; //拉低约600us
  123. Delayus(150);
  124. Delayus(150);

  125. DQ = 1;//产生上升沿,延时约15~60us
  126. Delayus(30);

  127. if(DQ==0) {presence=0;}         
  128. else presence=1;
  129. return(presence); //等待应答信号 0允许,1禁止
  130. }

  131. /*读取数据一位            */
  132. //---------------------------------
  133. bit Read_bit()
  134. {
  135. uint i = 0;
  136. bit b = 0;

  137. DQ = 0; //产生读时隙  
  138. i++;         //维持低电平至少1us

  139. DQ = 1; //1us以上后拉高
  140. Delayus(2); //延时8us,DO下降沿15内ds18b20输出的数据才有效


  141. b = DQ; //读取数据
  142. Delayus(40);         //每个读时隙至少持续60us

  143. return(b);
  144. }

  145. /*读取一个字节             */
  146. //------------------------------------
  147. uchar Read_byte()
  148. {
  149. uchar byte_read = 0;
  150. uchar i, j;

  151. for(i=0; i<8; i++)
  152.   {
  153.    j = Read_bit();
  154.    byte_read = (j<<i) | byte_read; //低位读起
  155.   }

  156. return(byte_read);
  157. }

  158. //-----------------------------------------
  159. /*写一个字节         */
  160. void Write_byte(uchar byte_to_write)
  161. {
  162. uchar i = 0;
  163. uchar j = 0;
  164. bit write_bit = 0;

  165. for(j=0; j<8; j++)
  166.   {
  167.    write_bit =         (byte_to_write & 0x01);
  168.     if(write_bit == 1) //写1
  169.          {
  170.           DQ = 0;  //产生写时隙
  171.          Delayus(3);           //延时15us

  172.           DQ = 1;  //写1
  173.           Delayus(40);   //延时,写时隙不得低于60us
  174.          }
  175.         else
  176.          {
  177.           DQ = 0;  //产生写时隙
  178.           Delayus(50);   //延时,保持低约60us~120us
  179.           DQ = 1;  
  180.           i++;
  181.          }
  182.    byte_to_write = byte_to_write >> 1;
  183.   }
  184. }
  185. //-----------------------------------
  186. /*读取温度,启动温度转换*/
  187. /*启动温度转换*/
  188. void start_convert()
  189. {
  190. ow_reset();          // 发出复位脉冲,每次操作都从复位开始
  191. ddelay(1);
  192. Write_byte(0xcc); //skip room命令,跳过序列号命令字
  193. Write_byte(0x44); //启动温度转换命令
  194. }

  195. /*读取温度值*/
  196. void read_tempreture()
  197. {
  198. ow_reset();          // 发出复位脉冲,每次操作都从复位开始
  199. ddelay(1);
  200. Write_byte(0xcc); //skip room命令
  201. Write_byte(0xbe); //读取暂存器命令
  202. temp_data[0] = Read_byte(); //存储温度低字节值 (整数部分低四位和小数部分) 先从低字节读取
  203. temp_data[1] = Read_byte(); //存储温度高字节值 (其中高五位为符号位)
  204. }
  205. //--------------------------------------
  206. /* CHECKING...显示              */
  207. void lcd_display()
  208. {
  209. uchar   m ;
  210. lcd_init() ;                 //初始化LCD
  211. lcd_pos(0) ;                 //设置显示位置为第一行的第1个字符
  212.       m = 0 ;
  213.      while(cdis0[m] != '\0')
  214.       {                          //显示字符
  215.         write_data(cdis0[m]) ;
  216.         m++ ;
  217.       }
  218. }

  219. //--------------------------------------
  220. /* DS18B20 OK 显示菜单                 */
  221. void Ok_Menu ()
  222. {
  223.      uchar   m ;
  224.      lcd_init() ;                 //初始化LCD            
  225.      lcd_pos(0) ;                 //设置显示位置为第一行的第1个字符
  226.       m = 0 ;
  227.      while(cdis1[m] != '\0')
  228.       {                          //显示字符
  229.         write_data(cdis1[m]) ;
  230.         m++ ;
  231.       }         
  232. }

  233. //-----------------------------------
  234. /*DS18B20   ERR0R          */
  235. /*PLEASE   CHECK  显示    */
  236. void Error_Menu ()
  237. {
  238.       uchar   m ;
  239.       lcd_init() ;                 //初始化LCD

  240.       lcd_pos(0) ;                 //设置显示位置为第一行的第1个字符
  241.       m = 0 ;
  242.       while(cdis3[m] != '\0')
  243.       {                          
  244.         write_data(cdis3[m]) ;           //显示字符
  245.         m++ ;
  246.       }

  247.       lcd_pos(0x40) ;              //设置显示位置为第二行第1个字符
  248.       m = 0 ;
  249.       while(cdis4[m] != '\0')
  250.       {
  251.         write_data(cdis4[m]) ;       //显示字符
  252.         m++ ;
  253.       }
  254. }

  255. //------------------------------------
  256. /*Temp:      ℃显示        */
  257. void temp_c()
  258. {
  259.   uchar m;
  260.   lcd_init() ;
  261.   lcd_pos(0);
  262.   m=0;
  263.   while(cdis5[m]!='\0')
  264.   {
  265.    write_data(cdis5[m]);
  266.    m++;
  267.   }

  268. //  write_data(0xDF);                //°
  269. zdyzfxs();lcd_pos(13);                  
  270.   write_data('C');
  271. }

  272. //-----------------------------------
  273. /*自定义字符显示    */
  274. void zdyzfxs()
  275. {
  276. mywritetab();
  277. lcd_pos(12);
  278. write_data(0x00);
  279. }
  280. //显示上下限
  281. void shangxian()
  282. {
  283. uchar m;
  284. cdis9[0]=shang/10+0x30;
  285. if(cdis9[0]==0x30)
  286.    {cdis9[0]=0x20;
  287.    }
  288.    cdis9[1]=shang%10+0x30;
  289.   lcd_pos(0x42);                            //显示字母H 和上限温度值
  290.   m=0;
  291.   while(cdis9[m]!='\0')
  292.   {
  293.    write_data(cdis9[m]);                    //调用显示函数
  294.    m++;
  295.   }
  296. }
  297. void dangwei()
  298. {
  299. uchar m;
  300. cdis11[0]=dang+0x30;

  301.   lcd_pos(0x4f);                            //显示字母H 和上限温度值
  302.   m=0;
  303.   while(cdis11[m]!='\0')
  304.   {
  305.    write_data(cdis11[m]);                    //调用显示函数
  306.    m++;
  307.   }
  308. }

  309. void xiaxian()
  310. {
  311. uchar m;
  312.    cdis10[0]=xia/10+0x30;
  313. if(cdis10[0]==0x30)
  314.    {cdis10[0]=0x20;
  315.    }
  316.    cdis10[1]=xia%10+0x30;
  317.   lcd_pos(0x47);                            //显示字母H 和上限温度值
  318.   m=0;
  319.   while(cdis10[m]!='\0')
  320.   {
  321.    write_data(cdis10[m]);                    //调用显示函数
  322.    m++;
  323.   }
  324. }                              

  325. void zi_keyscan()//自动模式按键扫描函数
  326. {
  327. if(key1==0)         //设置键按下
  328. {
  329.   Delayus(10);        //延时去抖
  330.   if(key1==0)flagg=1;      //再次判断按键,按下的话进入设置状态
  331.   while(key1==0);//松手检测    //按键释放
  332. }
  333. while(flagg==1)        //进入设置上限状态
  334. {

  335.   if(key1==0)        //判断设置键是否按下                                 
  336.   {
  337.    Delayus(10);       //延时去抖
  338.    if(key1==0)flagg=2;     //按键按下,进入设置下限模式
  339.    while(key1==0);//松手检测
  340.   }
  341.   if(key2==0)        //加键按下
  342.   {
  343.    Delayus(10);       //延时去抖
  344.    if(key2==0)       //加键按下
  345.    {
  346.     shang++;      //上限加5
  347.     if(shang>=100)shang=100;  //上限最大加到100
  348.    }while(key2==0);//松手检测
  349.   }
  350.   if(key3==0)        //减键按下
  351.   {
  352.    Delayus(10);       //延时去抖
  353.    if(key3==0)       //减键按下
  354.    {
  355.     shang--;      //上限减1
  356.     if(shang<=10)shang=10;   //上限最小减到10
  357.    }while(key3==0);//松手检测
  358.   }
  359.   shangxian();
  360. }
  361. while(flagg==2)        //设置下限
  362. {
  363.    //显示字母L 显示下限温度值
  364.       //以下注释同上
  365.   if(key1==0)
  366.   {
  367.    Delayus(10);
  368.    if(key1==0)flagg=0;
  369.    while(key1==0);//松手检测
  370.   }
  371.   if(key2==0)
  372.   {
  373.    Delayus(10);
  374.    if(key2==0)
  375.    {
  376.     xia+=1;
  377.     if(xia>=99)xia=99;
  378.    }while(key2==0);//松手检测
  379.   }
  380.   if(key3==0)
  381.   {
  382.    Delayus(10);
  383.    if(key3==0)
  384.    {
  385.     xia-=1;
  386.     if(xia<=0)xia=0;
  387.    }while(key3==0);//松手检测
  388.   }
  389.   xiaxian();  
  390. }
  391. /* while(flagg==0)        //设置下限
  392. {
  393.    //显示字母L 显示下限温度值
  394.   if(key1==0)
  395.   {
  396.    Delayus(10);
  397.    if(key1==0)flagg=1;
  398.    while(key1==0);//松手检测
  399.   }
  400.   }*/
  401. }
  402. void zi_dong()//自动温控模式
  403. {
  404. uchar i;
  405. //dangwei();
  406. zi_keyscan();//按键扫描函数
  407.                                 //调用显示函数
  408.   //调用显示函数
  409. if(cc1<xia){dj=0;dang=0;}//低于下限  档位为0 电机停止
  410.   dangwei();
  411. if((cc1>=xia)&&(cc1<=shang))//温度大于下限,小于上限  1挡
  412. {
  413.   dang=1;           //档位置1
  414.   for(i=0;i<3;i++){dj=0;dangwei();zi_keyscan();} //PWM通过延时得到
  415.   for(i=0;i<6;i++){dj=1;dangwei();zi_keyscan();}  
  416. }
  417. if(cc1>shang){dj=1;dang=2;}//高温全速
  418. dangwei();
  419. }  
  420. //------------------------------------
  421. /*温度显示                       */
  422. void temperature_display()
  423. {
  424.   uchar m;

  425.   flag=0;

  426.     ddelay(2);
  427.     EA=0;                                //DS18B20读写数据按照严格的时序,最好不要被打断,故把所有中断关闭
  428.         start_convert();                          //启动温度转换
  429.     ddelay(250);
  430.         read_tempreture();                          //读取温度
  431.     EA=1;
  432.         cc=temp_data[1]*256.0+temp_data[0];
  433.         if(temp_data[1]>0xF8) {flag=1;cc=~cc+1;} else flag=0;
  434.         cc1=cc*0.0625;
  435.         cc2=cc1*100;
  436.         cdis2[1]=cc2/1000+0x30;
  437.         if(cdis2[1]==0x30)
  438.          {cdis2[1]=0x20;}
  439.         cdis2[2]=cc2/100%10+0x30;
  440.         cdis2[4]=cc2%100/10+0x30;
  441.     cdis2[5]=cc2%10+0x30;
  442.         if(flag==1)
  443.            cdis2[0]='-';
  444.         else
  445.            cdis2[0]='+';

  446.          lcd_pos(6) ;                 //设置显示位置为第一行的第6个字符
  447.      m=0;
  448.      while(cdis2[m]!='\0')
  449.       {                          //显示字符
  450.         write_data(cdis2[m]) ;
  451.                 m++;
  452.       }

  453.                                                                         

  454. }


  455. void test()
  456. {
  457.   uchar m;


  458.   lcd_pos(0x40);
  459.   m=0;
  460.   while(cdis6[m]!='\0')
  461.   {
  462.    write_data(cdis6[m]);
  463.    m++;
  464.   }

  465.   lcd_pos(0x45);
  466.   m=0;
  467.   while(cdis7[m]!='\0')
  468.   {
  469.    write_data(cdis7[m]);
  470.    m++;
  471.   }

  472.   lcd_pos(0x4B);
  473.   m=0;
  474.   while(cdis8[m]!='\0')
  475.   {
  476.    write_data(cdis8[m]);
  477.    m++;
  478.   }

  479. }


  480. //---------------------------------         
  481. /*主函数             */
  482. void main()
  483. {
  484.   uchar j;
  485.   shang=30;
  486.   xia=20;
  487.   lcd_display();
  488.   ddelay(100);
  489.   ow_reset();
  490.   if(presence==0)
  491.     {
  492.           Ok_Menu ();
  493.          ddelay(100);
  494.          temp_c();zdyzfxs();
  495.                  test();
  496.                   shangxian();xiaxian();

  497.         while(1)
  498.     {
  499.          temperature_display(); //读取温度值
  500.          for(j=0;j<100;j++) zi_dong();  
  501.     }

  502.     }
  503.   else
  504.     {
  505.          Error_Menu ();
  506.          while(1)
  507.          {
  508.           ow_reset();
  509.           if(presence==0)
  510.            {
  511.                 Ok_Menu ();
  512.             ddelay(1000);
  513.             temperature_display();
  514.            }
  515.          }
  516.     }
  517. }
复制代码
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2019-6-1 04:24 | 只看该作者
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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