找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机智能温控风扇控制源码

[复制链接]
跳转到指定楼层
楼主
智能风扇,按键调节温度上下限,根据温度变化风扇有三个档位。

电路原理图如下:


单片机源程序如下:
  1. #include <reg52.h>             //调用单片机头文件
  2. #define uchar unsigned char  //无符号字符型 宏定义    变量范围0~255
  3. #define uint  unsigned int     //无符号整型 宏定义    变量范围0~65535
  4. #include <intrins.h>

  5. sbit dq   = P1^5;    //18b20 IO口的定义

  6. uint temperature ;  //
  7. bit flag_200ms ;

  8. bit flag_lj_en;         //按键连加使能
  9. bit flag_lj_3_en;     //按键连3次连加后使能  加的数就越大了
  10. uchar key_time,key_value;      //用做连加的中间变量
  11. bit key_500ms  ;


  12. uchar code table_num[]="0123456789abcdefg";

  13. sbit rs=P1^0;     //寄存器选择信号 H:数据寄存器      L:指令寄存器
  14. sbit rw=P1^1;     //寄存器选择信号 H:数据寄存器      L:指令寄存器
  15. sbit e =P1^2;     //片选信号   下降沿触发

  16. sbit pwm = P1^4;  
  17. uchar f_pwm_l ;      //

  18. uchar menu_1;        //菜单设计的变量
  19. uint t_high = 300,t_low = 100;


  20. /***********************1ms延时函数*****************************/
  21. void delay_1ms(uint q)
  22. {
  23.     uint i,j;
  24.     for(i=0;i<q;i++)
  25.         for(j=0;j<110;j++);
  26. }

  27. /********************************************************************
  28. * 名称 : delay_uint()
  29. * 功能 : 小延时。
  30. * 输入 : 无
  31. * 输出 : 无
  32. ***********************************************************************/
  33. void delay_uint(uint q)
  34. {
  35.     while(q--);
  36. }

  37. /********************************************************************
  38. * 名称 : write_com(uchar com)
  39. * 功能 : 1602命令函数
  40. * 输入 : 输入的命令值
  41. * 输出 : 无
  42. ***********************************************************************/
  43. void write_com(uchar com)
  44. {
  45.     e=0;
  46.     rs=0;
  47.     rw=0;
  48.     P0=com;
  49.     delay_uint(25);
  50.     e=1;
  51.     delay_uint(100);
  52.     e=0;
  53. }

  54. /********************************************************************
  55. * 名称 : write_data(uchar dat)
  56. * 功能 : 1602写数据函数
  57. * 输入 : 需要写入1602的数据
  58. * 输出 : 无
  59. ***********************************************************************/
  60. void write_data(uchar dat)
  61. {
  62.     e=0;
  63.     rs=1;
  64.     rw=0;
  65.     P0=dat;
  66.     delay_uint(25);
  67.     e=1;
  68.     delay_uint(100);
  69.     e=0;   
  70. }

  71. /********************************************************************
  72. * 名称 : write_string(uchar hang,uchar add,uchar *p)
  73. * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
  74.           write_string(1,5,"ab cd ef;")
  75. * 输入 : 行,列,需要输入1602的数据
  76. * 输出 : 无
  77. ***********************************************************************/
  78. void write_string(uchar hang,uchar add,uchar *p)
  79. {
  80.     if(hang==1)   
  81.         write_com(0x80+add);
  82.     else
  83.         write_com(0x80+0x40+add);
  84.     while(1)
  85.     {
  86.         if(*p == '\0')  break;
  87.         write_data(*p);
  88.         p++;
  89.     }   
  90. }

  91. /***********************lcd1602上显示特定的字符************************/
  92. void write_zifu(uchar hang,uchar add,uchar date)
  93. {
  94.     if(hang==1)   
  95.         write_com(0x80+add);
  96.     else
  97.         write_com(0x80+0x40+add);
  98.     write_data(date);   
  99. }

  100. /***********************lcd1602上显示两位十进制数************************/
  101. void write_sfm3_18B20(uchar hang,uchar add,uint date)
  102. {
  103.     if(hang==1)   
  104.         write_com(0x80+add);
  105.     else
  106.         write_com(0x80+0x40+add);
  107.     write_data(0x30+date/100%10);
  108.     write_data(0x30+date/10%10);
  109.     write_data('.');
  110.     write_data(0x30+date%10);   
  111. }

  112. /***********************lcd1602初始化设置************************/
  113. void init_1602()
  114. {
  115.     write_com(0x38);    //
  116.     write_com(0x0c);
  117.     write_com(0x06);
  118.     delay_uint(1000);
  119.     write_string(1,0,"   temp:  .          ");   
  120.     write_string(2,0,"H:    L:        ");
  121.     write_sfm3_18B20(2,2,t_high);   
  122.     write_sfm3_18B20(2,10,t_low);               
  123.     write_zifu(1,12,0xdf);  //显示度   
  124. }

  125. /***********************18b20初始化函数*****************************/
  126. void init_18b20()
  127. {
  128.     bit q;
  129.     dq = 1;                //把总线拿高
  130.     delay_uint(1);        //15us
  131.     dq = 0;                //给复位脉冲
  132.     delay_uint(80);        //750us
  133.     dq = 1;                //把总线拿高 等待
  134.     delay_uint(10);        //110us
  135.     q = dq;                //读取18b20初始化信号
  136.     delay_uint(20);        //200us
  137.     dq = 1;                //把总线拿高 释放总线
  138. }

  139. /*************写18b20内的数据***************/
  140. void write_18b20(uchar dat)
  141. {
  142.     uchar i;
  143.     for(i=0;i<8;i++)
  144.     {                     //写数据是低位开始
  145.         dq = 0;             //把总线拿低写时间隙开始
  146.         dq = dat & 0x01; //向18b20总线写数据了
  147.         delay_uint(5);     // 60us
  148.         dq = 1;             //释放总线
  149.         dat >>= 1;
  150.     }   
  151. }

  152. /*************读取18b20内的数据***************/
  153. uchar read_18b20()
  154. {
  155.     uchar i,value;
  156.     for(i=0;i<8;i++)
  157.     {
  158.         dq = 0;             //把总线拿低读时间隙开始
  159.         value >>= 1;     //读数据是低位开始
  160.         dq = 1;             //释放总线
  161.         if(dq == 1)         //开始读写数据
  162.             value |= 0x80;
  163.         delay_uint(5);     //60us    读一个时间隙最少要保持60us的时间
  164.     }
  165.     return value;         //返回数据
  166. }


  167. /*************读取温度的值 读出来的是小数***************/
  168. uint read_temp()
  169. {
  170.     uint value;
  171.     uchar low;               //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
  172.     init_18b20();           //初始化18b20

  173.     write_18b20(0xcc);       //跳过64位ROM
  174.     write_18b20(0x44);       //启动一次温度转换命令


  175.     init_18b20();           //初始化18b20

  176.     write_18b20(0xcc);       //跳过64位ROM
  177.     write_18b20(0xbe);       //发出读取暂存器命令

  178.     low = read_18b20();       //读温度低字节
  179.     value = read_18b20();  //读温度高字节

  180.     value <<= 8;           //把温度的高位左移8位
  181.     value |= low;           //把读出的温度低位放到value的低八位中
  182.     value *= 0.625;           //转换到温度值 小数
  183.     return value;           //返回读出的温度 带小数
  184. }

  185. /*************定时器0初始化程序***************/
  186. void time_init()      
  187. {
  188.     EA   = 1;           //开总中断
  189.     TMOD = 0X01;      //定时器0、定时器1工作方式1
  190.     ET0  = 1;          //开定时器0中断
  191.     TR0  = 1;          //允许定时器0定时
  192.     ET1  = 0;          //开定时器0中断
  193.     TR1  = 0;          //允许定时器0定时
  194. }

  195. /********************独立按键程序*****************/
  196. uchar key_can;     //按键值

  197. void key()         //独立按键程序
  198. {
  199.     static uchar key_new;
  200.     key_can = 20;               //按键值还原
  201.     if(key_500ms == 1)    //连加
  202.     {
  203.         key_500ms = 0;
  204.         key_new = 1;
  205.     }
  206.     if((P3 & 0xf0) != 0xf0)        //按键按下
  207.     {
  208.         delay_1ms(1);             //按键消抖动
  209.         if(((P3 & 0xf0) != 0xf0) && (key_new == 1))
  210.         {                        //确认是按键按下
  211.             key_new = 0;
  212.             switch(P3 & 0xf0)
  213.             {
  214.                 case 0xe0: key_can = 1; break;       //得到k1键值
  215.                 case 0xd0: key_can = 2; break;       //得到K2键值
  216.                 case 0xb0: key_can = 3; break;       //得到k3键值
  217.             }
  218.             flag_lj_en = 1;     //连加使能
  219.         }            
  220.     }
  221.     else
  222.     {
  223.             key_new = 1;
  224.     }   
  225. }


  226. /****************按键显示函数***************/
  227. void key_with()
  228. {
  229.     if(key_can == 1)       //设置键
  230.     {
  231.         menu_1 ++;
  232.         if(menu_1 >= 1)
  233.         {
  234.             menu_1 = 0;
  235.         }
  236.         if(menu_1 == 0)
  237.         {
  238.             write_com(0x0c);                //关闭光标
  239.         }
  240.     }
  241.     if(menu_1 == 1)            //设置高温报警
  242.     {
  243.         if(key_can == 2)
  244.         {
  245.             if(flag_lj_3_en == 0)
  246.                 t_high ++ ;        //按键按下未松开自动加三次   
  247.             else
  248.                 t_high += 10;    //按键按下未松开自动加三次之后每次自动加10
  249.             if(t_high > 990)
  250.                 t_high = 990;
  251.         }
  252.         if(key_can == 3)
  253.         {
  254.             if(flag_lj_3_en == 0)
  255.                 t_high -- ;        //按键按下未松开自动减三次   
  256.             else
  257.                 t_high -= 10;    //按键按下未松开自动减三次之后每次自动减10
  258.             if(t_high <= t_low)
  259.                 t_high = t_low + 1;
  260.         }        
  261.         write_sfm3_18B20(2,2,t_high);
  262.         write_com(0x80+0x40+2);             //将光标移动到秒个位
  263.         write_com(0x0f);                    //显示光标并且闪烁   
  264.     }   
  265.     if(menu_1 == 2)            //设置低温报警
  266.     {
  267.         if(key_can == 2)
  268.         {
  269.             if(flag_lj_3_en == 0)
  270.                 t_low ++ ;            //按键按下未松开自动加三次   
  271.             else
  272.                 t_low += 10;        //按键按下未松开自动加三次之后每次自动加10
  273.             if(t_low >= t_high)
  274.                 t_low = t_high - 1;
  275.         }
  276.         if(key_can == 3)
  277.         {
  278.             if(flag_lj_3_en == 0)
  279.                 t_low -- ;            //按键按下未松开自动减三次   
  280.             else
  281.                 t_low -= 10;        //按键按下未松开自动加三次之后每次自动加10
  282.             if(t_low <= 10)
  283.                 t_low = 10;
  284.         }
  285.         write_sfm3_18B20(2,10,t_low);
  286.         write_com(0x80+0x40+10);            //将光标移动到秒个位
  287.         write_com(0x0f);                    //显示光标并且闪烁   
  288.     }   
  289. }

  290. /****************风扇控制函数***************/
  291. void fengshan_kz()
  292. {
  293.     if(temperature >= t_high)      //风扇全开
  294.     {   
  295.         TR1 = 1;
  296.         pwm = 0;
  297.     }
  298.     else if((temperature < t_high)    && (temperature >= t_low))           //风扇缓慢
  299.     {
  300.         f_pwm_l = 60;     
  301.         TR1 = 1;
  302.     }
  303.     else if(temperature < t_low)     //关闭风扇
  304.     {
  305.         TR1 = 0;
  306.         pwm = 1;
  307.     }            
  308. }        

  309. /****************主函数***************/
  310. void main()
  311. {   
  312.     time_init();                    //初始化定时器
  313.     init_1602();                    //1602初始化
  314.     while(1)
  315.     {        
  316.         temperature = read_temp();    //先读出温度的值
  317.         write_sfm3_18B20(1,8,temperature);            
  318.         fengshan_kz();        //风扇控制函数

  319.         key();                    //按键程序
  320.         if(key_can < 10)
  321.         {
  322.             key_with();                //设置报警温度   
  323.         }
  324.     }
  325. }

  326. /*************定时器0中断服务程序***************/
  327. void time0_int() interrupt 1
  328. {   
  329.     static uchar value;
  330.     TH0 = 0x0c;
  331.     TL0 = 0xb0;     // 50ms
  332.     value ++;     
  333.     if(value % 4 == 0)
  334.     {
  335.         flag_200ms = 1;       //300ms
  336.         value = 0;
  337.     }

  338.     if(flag_lj_en == 1)       //按下按键使能
  339.     {
  340.         key_time ++;
  341.         if(key_time >= 10) //500ms
  342.         {
  343.             key_time = 0;
  344.             key_500ms = 1; //500ms
  345.             key_value ++;
  346.             if(key_value > 3)
  347.             {
  348.                 key_value = 10;
  349.                 flag_lj_3_en = 1; //3次后1.5秒连加大些
  350.             }                        
  351.         }
  352.     }
  353. }

  354. /*******************定时器1用做单片机模拟PWM 调节***********************/
  355. void Timer1() interrupt 3  //调用定时器1
  356. {
  357.     static uchar value_l;
  358.     TH1=0x3c;    //  
  359.     TL1=0xb0;     //
  360.     if(pwm==1)
  361.     {
  362.         value_l+=1;
  363.         if(value_l > f_pwm_l)   //高电平
  364.         {
  365.         
  366.                 pwm=0;     
  367.         }
  368.     }
  369.     else               
  370.     {
  371.         value_l+=1;
  372.         if(value_l  > f_pwm_l)          //低电平
  373.         {
  374.             pwm=1;
  375.         }
  376.     }
  377. }
复制代码

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

使用道具 举报

沙发
ID:853393 发表于 2020-12-9 09:47 | 只看该作者
好的一匹,99999
回复

使用道具 举报

板凳
ID:321836 发表于 2021-5-1 22:05 | 只看该作者
程序被阉割掉了一部分。。。
回复

使用道具 举报

地板
ID:81441 发表于 2023-4-3 12:48 | 只看该作者
仿真结果不一样,没有档位,按键不能进行设置,只能显示测量温度。

5566.png (119.7 KB, 下载次数: 82)

5566.png
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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