找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 3537|回復(fù): 1
收起左側(cè)

基于51單片機(jī)的智能風(fēng)扇Proteus仿真程序設(shè)計(jì)

[復(fù)制鏈接]
ID:525068 發(fā)表于 2020-12-15 20:44 | 顯示全部樓層 |閱讀模式
電路原理圖如下:
51hei.png

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png

元件清單:
Comment    Description    Designator
10uF    電容    C1
20    電容    C2, C3
    發(fā)光二極管    D1
SMG04_1    數(shù)碼管    DS1
紅外熱釋電    人體感應(yīng)傳感器    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-灰色    電源開關(guān)    SW1
單片機(jī)    單片機(jī)    U1
DS18B20    溫度傳感器    U2
12M    晶振     Y1

單片機(jī)源程序如下:
  1. #include <reg52.h>                 //調(diào)用單片機(jī)頭文件
  2. #define uchar unsigned char  //無(wú)符號(hào)字符型 宏定義        變量范圍0~255
  3. #define uint  unsigned int         //無(wú)符號(hào)整型 宏定義        變量范圍0~65535

  4. //數(shù)碼管段選定義      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. //數(shù)碼管位選定義
  8. uchar code smg_we[]={0xef,0xdf,0xbf,0x7f};
  9. uchar dis_smg[8] = {0};        
  10. uchar smg_i = 3;    //顯示數(shù)碼管的個(gè)位數(shù)
  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次連加后使能  加的數(shù)就越大了
  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;       //菜單設(shè)計(jì)的變量
  24. uint t_high = 200,t_low = 100;           //溫度上下限報(bào)警值

  25. /***********************1ms延時(shí)函數(shù)*****************************/
  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. /***********************小延時(shí)函數(shù)*****************************/
  33. void delay_uint(uint q)
  34. {
  35.         while(q--);
  36. }


  37. /***********************數(shù)碼顯示函數(shù)*****************************/
  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初始化函數(shù)*****************************/
  49. void init_18b20()
  50. {
  51.         bit q;
  52.         dq = 1;                                //把總線拿高
  53.         delay_uint(1);            //15us
  54.         dq = 0;                                //給復(fù)位脈沖
  55.         delay_uint(80);                //750us
  56.         dq = 1;                                //把總線拿高 等待
  57.         delay_uint(10);                //110us
  58.         q = dq;                                //讀取18b20初始化信號(hào)
  59.         delay_uint(20);                //200us
  60.         dq = 1;                                //把總線拿高 釋放總線
  61. }

  62. /*************寫18b20內(nèi)的數(shù)據(jù)***************/
  63. void write_18b20(uchar dat)
  64. {
  65.         uchar i;
  66.         for(i=0;i<8;i++)
  67.         {                                         //寫數(shù)據(jù)是低位開始
  68.                 dq = 0;                         //把總線拿低寫時(shí)間隙開始
  69.                 dq = dat & 0x01; //向18b20總線寫數(shù)據(jù)了
  70.                 delay_uint(5);         // 60us
  71.                 dq = 1;                         //釋放總線
  72.                 dat >>= 1;
  73.         }        
  74. }

  75. /*************讀取18b20內(nèi)的數(shù)據(jù)***************/
  76. uchar read_18b20()
  77. {
  78.         uchar i,value;
  79.         for(i=0;i<8;i++)
  80.         {
  81.                 dq = 0;                         //把總線拿低讀時(shí)間隙開始
  82.                 value >>= 1;         //讀數(shù)據(jù)是低位開始
  83.                 dq = 1;                         //釋放總線
  84.                 if(dq == 1)                 //開始讀寫數(shù)據(jù)
  85.                         value |= 0x80;
  86.                 delay_uint(5);         //60us        讀一個(gè)時(shí)間隙最少要保持60us的時(shí)間
  87.         }
  88.         return value;                 //返回?cái)?shù)據(jù)
  89. }

  90. /*************讀取溫度的值 讀出來(lái)的是小數(shù)***************/
  91. uint read_temp()
  92. {
  93.         uint value;
  94.         uchar low;                           //在讀取溫度的時(shí)候如果中斷的太頻繁了,就應(yīng)該把中斷給關(guān)了,否則會(huì)影響到18b20的時(shí)序
  95.         init_18b20();                   //初始化18b20
  96.         write_18b20(0xcc);           //跳過(guò)64位ROM
  97.         write_18b20(0x44);           //啟動(dòng)一次溫度轉(zhuǎn)換命令
  98.         delay_uint(50);                   //500us

  99.         init_18b20();                   //初始化18b20
  100.         
  101.         write_18b20(0xcc);           //跳過(guò)64位ROM
  102.         write_18b20(0xbe);           //發(fā)出讀取暫存器命令
  103.         
  104.         low = read_18b20();           //讀溫度低字節(jié)
  105.         value = read_18b20();  //讀溫度高字節(jié)
  106.         value <<= 8;                   //把溫度的高位左移8位
  107.         value |= low;                   //把讀出的溫度低位放到value的低八位中
  108.         value *= 0.625;               //轉(zhuǎn)換到溫度值 小數(shù)
  109.         return value;                   //返回讀出的溫度 帶小數(shù)
  110. }

  111. /*************定時(shí)器0初始化程序***************/
  112. void time_init()         
  113. {
  114.         EA   = 1;                   //開總中斷
  115.         TMOD = 0X21;          //定時(shí)器0、定時(shí)器1工作方式1
  116.         ET0  = 1;                  //開定時(shí)器0中斷
  117.         TR0  = 1;                  //允許定時(shí)器0定時(shí)

  118.         ET1  = 1;                  //開定時(shí)器0中斷
  119.         TR1  = 1;                  //允許定時(shí)器0定時(shí)
  120. }

  121. /********************獨(dú)立按鍵程序*****************/
  122. uchar key_can;         //按鍵值

  123. void key()         //獨(dú)立按鍵程序
  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);                     //按鍵消抖動(dòng)
  136.                 if(((P2 & 0x07) != 0x07) && (key_new == 1))
  137.                 {                                                //確認(rèn)是按鍵按下
  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;                //關(guān)閉連加使能
  154.                         flag_lj_3_en = 0;        //關(guān)閉3秒后使能
  155.                         key_value = 0;                //清零
  156.                         key_time = 0;
  157.                         key_500ms = 0;
  158.                 }
  159.         }        
  160. }

  161. /****************按鍵處理數(shù)碼管顯示函數(shù)***************/
  162. void key_with()
  163. {
  164.         if(key_can == 1)          //設(shè)置鍵
  165.         {
  166.                 f_pwm_l = 30;
  167.                 menu_1 ++;
  168.                 if(menu_1 >= 3)
  169.                 {
  170.                         menu_1 = 0;
  171.                         smg_i = 3;                  //數(shù)碼管顯示3位
  172.                 }
  173.         }
  174.         if(menu_1 == 1)                        //設(shè)置高溫報(bào)警
  175.         {
  176.                 smg_i = 4;                  //數(shù)碼管顯示4位
  177.                 if(key_can == 2)
  178.                 {
  179.                         if(flag_lj_3_en == 0)
  180.                                 t_high ++ ;                //按鍵按下未松開自動(dòng)加三次        
  181.                         else
  182.                                 t_high += 10;        //按鍵按下未松開自動(dòng)加三次之后每次自動(dòng)加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 -- ;                //按鍵按下未松開自動(dòng)減三次        
  190.                         else
  191.                                 t_high -= 10;        //按鍵按下未松開自動(dòng)減三次之后每次自動(dòng)減10
  192.                         if(t_high <= t_low)
  193.                                 t_high = t_low + 1;
  194.                 }
  195.                 dis_smg[0] = smg_du[t_high % 10];                   //取小數(shù)顯示
  196.                 dis_smg[1] = smg_du[t_high / 10 % 10] & 0xdf;  //取個(gè)位顯示
  197.                 dis_smg[2] = smg_du[t_high / 100 % 10] ;           //取十位顯示
  198.                 dis_smg[3] = 0x64;         //H
  199.         }        
  200.         if(menu_1 == 2)                        //設(shè)置低溫報(bào)警
  201.         {
  202.                 smg_i = 4;                  //數(shù)碼管顯示4位
  203.                 if(key_can == 2)
  204.                 {
  205.                         if(flag_lj_3_en == 0)
  206.                                 t_low ++ ;                        //按鍵按下未松開自動(dòng)加三次        
  207.                         else
  208.                                 t_low += 10;                //按鍵按下未松開自動(dòng)加三次之后每次自動(dòng)加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 -- ;                        //按鍵按下未松開自動(dòng)減三次        
  216.                         else
  217.                                 t_low -= 10;                //按鍵按下未松開自動(dòng)加三次之后每次自動(dòng)加10
  218.                         if(t_low <= 10)
  219.                                 t_low = 10;
  220.                 }
  221.                 dis_smg[0] = smg_du[t_low % 10];                   //取小數(shù)顯示
  222.                 dis_smg[1] = smg_du[t_low / 10 % 10] & 0xdf;   //取個(gè)位顯示
  223.                 dis_smg[2] = smg_du[t_low / 100 % 10] ;               //取十位顯示
  224.                 dis_smg[3] = 0x3D;          //L
  225.         }        
  226. }  

  227. /****************風(fēng)扇控制函數(shù)***************/
  228. void fengshan_kz()
  229. {
  230.         if(flag_en == 1)
  231.         {
  232.                 if(temperature >= t_high)          //風(fēng)扇全開
  233.                 {        
  234.                         TR1 = 1;
  235.                         pwm = 0;
  236.                 }
  237.                 else if((temperature < t_high)        && (temperature >= t_low))                   //風(fēng)扇緩慢
  238.                 {
  239.                         f_pwm_l = 60;         
  240.                         TR1 = 1;
  241.                 }
  242.                 else if(temperature < t_low)         //關(guān)閉風(fēng)扇
  243.                 {
  244.                         TR1 = 0;
  245.                         pwm = 1;
  246.                 }        
  247.         }               
  248. }
  249.                

  250. /****************主函數(shù)***************/
  251. void main()
  252. {
  253.         static uchar value;
  254.         time_init();                    //初始化定時(shí)器
  255.         temperature = read_temp();                //先讀出溫度的值        
  256.         delay_1ms(650);                                
  257.         temperature = read_temp();                         //先讀出溫度的值
  258.         dis_smg[0] = smg_du[temperature % 10];         //取溫度的小數(shù)顯示
  259.         dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取溫度的個(gè)位顯示
  260.         dis_smg[2] = smg_du[temperature / 100 % 10] ;           //取溫度的十位顯示
  261.         while(1)
  262.         {               
  263.                 key();                                        //按鍵程序
  264.                 if(key_can < 10)
  265.                 {
  266.                         key_with();                        //設(shè)置報(bào)警溫度        
  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];         //取溫度的小數(shù)顯示
  276.                                 dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取溫度的個(gè)位顯示
  277.                                 dis_smg[2] = smg_du[temperature / 100 % 10] ;           //取溫度的十位顯示
  278.                         }
  279.                         fengshan_kz();        //風(fēng)扇控制函數(shù)
  280.                         value ++;
  281.                         if(value >= 4)
  282.                         {
  283.                                 value = 0;
  284.                                 if(miao != 0)
  285.                                 {
  286.                                         miao --;    //時(shí)間減1
  287.                                 }
  288.                                 if(miao == 0)
  289.                                         flag_en = 0;
  290.                         }
  291.                         if(hw == 1)  //感應(yīng)到人
  292.                         {
  293.                                 miao = 30;
  294.                                 flag_en = 1;
  295.                         }
  296.                 }

  297.                 display();                //數(shù)碼管顯示函數(shù)
  298.         }
  299. }

  300. /*************定時(shí)器0中斷服務(wù)程序***************/
  301. void time0_int() interrupt 1
  302. {        
  303.         static uchar value;                         //定時(shí)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. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
智能溫控風(fēng)扇設(shè)計(jì).7z (2.31 MB, 下載次數(shù): 81)
回復(fù)

使用道具 舉報(bào)

ID:1064592 發(fā)表于 2024-4-18 18:58 | 顯示全部樓層
哥,仿真里面沒有紅外熱釋電部分的吧
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表