找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的智能风扇Proteus仿真程序设计

[复制链接]
跳转到指定楼层
楼主
电路原理图如下:


仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


元件清单:
Comment    Description    Designator
10uF    电容    C1
20    电容    C2, C3
    发光二极管    D1
SMG04_1    数码管    DS1
红外热释电    人体感应传感器    P1
Header 2    电源接口    P2, P3
9012    三极管    Q1, Q2, Q3, Q4, Q5
1K    电阻    R1, R2, R3, R8, R9, R10, R11, R12
1K    电阻    R4, R5, R6, R7, R15
1K    电阻    R13
10K    电阻    R14, R16
SW-PB    按键    S1, S2, S3, S4
sw-灰色    电源开关    SW1
单片机    单片机    U1
DS18B20    温度传感器    U2
12M    晶振     Y1

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

  4. //数码管段选定义      0     1    2    3    4    5        6         7          8           9        
  5. uchar code smg_du[]={0x28,0xe4,0x42,0x72,0xe5,0xa8,0x41,0x77,0x20,0xa0,
  6.                                            0x60,0x25,0x39,0x26,0x31,0x71,0xff};         //断码
  7. //数码管位选定义
  8. uchar code smg_we[]={0xef,0xdf,0xbf,0x7f};
  9. uchar dis_smg[8] = {0};        
  10. uchar smg_i = 3;    //显示数码管的个位数
  11. sbit dq   = P2^4;        //18b20 IO口的定义
  12. sbit hw = P2^5;
  13. uchar miao = 30;
  14. uchar flag_en;

  15. bit flag_lj_en;                 //按键连加使能
  16. bit flag_lj_3_en;         //按键连3次连加后使能  加的数就越大了
  17. uchar key_time,key_value;      //用做连加的中间变量
  18. bit key_500ms  ;
  19. sbit pwm = P2^3;  
  20. uchar f_pwm_l ;          //越小越慢

  21. uint temperature ;  //
  22. bit flag_200ms ;
  23. uchar menu_1;       //菜单设计的变量
  24. uint t_high = 200,t_low = 100;           //温度上下限报警值

  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<120;j++);
  31. }

  32. /***********************小延时函数*****************************/
  33. void delay_uint(uint q)
  34. {
  35.         while(q--);
  36. }


  37. /***********************数码显示函数*****************************/
  38. void display()
  39. {
  40.         static uchar i;   
  41.         i++;
  42.         if(i >= smg_i)
  43.                 i = 0;        
  44.         P1 = 0xff;                         //消隐
  45.         P3 = smg_we[i];                          //位选
  46.         P1 = dis_smg[i];                 //段选               

  47. }

  48. /***********************18b20初始化函数*****************************/
  49. void init_18b20()
  50. {
  51.         bit q;
  52.         dq = 1;                                //把总线拿高
  53.         delay_uint(1);            //15us
  54.         dq = 0;                                //给复位脉冲
  55.         delay_uint(80);                //750us
  56.         dq = 1;                                //把总线拿高 等待
  57.         delay_uint(10);                //110us
  58.         q = dq;                                //读取18b20初始化信号
  59.         delay_uint(20);                //200us
  60.         dq = 1;                                //把总线拿高 释放总线
  61. }

  62. /*************写18b20内的数据***************/
  63. void write_18b20(uchar dat)
  64. {
  65.         uchar i;
  66.         for(i=0;i<8;i++)
  67.         {                                         //写数据是低位开始
  68.                 dq = 0;                         //把总线拿低写时间隙开始
  69.                 dq = dat & 0x01; //向18b20总线写数据了
  70.                 delay_uint(5);         // 60us
  71.                 dq = 1;                         //释放总线
  72.                 dat >>= 1;
  73.         }        
  74. }

  75. /*************读取18b20内的数据***************/
  76. uchar read_18b20()
  77. {
  78.         uchar i,value;
  79.         for(i=0;i<8;i++)
  80.         {
  81.                 dq = 0;                         //把总线拿低读时间隙开始
  82.                 value >>= 1;         //读数据是低位开始
  83.                 dq = 1;                         //释放总线
  84.                 if(dq == 1)                 //开始读写数据
  85.                         value |= 0x80;
  86.                 delay_uint(5);         //60us        读一个时间隙最少要保持60us的时间
  87.         }
  88.         return value;                 //返回数据
  89. }

  90. /*************读取温度的值 读出来的是小数***************/
  91. uint read_temp()
  92. {
  93.         uint value;
  94.         uchar low;                           //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
  95.         init_18b20();                   //初始化18b20
  96.         write_18b20(0xcc);           //跳过64位ROM
  97.         write_18b20(0x44);           //启动一次温度转换命令
  98.         delay_uint(50);                   //500us

  99.         init_18b20();                   //初始化18b20
  100.         
  101.         write_18b20(0xcc);           //跳过64位ROM
  102.         write_18b20(0xbe);           //发出读取暂存器命令
  103.         
  104.         low = read_18b20();           //读温度低字节
  105.         value = read_18b20();  //读温度高字节
  106.         value <<= 8;                   //把温度的高位左移8位
  107.         value |= low;                   //把读出的温度低位放到value的低八位中
  108.         value *= 0.625;               //转换到温度值 小数
  109.         return value;                   //返回读出的温度 带小数
  110. }

  111. /*************定时器0初始化程序***************/
  112. void time_init()         
  113. {
  114.         EA   = 1;                   //开总中断
  115.         TMOD = 0X21;          //定时器0、定时器1工作方式1
  116.         ET0  = 1;                  //开定时器0中断
  117.         TR0  = 1;                  //允许定时器0定时

  118.         ET1  = 1;                  //开定时器0中断
  119.         TR1  = 1;                  //允许定时器0定时
  120. }

  121. /********************独立按键程序*****************/
  122. uchar key_can;         //按键值

  123. void key()         //独立按键程序
  124. {
  125.         static uchar key_new;
  126.         key_can = 20;                   //按键值还原
  127.         P2 |= 0x07;
  128.         if((P2 & 0x07) != 0x07)                //按键按下
  129.         {
  130.                 if(key_500ms == 1)        //连加
  131.                 {
  132.                         key_500ms = 0;
  133.                         key_new = 1;
  134.                 }
  135.                 delay_1ms(1);                     //按键消抖动
  136.                 if(((P2 & 0x07) != 0x07) && (key_new == 1))
  137.                 {                                                //确认是按键按下
  138.                         key_new = 0;
  139.                         switch(P2 & 0x07)
  140.                         {
  141.                                 case 0x06: key_can = 1; break;           //得到k2键值
  142.                                 case 0x04: key_can = 2; break;           //得到k3键值
  143.                                 case 0x02: key_can = 3; break;           //得到k4键值
  144.                         }
  145.                         flag_lj_en = 1;         //连加使能
  146.                 }                        
  147.         }
  148.         else
  149.         {
  150.                 if(key_new == 0)
  151.                 {
  152.                         key_new = 1;
  153.                         flag_lj_en = 0;                //关闭连加使能
  154.                         flag_lj_3_en = 0;        //关闭3秒后使能
  155.                         key_value = 0;                //清零
  156.                         key_time = 0;
  157.                         key_500ms = 0;
  158.                 }
  159.         }        
  160. }

  161. /****************按键处理数码管显示函数***************/
  162. void key_with()
  163. {
  164.         if(key_can == 1)          //设置键
  165.         {
  166.                 f_pwm_l = 30;
  167.                 menu_1 ++;
  168.                 if(menu_1 >= 3)
  169.                 {
  170.                         menu_1 = 0;
  171.                         smg_i = 3;                  //数码管显示3位
  172.                 }
  173.         }
  174.         if(menu_1 == 1)                        //设置高温报警
  175.         {
  176.                 smg_i = 4;                  //数码管显示4位
  177.                 if(key_can == 2)
  178.                 {
  179.                         if(flag_lj_3_en == 0)
  180.                                 t_high ++ ;                //按键按下未松开自动加三次        
  181.                         else
  182.                                 t_high += 10;        //按键按下未松开自动加三次之后每次自动加10
  183.                         if(t_high > 990)
  184.                                 t_high = 990;
  185.                 }
  186.                 if(key_can == 3)
  187.                 {
  188.                         if(flag_lj_3_en == 0)
  189.                                 t_high -- ;                //按键按下未松开自动减三次        
  190.                         else
  191.                                 t_high -= 10;        //按键按下未松开自动减三次之后每次自动减10
  192.                         if(t_high <= t_low)
  193.                                 t_high = t_low + 1;
  194.                 }
  195.                 dis_smg[0] = smg_du[t_high % 10];                   //取小数显示
  196.                 dis_smg[1] = smg_du[t_high / 10 % 10] & 0xdf;  //取个位显示
  197.                 dis_smg[2] = smg_du[t_high / 100 % 10] ;           //取十位显示
  198.                 dis_smg[3] = 0x64;         //H
  199.         }        
  200.         if(menu_1 == 2)                        //设置低温报警
  201.         {
  202.                 smg_i = 4;                  //数码管显示4位
  203.                 if(key_can == 2)
  204.                 {
  205.                         if(flag_lj_3_en == 0)
  206.                                 t_low ++ ;                        //按键按下未松开自动加三次        
  207.                         else
  208.                                 t_low += 10;                //按键按下未松开自动加三次之后每次自动加10
  209.                         if(t_low >= t_high)
  210.                                 t_low = t_high - 1;
  211.                 }
  212.                 if(key_can == 3)
  213.                 {
  214.                         if(flag_lj_3_en == 0)
  215.                                 t_low -- ;                        //按键按下未松开自动减三次        
  216.                         else
  217.                                 t_low -= 10;                //按键按下未松开自动加三次之后每次自动加10
  218.                         if(t_low <= 10)
  219.                                 t_low = 10;
  220.                 }
  221.                 dis_smg[0] = smg_du[t_low % 10];                   //取小数显示
  222.                 dis_smg[1] = smg_du[t_low / 10 % 10] & 0xdf;   //取个位显示
  223.                 dis_smg[2] = smg_du[t_low / 100 % 10] ;               //取十位显示
  224.                 dis_smg[3] = 0x3D;          //L
  225.         }        
  226. }  

  227. /****************风扇控制函数***************/
  228. void fengshan_kz()
  229. {
  230.         if(flag_en == 1)
  231.         {
  232.                 if(temperature >= t_high)          //风扇全开
  233.                 {        
  234.                         TR1 = 1;
  235.                         pwm = 0;
  236.                 }
  237.                 else if((temperature < t_high)        && (temperature >= t_low))                   //风扇缓慢
  238.                 {
  239.                         f_pwm_l = 60;         
  240.                         TR1 = 1;
  241.                 }
  242.                 else if(temperature < t_low)         //关闭风扇
  243.                 {
  244.                         TR1 = 0;
  245.                         pwm = 1;
  246.                 }        
  247.         }               
  248. }
  249.                

  250. /****************主函数***************/
  251. void main()
  252. {
  253.         static uchar value;
  254.         time_init();                    //初始化定时器
  255.         temperature = read_temp();                //先读出温度的值        
  256.         delay_1ms(650);                                
  257.         temperature = read_temp();                         //先读出温度的值
  258.         dis_smg[0] = smg_du[temperature % 10];         //取温度的小数显示
  259.         dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取温度的个位显示
  260.         dis_smg[2] = smg_du[temperature / 100 % 10] ;           //取温度的十位显示
  261.         while(1)
  262.         {               
  263.                 key();                                        //按键程序
  264.                 if(key_can < 10)
  265.                 {
  266.                         key_with();                        //设置报警温度        
  267.                 }
  268.                 if(flag_200ms == 1)            //200ms 处理一次温度程序
  269.                 {           
  270.                         flag_200ms = 0;        
  271.                         temperature = read_temp();        //先读出温度的值
  272.                         if(menu_1 == 0)
  273.                         {        
  274.                                 smg_i = 3;
  275.                                 dis_smg[0] = smg_du[temperature % 10];         //取温度的小数显示
  276.                                 dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取温度的个位显示
  277.                                 dis_smg[2] = smg_du[temperature / 100 % 10] ;           //取温度的十位显示
  278.                         }
  279.                         fengshan_kz();        //风扇控制函数
  280.                         value ++;
  281.                         if(value >= 4)
  282.                         {
  283.                                 value = 0;
  284.                                 if(miao != 0)
  285.                                 {
  286.                                         miao --;    //时间减1
  287.                                 }
  288.                                 if(miao == 0)
  289.                                         flag_en = 0;
  290.                         }
  291.                         if(hw == 1)  //感应到人
  292.                         {
  293.                                 miao = 30;
  294.                                 flag_en = 1;
  295.                         }
  296.                 }

  297.                 display();                //数码管显示函数
  298.         }
  299. }

  300. /*************定时器0中断服务程序***************/
  301. void time0_int() interrupt 1
  302. {        
  303.         static uchar value;                         //定时2ms中断一次
  304.         TH0 = 0xf8;
  305.         TL0 = 0x30;     //2ms
  306.         value++;         
  307.         if(value >= 150)
  308.         {
  309.                 value = 0;         
  310.                 flag_200ms = 1;
  311.         }
  312.         if(flag_lj_en == 1)           //按下按键使能
  313.         {
  314.                 key_time ++;
  315. ……………………

  316. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
智能温控风扇设计.7z (2.31 MB, 下载次数: 63)
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1064592 发表于 2024-4-18 18:58 | 只看该作者
哥,仿真里面没有红外热释电部分的吧
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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