找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1791|回复: 0
收起左侧

温控风扇的单片机源码

[复制链接]
ID:253484 发表于 2017-11-25 16:41 | 显示全部楼层 |阅读模式

  1. #include <reg52.h>          //调用单片机头文件
  2. #define uchar unsigned char  //无符号字符型 宏定义 变量范围0~255
  3. #define uint  unsigned int  //无符号整型 宏定义 变量范围0~65535
  4. #include "eeprom52.h"
  5. //数码管段选定义      0     1    2    3    4    5 6  7   8    9
  6. uchar code smg_du[]={0x28,0xee,0x32,0xa2,0xe4,0xa1,0x21,0xea,0x20,0xa0,
  7.         0x60,0x25,0x39,0x26,0x31,0x71,0xff};  //断码
  8. //数码管位选定义
  9. uchar code smg_we[]={0xef,0xdf,0xbf,0x7f};
  10. uchar dis_smg[8] = {0x28,0xee,0x32,0xa2,0xe4,0x92,0x82,0xf8};
  11. uchar smg_i = 3;    //显示数码管的个位数
  12. sbit dq   = P2^4; //18b20 IO口的定义
  13. bit flag_lj_en;   //按键连加使能
  14. bit flag_lj_3_en;  //按键连3次连加后使能  加的数就越大了
  15. uchar key_time,key_value;      //用做连加的中间变量
  16. bit key_500ms  ;
  17. sbit pwm = P2^3;  
  18. uchar f_pwm_l ;   //越小越暗
  19. uint temperature ;  //
  20. bit flag_300ms ;
  21. uchar menu_1;       //菜单设计的变量
  22. uint t_high = 300,t_low = 100;    //温度上下限报警值
  23. uint number;
  24. /***********************1ms延时函数*****************************/
  25. void delay_1ms(uint q)
  26. {
  27. uint i,j;
  28. for(i=0;i<q;i++)
  29.   for(j=0;j<120;j++);
  30. }
  31. /***********************小延时函数*****************************/
  32. void delay_uint(uint q)
  33. {
  34. while(q--);
  35. }

  36. /***********************数码显示函数*****************************/
  37. void display()
  38. {
  39. static uchar i;   
  40. i++;
  41. if(i >= smg_i)
  42.   i = 0;
  43. P1 = 0xff;    //消隐
  44. P3 = smg_we[i];     //位选
  45. P1 = dis_smg[i];   //段选         
  46. }
  47. /******************把数据保存到单片机内部eepom中******************/
  48. void write_eeprom()
  49. {
  50. SectorErase(0x2000);
  51. byte_write(0x2000, t_high % 256);
  52. byte_write(0x2001, t_high / 256);
  53. byte_write(0x2002, t_low % 256);
  54. byte_write(0x2003, t_low / 256);
  55. byte_write(0x2055, a_a);
  56. }
  57. /******************把数据从单片机内部eepom中读出来*****************/
  58. void read_eeprom()
  59. {
  60. t_high  = byte_read(0x2001);
  61. t_high <<= 8;
  62. t_high  |= byte_read(0x2000);
  63. t_low   = byte_read(0x2003);
  64. t_low <<= 8;
  65. t_low   |= byte_read(0x2002);
  66. a_a      = byte_read(0x2055);
  67. }
  68. /**************开机初始化保存的数据*****************/
  69. void init_eeprom()
  70. {
  71. read_eeprom();  //先读
  72. if(a_a != 22)  //新的单片机初始单片机内问eeprom
  73. {
  74.   t_high = 250;
  75.   t_low  = 200;
  76.   a_a = 22;
  77.   write_eeprom();    //保存数据
  78. }
  79. }

  80. /***********************18b20初始化函数*****************************/
  81. void init_18b20()
  82. {
  83. bit q;
  84. dq = 1;    //把总线拿高
  85. delay_uint(1);     //15us
  86. dq = 0;    //给复位脉冲
  87. delay_uint(80);  //750us
  88. dq = 1;    //把总线拿高 等待
  89. delay_uint(10);  //110us
  90. q = dq;    //读取18b20初始化信号
  91. delay_uint(20);  //200us
  92. dq = 1;    //把总线拿高 释放总线
  93. }
  94. /*************写18b20内的数据***************/
  95. void write_18b20(uchar dat)
  96. {
  97. uchar i;
  98. for(i=0;i<8;i++)
  99. {      //写数据是低位开始
  100.   dq = 0;    //把总线拿低写时间隙开始
  101.   dq = dat & 0x01; //向18b20总线写数据了
  102.   delay_uint(5);  // 60us
  103.   dq = 1;    //释放总线
  104.   dat >>= 1;
  105. }
  106. }
  107. /*************读取18b20内的数据***************/
  108. uchar read_18b20()
  109. {
  110. uchar i,value;
  111. for(i=0;i<8;i++)
  112. {
  113.   dq = 0;    //把总线拿低读时间隙开始
  114.   value >>= 1;  //读数据是低位开始
  115.   dq = 1;    //释放总线
  116.   if(dq == 1)   //开始读写数据
  117.    value |= 0x80;
  118.   delay_uint(5);  //60us 读一个时间隙最少要保持60us的时间
  119. }
  120. return value;   //返回数据
  121. }
  122. /*************读取温度的值 读出来的是小数***************/
  123. uint read_temp()
  124. {
  125. uint value;
  126. uchar low;      //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
  127. init_18b20();     //初始化18b20
  128. EA = 0;
  129. write_18b20(0xcc);    //跳过64位ROM
  130. write_18b20(0x44);    //启动一次温度转换命令
  131. EA = 1;
  132. delay_uint(50);     //500us
  133. init_18b20();     //初始化18b20

  134. EA = 0;
  135. write_18b20(0xcc);    //跳过64位ROM
  136. write_18b20(0xbe);    //发出读取暂存器命令

  137. low = read_18b20();    //读温度低字节
  138. value = read_18b20();  //读温度高字节
  139. EA = 1;
  140. value <<= 8;     //把温度的高位左移8位
  141. value |= low;     //把读出的温度低位放到value的低八位中
  142. value *= 0.625;        //转换到温度值 小数
  143. return value;     //返回读出的温度 带小数
  144. }
  145. /*************定时器0初始化程序***************/
  146. void time_init()   
  147. {
  148. EA   = 1;     //开总中断
  149. TMOD = 0X11;   //定时器0、定时器1工作方式1
  150. ET0  = 1;    //开定时器0中断
  151. TR0  = 1;    //允许定时器0定时
  152. ET1  = 1;    //开定时器0中断
  153. TR1  = 0;    //允许定时器0定时
  154. }
  155. /********************独立按键程序*****************/
  156. uchar key_can;  //按键值
  157. void key()  //独立按键程序
  158. {
  159. static uchar key_new;
  160. key_can = 20;                   //按键值还原
  161. P2 |= 0x07;
  162. if((P2 & 0x07) != 0x07)  //按键按下
  163. {
  164.   if(key_500ms == 1) //连加
  165.   {
  166.    key_500ms = 0;
  167.    key_new = 1;
  168.   }
  169.   delay_1ms(1);       //按键消抖动
  170.   if(((P2 & 0x07) != 0x07) && (key_new == 1))
  171.   {      //确认是按键按下
  172.    key_new = 0;
  173.    switch(P2 & 0x07)
  174.    {
  175.     case 0x06: key_can = 3; break;    //得到k2键值
  176.     case 0x05: key_can = 2; break;    //得到k3键值
  177.     case 0x03: key_can = 1; break;    //得到k4键值
  178.    }
  179.    flag_lj_en = 1;  //连加使能
  180.   }   
  181. }
  182. else
  183. {
  184.   if(key_new == 0)
  185.   {
  186.    key_new = 1;
  187.    write_eeprom();  //保存数据
  188.    flag_lj_en = 0;  //关闭连加使能
  189.    flag_lj_3_en = 0; //关闭3秒后使能
  190.    key_value = 0;  //清零
  191.    key_time = 0;
  192.    key_500ms = 0;
  193.   }
  194. }
  195. }
  196. /****************按键处理数码管显示函数***************/
  197. void key_with()
  198. {
  199. if(key_can == 1)   //设置键
  200. {
  201.   f_pwm_l = 30;
  202.   menu_1 ++;
  203.   if(menu_1 >= 3)
  204.   {
  205.    menu_1 = 0;
  206.    smg_i = 3;    //数码管显示3位
  207.   }
  208. }
  209. if(menu_1 == 1)   //设置高温报警
  210. {
  211.   smg_i = 4;    //数码管显示4位
  212.   if(key_can == 2)
  213.   {
  214.    if(flag_lj_3_en == 0)
  215.     t_high ++ ;  //按键按下未松开自动加三次
  216.    else
  217.     t_high += 10; //按键按下未松开自动加三次之后每次自动加10
  218.    if(t_high > 990)
  219.     t_high = 990;
  220.   }
  221.   if(key_can == 3)
  222.   {
  223.    if(flag_lj_3_en == 0)
  224.     t_high -- ;  //按键按下未松开自动减三次
  225.    else
  226.     t_high -= 10; //按键按下未松开自动减三次之后每次自动减10
  227.    if(t_high <= t_low)
  228.     t_high = t_low + 1;
  229.   }
  230.   dis_smg[0] = smg_du[t_high % 10];            //取小数显示
  231.   dis_smg[1] = smg_du[t_high / 10 % 10] & 0xdf;  //取个位显示
  232.   dis_smg[2] = smg_du[t_high / 100 % 10] ;    //取十位显示
  233.   dis_smg[3] = 0x64;  //H
  234. }
  235. if(menu_1 == 2)   //设置低温报警
  236. {
  237.   smg_i = 4;    //数码管显示4位
  238.   if(key_can == 2)
  239.   {
  240.    if(flag_lj_3_en == 0)
  241.     t_low ++ ;   //按键按下未松开自动加三次
  242.    else
  243.     t_low += 10;  //按键按下未松开自动加三次之后每次自动加10
  244.    if(t_low >= t_high)
  245.     t_low = t_high - 1;
  246.   }
  247.   if(key_can == 3)
  248.   {
  249.    if(flag_lj_3_en == 0)
  250.     t_low -- ;   //按键按下未松开自动减三次
  251.    else
  252.     t_low -= 10;  //按键按下未松开自动加三次之后每次自动加10
  253.    if(t_low <= 10)
  254.     t_low = 10;
  255.   }
  256.   dis_smg[0] = smg_du[t_low % 10];            //取小数显示
  257.   dis_smg[1] = smg_du[t_low / 10 % 10] & 0xdf;   //取个位显示
  258.   dis_smg[2] = smg_du[t_low / 100 % 10] ;        //取十位显示
  259.   dis_smg[3] = 0x3D;   //L
  260. }
  261. }  
  262. /****************风扇控制函数***************/
  263. void fengshan_kz()
  264. {
  265. if(temperature >= t_high)   //风扇全开
  266. {
  267.   TR1 = 1;
  268.   pwm = 0;
  269. }
  270. else if((temperature < t_high) && (temperature >= t_low))     //风扇缓慢
  271. {
  272.   f_pwm_l = 60;  
  273.   TR1 = 1;
  274. }
  275. else if(temperature < t_low)  //关闭风扇
  276. {
  277.   TR1 = 0;
  278.   pwm = 1;
  279. }   
  280. }  
  281. /****************主函数***************/
  282. void main()
  283. {
  284. P0 = P1 = P2 = P3 = 0xff;
  285. time_init();                    //初始化定时器
  286. temperature = read_temp();  //先读出温度的值
  287. init_eeprom();  //开始初始化保存的数据
  288. delay_1ms(650);   
  289. temperature = read_temp();           //先读出温度的值
  290. dis_smg[0] = smg_du[temperature % 10];  //取温度的小数显示
  291. dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取温度的个位显示
  292. dis_smg[2] = smg_du[temperature / 100 % 10] ;    //取温度的十位显示
  293. f_pwm_l = 50;
  294. while(1)
  295. {  
  296.   key();     //按键程序
  297.   if(key_can < 10)
  298.   {
  299.    key_with();   //设置报警温度
  300.   }
  301.   if(flag_300ms == 1)     //300ms 处理一次温度程序
  302.   {   
  303.    flag_300ms = 0;
  304.    temperature = read_temp(); //先读出温度的值
  305.    if(menu_1 == 0)
  306.    {
  307.     smg_i = 3;
  308.     dis_smg[0] = smg_du[temperature % 10];  //取温度的小数显示
  309.     dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取温度的个位显示
  310.     dis_smg[2] = smg_du[temperature / 100 % 10] ;    //取温度的十位显示
  311.    }
  312.   }
  313.   fengshan_kz();        //风扇控制函数
  314. }
  315. }
  316. /*************定时器0中断服务程序***************/
  317. void time0_int() interrupt 1
  318. {
  319. static uchar value;    //定时2ms中断一次
  320. TH0 = 0xf8;
  321. TL0 = 0x30;     //2ms
  322. display();  //数码管显示函数
  323. value++;   
  324. if(value >= 150)
  325. {
  326.   value = 0;   
  327.   flag_300ms = 1;
  328. }
  329. if(flag_lj_en == 1)    //按下按键使能
  330. {
  331.   key_time ++;
  332.   if(key_time >= 250) //500ms
  333.   {
  334.    key_time = 0;
  335.    key_500ms = 1; //500ms
  336.    key_value ++;
  337.    if(key_value > 3)
  338.    {
  339.     key_value = 10;
  340.     flag_lj_3_en = 1; //3次后1.5秒连加大些
  341.    }      
  342.   }
  343. }
  344. }

  345. /*******************定时器1用做单片机模拟PWM 调节***********************/
  346. void Timer1() interrupt 3  //调用定时器1
  347. {
  348. static uchar value_l;
  349. TH1=0x0f;    //    定时中断一次
  350. TL1=0xec;  //
  351. if(pwm==1)
  352. {
  353.   value_l+=3;
  354.   if(value_l > f_pwm_l)   //高电平
  355.   {
  356.    value_l=0;
  357.     pwm=0;  
  358.   }
  359. }
  360. else   
  361. {
  362.   value_l+=3;
  363.   if(value_l  > 100 - f_pwm_l)    //低电平
  364.   {
  365.    value_l=0;
  366.    pwm=1;
  367.   }
  368.     }
  369. }
复制代码
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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