電路原理圖如下:
仿真原理圖如下(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
單片機源程序如下:
- #include <reg52.h> //調用單片機頭文件
- #define uchar unsigned char //無符號字符型 宏定義 變量范圍0~255
- #define uint unsigned int //無符號整型 宏定義 變量范圍0~65535
- //數碼管段選定義 0 1 2 3 4 5 6 7 8 9
- uchar code smg_du[]={0x28,0xe4,0x42,0x72,0xe5,0xa8,0x41,0x77,0x20,0xa0,
- 0x60,0x25,0x39,0x26,0x31,0x71,0xff}; //斷碼
- //數碼管位選定義
- uchar code smg_we[]={0xef,0xdf,0xbf,0x7f};
- uchar dis_smg[8] = {0};
- uchar smg_i = 3; //顯示數碼管的個位數
- sbit dq = P2^4; //18b20 IO口的定義
- sbit hw = P2^5;
- uchar miao = 30;
- uchar flag_en;
- bit flag_lj_en; //按鍵連加使能
- bit flag_lj_3_en; //按鍵連3次連加后使能 加的數就越大了
- uchar key_time,key_value; //用做連加的中間變量
- bit key_500ms ;
- sbit pwm = P2^3;
- uchar f_pwm_l ; //越小越慢
- uint temperature ; //
- bit flag_200ms ;
- uchar menu_1; //菜單設計的變量
- uint t_high = 200,t_low = 100; //溫度上下限報警值
- /***********************1ms延時函數*****************************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<120;j++);
- }
- /***********************小延時函數*****************************/
- void delay_uint(uint q)
- {
- while(q--);
- }
- /***********************數碼顯示函數*****************************/
- void display()
- {
- static uchar i;
- i++;
- if(i >= smg_i)
- i = 0;
- P1 = 0xff; //消隱
- P3 = smg_we[i]; //位選
- P1 = dis_smg[i]; //段選
- }
- /***********************18b20初始化函數*****************************/
- void init_18b20()
- {
- bit q;
- dq = 1; //把總線拿高
- delay_uint(1); //15us
- dq = 0; //給復位脈沖
- delay_uint(80); //750us
- dq = 1; //把總線拿高 等待
- delay_uint(10); //110us
- q = dq; //讀取18b20初始化信號
- delay_uint(20); //200us
- dq = 1; //把總線拿高 釋放總線
- }
- /*************寫18b20內的數據***************/
- void write_18b20(uchar dat)
- {
- uchar i;
- for(i=0;i<8;i++)
- { //寫數據是低位開始
- dq = 0; //把總線拿低寫時間隙開始
- dq = dat & 0x01; //向18b20總線寫數據了
- delay_uint(5); // 60us
- dq = 1; //釋放總線
- dat >>= 1;
- }
- }
- /*************讀取18b20內的數據***************/
- uchar read_18b20()
- {
- uchar i,value;
- for(i=0;i<8;i++)
- {
- dq = 0; //把總線拿低讀時間隙開始
- value >>= 1; //讀數據是低位開始
- dq = 1; //釋放總線
- if(dq == 1) //開始讀寫數據
- value |= 0x80;
- delay_uint(5); //60us 讀一個時間隙最少要保持60us的時間
- }
- return value; //返回數據
- }
- /*************讀取溫度的值 讀出來的是小數***************/
- uint read_temp()
- {
- uint value;
- uchar low; //在讀取溫度的時候如果中斷的太頻繁了,就應該把中斷給關了,否則會影響到18b20的時序
- init_18b20(); //初始化18b20
- write_18b20(0xcc); //跳過64位ROM
- write_18b20(0x44); //啟動一次溫度轉換命令
- delay_uint(50); //500us
- init_18b20(); //初始化18b20
-
- write_18b20(0xcc); //跳過64位ROM
- write_18b20(0xbe); //發出讀取暫存器命令
-
- low = read_18b20(); //讀溫度低字節
- value = read_18b20(); //讀溫度高字節
- value <<= 8; //把溫度的高位左移8位
- value |= low; //把讀出的溫度低位放到value的低八位中
- value *= 0.625; //轉換到溫度值 小數
- return value; //返回讀出的溫度 帶小數
- }
- /*************定時器0初始化程序***************/
- void time_init()
- {
- EA = 1; //開總中斷
- TMOD = 0X21; //定時器0、定時器1工作方式1
- ET0 = 1; //開定時器0中斷
- TR0 = 1; //允許定時器0定時
- ET1 = 1; //開定時器0中斷
- TR1 = 1; //允許定時器0定時
- }
- /********************獨立按鍵程序*****************/
- uchar key_can; //按鍵值
- void key() //獨立按鍵程序
- {
- static uchar key_new;
- key_can = 20; //按鍵值還原
- P2 |= 0x07;
- if((P2 & 0x07) != 0x07) //按鍵按下
- {
- if(key_500ms == 1) //連加
- {
- key_500ms = 0;
- key_new = 1;
- }
- delay_1ms(1); //按鍵消抖動
- if(((P2 & 0x07) != 0x07) && (key_new == 1))
- { //確認是按鍵按下
- key_new = 0;
- switch(P2 & 0x07)
- {
- case 0x06: key_can = 1; break; //得到k2鍵值
- case 0x04: key_can = 2; break; //得到k3鍵值
- case 0x02: key_can = 3; break; //得到k4鍵值
- }
- flag_lj_en = 1; //連加使能
- }
- }
- else
- {
- if(key_new == 0)
- {
- key_new = 1;
- flag_lj_en = 0; //關閉連加使能
- flag_lj_3_en = 0; //關閉3秒后使能
- key_value = 0; //清零
- key_time = 0;
- key_500ms = 0;
- }
- }
- }
- /****************按鍵處理數碼管顯示函數***************/
- void key_with()
- {
- if(key_can == 1) //設置鍵
- {
- f_pwm_l = 30;
- menu_1 ++;
- if(menu_1 >= 3)
- {
- menu_1 = 0;
- smg_i = 3; //數碼管顯示3位
- }
- }
- if(menu_1 == 1) //設置高溫報警
- {
- smg_i = 4; //數碼管顯示4位
- if(key_can == 2)
- {
- if(flag_lj_3_en == 0)
- t_high ++ ; //按鍵按下未松開自動加三次
- else
- t_high += 10; //按鍵按下未松開自動加三次之后每次自動加10
- if(t_high > 990)
- t_high = 990;
- }
- if(key_can == 3)
- {
- if(flag_lj_3_en == 0)
- t_high -- ; //按鍵按下未松開自動減三次
- else
- t_high -= 10; //按鍵按下未松開自動減三次之后每次自動減10
- if(t_high <= t_low)
- t_high = t_low + 1;
- }
- dis_smg[0] = smg_du[t_high % 10]; //取小數顯示
- dis_smg[1] = smg_du[t_high / 10 % 10] & 0xdf; //取個位顯示
- dis_smg[2] = smg_du[t_high / 100 % 10] ; //取十位顯示
- dis_smg[3] = 0x64; //H
- }
- if(menu_1 == 2) //設置低溫報警
- {
- smg_i = 4; //數碼管顯示4位
- if(key_can == 2)
- {
- if(flag_lj_3_en == 0)
- t_low ++ ; //按鍵按下未松開自動加三次
- else
- t_low += 10; //按鍵按下未松開自動加三次之后每次自動加10
- if(t_low >= t_high)
- t_low = t_high - 1;
- }
- if(key_can == 3)
- {
- if(flag_lj_3_en == 0)
- t_low -- ; //按鍵按下未松開自動減三次
- else
- t_low -= 10; //按鍵按下未松開自動加三次之后每次自動加10
- if(t_low <= 10)
- t_low = 10;
- }
- dis_smg[0] = smg_du[t_low % 10]; //取小數顯示
- dis_smg[1] = smg_du[t_low / 10 % 10] & 0xdf; //取個位顯示
- dis_smg[2] = smg_du[t_low / 100 % 10] ; //取十位顯示
- dis_smg[3] = 0x3D; //L
- }
- }
- /****************風扇控制函數***************/
- void fengshan_kz()
- {
- if(flag_en == 1)
- {
- if(temperature >= t_high) //風扇全開
- {
- TR1 = 1;
- pwm = 0;
- }
- else if((temperature < t_high) && (temperature >= t_low)) //風扇緩慢
- {
- f_pwm_l = 60;
- TR1 = 1;
- }
- else if(temperature < t_low) //關閉風扇
- {
- TR1 = 0;
- pwm = 1;
- }
- }
- }
-
- /****************主函數***************/
- void main()
- {
- static uchar value;
- time_init(); //初始化定時器
- temperature = read_temp(); //先讀出溫度的值
- delay_1ms(650);
- temperature = read_temp(); //先讀出溫度的值
- dis_smg[0] = smg_du[temperature % 10]; //取溫度的小數顯示
- dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取溫度的個位顯示
- dis_smg[2] = smg_du[temperature / 100 % 10] ; //取溫度的十位顯示
- while(1)
- {
- key(); //按鍵程序
- if(key_can < 10)
- {
- key_with(); //設置報警溫度
- }
- if(flag_200ms == 1) //200ms 處理一次溫度程序
- {
- flag_200ms = 0;
- temperature = read_temp(); //先讀出溫度的值
- if(menu_1 == 0)
- {
- smg_i = 3;
- dis_smg[0] = smg_du[temperature % 10]; //取溫度的小數顯示
- dis_smg[1] = smg_du[temperature / 10 % 10] & 0xdf; //取溫度的個位顯示
- dis_smg[2] = smg_du[temperature / 100 % 10] ; //取溫度的十位顯示
- }
- fengshan_kz(); //風扇控制函數
- value ++;
- if(value >= 4)
- {
- value = 0;
- if(miao != 0)
- {
- miao --; //時間減1
- }
- if(miao == 0)
- flag_en = 0;
- }
- if(hw == 1) //感應到人
- {
- miao = 30;
- flag_en = 1;
- }
- }
- display(); //數碼管顯示函數
- }
- }
- /*************定時器0中斷服務程序***************/
- void time0_int() interrupt 1
- {
- static uchar value; //定時2ms中斷一次
- TH0 = 0xf8;
- TL0 = 0x30; //2ms
- value++;
- if(value >= 150)
- {
- value = 0;
- flag_200ms = 1;
- }
- if(flag_lj_en == 1) //按下按鍵使能
- {
- key_time ++;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
智能溫控風扇設計.7z
(2.31 MB, 下載次數: 81)
2020-12-15 20:44 上傳
點擊文件名下載附件
|