找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6448|回复: 7
收起左侧

单片机智能温控风扇原理图PCB文件与源程序

  [复制链接]
ID:431677 发表于 2020-2-16 15:36 | 显示全部楼层 |阅读模式
主芯片为89c51,外设有电机,温度传感器,红外热释电,lcd1602,主要功能是可根据室温自动调整电机转速,并且识别人体,有人打开,无人断电,室内温度,以及上下限可按键调整,并在1602上显示。
压缩包里有原理图,pcb板,以及库。还有代码和文档。

Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
51hei.png 51hei.png 51hei.png

单片机源程序如下:
  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   = P2^4;        //18b20 IO口的定义
  6. sbit BGVCC   = P2^7;
  7. uint temperature ;  //
  8. bit flag_200ms ;

  9. bit flag_lj_en;                 //按键连加使能
  10. bit flag_lj_3_en;         //按键连3次连加后使能  加的数就越大了
  11. uchar key_time,key_value;      //用做连加的中间变量
  12. bit key_500ms  ;
  13. sbit hw = P2^5;
  14. uchar miao = 30;
  15. uchar flag_en;
  16. sbit buzz=P1^3;
  17. uchar code table_num[]="0123456789abcdefg";

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

  21. sbit pwm = P2^3;  
  22. uchar f_pwm_l ;          //

  23. uchar menu_1;        //菜单设计的变量
  24. uint t_high = 300,t_low = 200;


  25. /***********************1ms延时函数*****************************/
  26. void delay_1ms(uint q)
  27. {
  28.         uint i,j;
  29.         for(i=0;i<q;i++)
  30.                 for(j=0;j<110;j++);
  31. }

  32. /********************************************************************
  33. * 名称 : delay_uint()
  34. * 功能 : 小延时。
  35. * 输入 : 无
  36. * 输出 : 无
  37. ***********************************************************************/
  38. void delay_uint(uint q)
  39. {
  40.         while(q--);
  41. }

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

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

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

  96. /***********************lcd1602上显示特定的字符************************/
  97. void write_zifu(uchar hang,uchar add,uchar date)
  98. {
  99.         if(hang==1)   
  100.                 write_com(0x80+add);
  101.         else
  102.                 write_com(0x80+0x40+add);
  103.         write_data(date);       
  104. }

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

  118. /***********************lcd1602初始化设置************************/
  119. void init_1602()
  120. {
  121.         write_com(0x38);        //
  122.         write_com(0x0c);
  123.         write_com(0x06);
  124.         delay_uint(1000);
  125.         write_string(1,0,"temp:           ");       
  126.         write_string(2,0,"H:      L:       ");
  127.         write_sfm3_18B20(2,2,t_high);       
  128.         write_sfm3_18B20(2,10,t_low);                               
  129.         write_zifu(1,9,0xdf);  //显示度       
  130. }

  131. /***********************18b20初始化函数*****************************/
  132. void init_18b20()
  133. {          
  134.         bit q;
  135.                 EA=0;
  136.         dq = 1;                                //把总线拿高
  137.         delay_uint(1);            //15us
  138.         dq = 0;                                //给复位脉冲
  139.         delay_uint(80);                //750us
  140.         dq = 1;                                //把总线拿高 等待
  141.         delay_uint(10);                //110us
  142.         q = dq;                                //读取18b20初始化信号
  143.         delay_uint(20);                //200us
  144.         dq = 1;                                //把总线拿高 释放总线
  145.         EA=1 ;
  146. }

  147. /*************写18b20内的数据***************/
  148. void write_18b20(uchar dat)
  149. {         
  150.         uchar i;
  151.                  EA=0;
  152.         for(i=0;i<8;i++)
  153.         {                                         //写数据是低位开始
  154.                 dq = 0;                         //把总线拿低写时间隙开始
  155.                 dq = dat & 0x01; //向18b20总线写数据了
  156.                 delay_uint(5);         // 60us
  157.                 dq = 1;                         //释放总线
  158.                 dat >>= 1;
  159.         }
  160.         EA=1;       
  161. }

  162. /*************读取18b20内的数据***************/
  163. uchar read_18b20()
  164. {         
  165.         uchar i,value;
  166.                          EA=0 ;
  167.         for(i=0;i<8;i++)
  168.         {
  169.                 dq = 0;                         //把总线拿低读时间隙开始
  170.                 value >>= 1;         //读数据是低位开始
  171.                 dq = 1;                         //释放总线
  172.                 if(dq == 1)                 //开始读写数据
  173.                         value |= 0x80;
  174.                 delay_uint(7);         //60us        读一个时间隙最少要保持60us的时间
  175.         }
  176.         EA=1  ;
  177.         return value;                 //返回数据
  178. }


  179. /*************读取温度的值 读出来的是小数***************/
  180. uint read_temp()
  181. {          
  182.         uint value;
  183.         uchar low;                           //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
  184.            EA=0;
  185.         init_18b20();                   //初始化18b20

  186.         write_18b20(0xcc);           //跳过64位ROM
  187.         write_18b20(0x44);           //启动一次温度转换命令
  188.          delay_uint(50);                   //500us

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

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

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

  194.         value <<= 8;                   //把温度的高位左移8位
  195.         value |= low;                   //把读出的温度低位放到value的低八位中
  196.         value *=0.625 ;               //转换到温度值 小数
  197.         EA=1;
  198.         return value;                   //返回读出的温度 带小数
  199. }

  200. /*************定时器0初始化程序***************/
  201. void time_init()          
  202. {
  203.         EA   = 1;                   //开总中断
  204.         TMOD = 0X21;          //定时器0、定时器1工作方式1
  205.         ET0  = 1;                  //开定时器0中断
  206.         TR0  = 1;                  //允许定时器0定时
  207.         ET1  = 1;                  //开定时器0中断
  208.         TR1  = 1;                  //允许定时器0定时
  209. }

  210. /********************独立按键程序*****************/
  211. uchar key_can;         //按键值

  212. void key()             //独立按键程序
  213. {          
  214.         static uchar key_new;
  215.          
  216.         key_can = 20;               //按键值还原
  217.          P1 |= 0xf0;
  218.         if(key_500ms == 1)        //连加
  219.         {
  220.                 key_500ms = 0;
  221.                 key_new = 1;
  222.         }
  223.         if((P1 & 0xf0) != 0xf0)                //按键按下
  224.         {
  225.                 delay_1ms(1);                     //按键消抖动
  226.                 if(((P1 & 0xf0) != 0xf0) && (key_new == 1))
  227.                 {                                                //确认是按键按下
  228.                         key_new = 0;
  229.                         switch(P1 & 0xf0)
  230.                         {
  231.                                 case 0xe0: key_can = 1; break;           //得到k1键值
  232.                                 case 0xd0: key_can = 2; break;           //得到K2键值
  233.                                 case 0xb0: key_can = 3; break;           //得到k3键值
  234.                         }
  235.                         flag_lj_en = 1;         //连加使能
  236.                 }                       
  237.         }
  238.         else
  239.         {
  240.                         if(key_new == 0)
  241.                 {
  242.                         key_new = 1;
  243.                         flag_lj_en = 0;                //关闭连加使能
  244.                         flag_lj_3_en = 0;        //关闭3秒后使能
  245.                         key_value = 0;                //清零
  246.                         key_time = 0;
  247.                         key_500ms = 0;
  248.                 }
  249.         }

  250. }


  251. /****************按键显示函数***************/
  252. void key_with()
  253. {          
  254.        
  255.         if(key_can == 1)           //设置键
  256.         {         
  257.                 menu_1 ++;
  258.                 if(menu_1 >= 3)
  259.                 {
  260.                         menu_1 = 0;
  261.                 }
  262.                 if(menu_1 == 0)
  263.                 {
  264.                         write_com(0x0c);                //关闭光标
  265.                 }
  266.         }
  267.         if(menu_1 == 1)                        //设置高温报警
  268.         {
  269.                 if(key_can == 2)
  270.                 {
  271.                         if(flag_lj_3_en == 0)
  272.                                 t_high ++ ;                //按键按下未松开自动加三次       
  273.                         else
  274.                                 t_high += 10;        //按键按下未松开自动加三次之后每次自动加10
  275.                         if(t_high > 990)
  276.                                 t_high = 990;
  277.                 }
  278.                 if(key_can == 3)
  279.                 {
  280.                         if(flag_lj_3_en == 0)
  281.                                 t_high -- ;                //按键按下未松开自动减三次       
  282.                         else
  283.                                 t_high -= 10;        //按键按下未松开自动减三次之后每次自动减10
  284.                         if(t_high <= t_low)
  285.                                 t_high = t_low + 1;
  286.                 }               
  287.                 write_sfm3_18B20(2,2,t_high);
  288.                 write_com(0x80+0x40+2);             //将光标移动到秒个位
  289.                 write_com(0x0f);                    //显示光标并且闪烁       
  290.         }       
  291.         if(menu_1 == 2)                        //设置低温报警
  292.         {
  293.                 if(key_can == 2)
  294.                 {
  295.                         if(flag_lj_3_en == 0)
  296.                                 t_low ++ ;                        //按键按下未松开自动加三次       
  297.                         else
  298.                                 t_low += 10;                //按键按下未松开自动加三次之后每次自动加10
  299.                         if(t_low >= t_high)
  300.                                 t_low = t_high - 1;
  301.                 }
  302.                 if(key_can == 3)
  303.                 {
  304.                         if(flag_lj_3_en == 0)
  305.                                 t_low -- ;                        //按键按下未松开自动减三次       
  306.                         else
  307.                                 t_low -= 10;                //按键按下未松开自动加三次之后每次自动加10
  308.                         if(t_low <= 10)
  309.                                 t_low = 10;
  310.                 }
  311.                 write_sfm3_18B20(2,10,t_low);
  312.                 write_com(0x80+0x40+10);            //将光标移动到秒个位
  313.                 write_com(0x0f);                    //显示光标并且闪烁       
  314.         }
  315.        
  316. }

  317. /****************风扇控制函数***************/
  318. void fengshan_kz()
  319. {        if(flag_en == 1)
  320.         { BGVCC=0;

  321.         if(temperature >= t_high)          //风扇全开
  322.         {         
  323.                  
  324.                 f_pwm_l = 60;
  325.                    pwm = 1;
  326.                         TR1 = 1;
  327.                   write_string(1,10," high ");
  328.         }
  329.         else if((temperature < t_high)        && (temperature >= t_low))                   //风扇缓慢
  330.         {         
  331.                   
  332.                 f_pwm_l =61;
  333.                    pwm = 0;
  334.                 TR1 = 1;
  335.                 write_string(1,10," slow ");       
  336.                
  337.         }
  338.         else if(temperature < t_low)         //关闭风扇
  339.         {
  340.                 TR1 = 0;
  341.                 pwm = 1;
  342.                  write_string(1,10,"close");
  343.         }
  344.         }
  345.         else
  346.         {TR1 = 0;
  347.                 pwm = 1;
  348.                 BGVCC=1;
  349.                 write_string(1,10,"noman");
  350.         }                       
  351. }               

  352. /****************主函数***************/
  353. void main()
  354. {         static uchar value;
  355.           BGVCC=0;
  356.         time_init();                    //初始化定时器
  357.         init_1602();                    //1602初始化
  358.           temperature = read_temp();        //先读出温度的值
  359.                         write_sfm3_18B20(1,5,temperature);       
  360.                                        
  361.         while(1)
  362.         {
  363.                         if(flag_200ms == 1)            //200ms 处理一次温度程序
  364.                 {        TR1=0;
  365.                 key();                                        //按键程序
  366.                           
  367.                 if(key_can < 10)
  368.                 {
  369.                         key_with();                            //设置报警温度       
  370.                 }                  
  371.                 temperature = read_temp();        //先读出温度的值
  372.                        
  373.                 write_sfm3_18B20(1,5,temperature);
  374.                
  375.                                
  376.                 fengshan_kz();        //风扇控制函数
  377.                  value ++;
  378.                         if(value >= 4)
  379.                         {
  380.                                 value = 0;
  381.                                 if(miao != 0)
  382.                                 {
  383.                                         miao --;    //时间减1
  384.                                 }
  385.                                 if(miao == 0)
  386.                                           
  387.                                                          
  388.                                         flag_en = 0;
  389.                         }
  390.                         if(hw == 1)  //感应到人
  391.                         {         if(miao==0)
  392.                             {buzz=0;
  393.                             delay_1ms(500);
  394.                             buzz=1;
  395.                                 }
  396.                                 miao = 30;
  397.                                 flag_en = 1;
  398.                         }
  399.                   }
  400.         }
  401. }

  402. /*************定时器0中断服务程序***************/
  403. void time0_int() interrupt 1
  404. {       
  405.         static uchar value;

  406.         TH0 = 0x0c;
  407.         TL0 = 0xb0;     // 50ms
  408.         value ++;         
  409.         if(value % 4 == 0)
  410.         {
  411.                 flag_200ms = 1;           //300ms
  412.                 value = 0;
  413.         }

  414.         if(flag_lj_en == 1)           //按下按键使能
  415.         {
  416.                 key_time ++;
  417.                 if(key_time >= 10) //500ms
  418.                 {
  419.                         key_time = 0;
  420.                         key_500ms = 1; //500ms
  421.                         key_value ++;
  422.                         if(key_value > 3)
  423.                         {
  424.                                 key_value = 10;
  425.                                 flag_lj_3_en = 1; //3次后1.5秒连加大些
  426.                         }                                               
  427.                 }
  428.         }

  429. }

  430. /*******************定时器1用做单片机模拟PWM 调节***********************/
  431. void Timer1() interrupt 3  //调用定时器1
  432. {
  433.         static uchar value_l;
  434.         TH1=0x3c;    //  
  435.         TL1=0xb0;         //
  436.         if(pwm==1)
  437.         {
  438.                 value_l+=1;
  439.                 if(value_l > f_pwm_l)   //高电平
  440.                 {
  441.                                  value_l=0;
  442.                                 pwm=0;         
  443.                 }
  444.         }
  445.         else                               
  446.         {
  447.                 value_l+=1;
  448.                 if(value_l  > 100-f_pwm_l)                  //低电平
  449.                 {         value_l=0;
  450.                         pwm=1;
  451.                 }
  452.     }
  453. }
复制代码

所有资料51hei提供下载:
zhinengfengshan111.zip (2.55 MB, 下载次数: 207)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:89286 发表于 2020-2-17 10:43 | 显示全部楼层
thanks for sahring
回复

使用道具 举报

ID:858078 发表于 2020-12-10 14:00 | 显示全部楼层
thanks for sharing
回复

使用道具 举报

ID:120677 发表于 2020-12-10 20:42 | 显示全部楼层
程序写得很规范 有参考意义
回复

使用道具 举报

ID:255559 发表于 2020-12-11 07:56 | 显示全部楼层
谢谢你的分享,学习一下你的程序
回复

使用道具 举报

ID:835755 发表于 2021-6-18 20:08 | 显示全部楼层
我这个pcb图打不开是啥情况
回复

使用道具 举报

ID:945802 发表于 2021-6-28 09:06 | 显示全部楼层
thank for share
回复

使用道具 举报

ID:900636 发表于 2022-5-13 00:42 来自手机 | 显示全部楼层
BGVCC是什么
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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