系統主要設計了一個基于單片機的風扇溫控儀,以單片機和DS18B20 傳感器為核心,具有溫度顯示和控制風扇轉速功能DS18B20 傳感器,將檢測到的溫度轉化為數字信號,單片機對輸入的數字信號進行分析處理,當溫度高于上限值時,風扇全速旋轉;當溫度低于下限時,風扇停轉;當溫度處于上限值與下限 之間時,風扇轉速越慢,。圖1 所示為系統設計結構框圖。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png (16.08 KB, 下載次數: 48)
下載附件
2021-5-14 03:14 上傳
電路原理圖如下:
51hei.png (34.05 KB, 下載次數: 51)
下載附件
2021-5-14 03:16 上傳
單片機源程序如下:
- #include <reg52.h>
- #include <stdio.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit dq=P3^6;
- sbit w4=P2^6;
- sbit w3=P2^4;
- sbit w2=P2^2;
- sbit w1=P2^0;
- sbit dp=P0^7;
- sbit fs=P3^7;//風扇接口
- sbit key_shezhi=P1^5;
- sbit key_jia=P1^6;
- sbit key_jian=P1^7;
- uchar flag_0;
- uint t_max=250,t_max_1=300;
- uint count=0;
- int wendu,t;
- uchar speed; //速度變量
- void delay(uint z) //延時函數
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /********************************/
- void pro()//按鍵處理函數
- {
- if(key_shezhi==0)
- {
- delay(10);
- if(key_shezhi==0)
- {
- flag_0++;
- if(flag_0>=3)
- flag_0=0;
- while(!key_shezhi) ;
- }
- }
- }
- /**********************************/
- uchar code table[]={
- 0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8, 0x80,0x90,0xbf//0 1 2 3......7 8 9 的字形碼
- };
- uchar code table1[]={
- 0xc7,0x89 // L H 的字形碼
- };
- uint temp,mm;uchar i;float f_temp;
- /***********************小延時函數*****************************/
- void delay_uint(uint q)
- {
- while(q--);
- }
- /*******************************************************
- /***********************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,wendu;
- for(i=0;i<8;i++)
- {
- dq = 0; //把總線拿低讀時間隙開始
- wendu >>= 1; //讀數據是低位開始
- dq = 1; //釋放總線
- if(dq == 1) //開始讀寫數據
- wendu |= 0x80;
- delay_uint(5); //60us 讀一個時間隙最少要保持60us的時間
- }
- return wendu; //返回數據
- }
- /*************讀取溫度的值 讀出來的是小數***************/
- uint read_temp()
- {
- uint wendu;
- 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); //發出讀取暫存器命令
-
- EA = 0;
- low = read_18b20(); //讀溫度低字節
- wendu = read_18b20(); //讀溫度高字節
- EA = 1;
- wendu <<= 8; //把溫度的高位左移8位
- wendu |= low; //把讀出的溫度低位放到value的低八位中
- wendu *= 0.625; //轉換到溫度值 小數
- return wendu; //返回讀出的溫度 帶小數
- }
- void display0()
- {
- P0=0xff;//消隱
- w1=0; //選通第一位數碼管
- if(speed>5) //如果speed的值>5則檔位顯示speed-5,比如speed=6,則顯示1檔
- P0=table[speed-5];//顯示檔位
- else //否則speed的值如果小于5,則顯示0檔
- P0=table[0];//顯示檔位
- delay(2);//延遲一會
- w1=1;//關閉第一位數碼管
-
- P0=0xff;//第二位數碼管的顯示原理及方法同上
- w2=0;
- P0=0xbf;//顯示-
- delay(2);
- w2=1;
-
- P0=0xff;
- w3=0;
- P0=table[wendu/100];//顯示溫度十位
- delay(2);
- w3=1;
-
- P0=0xff;
- w4=0;
- P0=table[wendu%100/10];//顯示溫度各位
- delay(2);
- w4=1;
- }
- void zi_dong()//自動溫控模式
- {
- // 此函數的目的是將上限和下限的差值平均為5份,每一份對應一個速度值 14-25
- if(wendu<t_max) //溫度小于下限
- speed=0; //速度0檔
- else if(wendu>=t_max&&(wendu<(uint)((t_max_1-t_max)/4+t_max))) //溫度大于下限并且小于(上限減去下限)除以4加下限
- speed=6; //6檔 14-16.75 14-15
- else if((wendu>=(uint)((float)(t_max_1-t_max)/4+t_max))&&(wendu<(uint)((float)(t_max_1-t_max)/2+t_max))) //溫度大于 (上限減去下限)除以4加下限 并且小于(上限減去下限)除以2加下限
- speed=7; //7檔 16-19.5 16-18
- else if((wendu>=(uint)(t_max_1-t_max)/2+t_max)&&(wendu<(uint)((float)((float)(t_max_1-t_max)/4)*3+t_max))) //溫度大于 (上限減去下限)除以2加下限 并且小于(上限減去下限)除以4乘以3加下限
- speed=8; //8檔 19-22.25 19-21
- else if((wendu>=(uint)((float)((float)(t_max_1-t_max)/4)*3+t_max))&&wendu<t_max_1) //溫度大于 (上限減去下限)除以4乘以3加下限 并且小于上限
- speed=9; //9檔 22-24 22-24
- else if(wendu>=t_max_1) //大于上限
- speed=10; //10檔 >25
- }
- /***************************************/
- void fengshan()
- {
- uchar m;
- if(m<speed) //m值小于speed
- fs=0; //打開風扇
- else if(m>=speed) //否則
- fs=1; //關閉風扇
- m++; //m加
- if(m>=10) //m極愛到10,也就是2ms
- m=0;
- }
- /**************************************/
- /**************************************/
- void display1()
- {
- P0=0xff;//消隱
- w1=0;//選通第一位數碼管
- P0=table1[0];//顯示 L
- delay(2);//延遲一會
- w1=1;//關閉第一位數碼管
-
- P0=0xff;//第二位數碼管顯示方法及原理同上
- w2=0;
- P0=0xbf;//顯示 -
- delay(2);
- w2=1;
-
- P0=0xff;
- w3=0;
- P0=table[t_max/100];//顯示設置下限值的十位
- delay(2);
- w3=1;
-
- P0=0xff;
- w4=0;
- P0=table[t_max%100/10];//顯示設置下限值的個位
- delay(2);
- w4=1;
- }
- /**************************************/
- void display2()
- {
- P0=0xff;
- w1=0;
- P0=table1[1];//顯示 H
- delay(2);
- w1=1;
-
- P0=0xff;
- w2=0;
- P0=0xbf;//顯示 -
- delay(2);
- w2=1;
-
- P0=0xff;
- w3=0;
- P0=table[t_max_1/100];//顯示設置上限值得十位
- delay(2);
- w3=1;
-
- P0=0xff;
- w4=0;
- P0=table[t_max_1%100/10];//顯示設置上限值得個位
- delay(2);
- w4=1;
- }
- /***************************************/
- void shezhi()
- {
- if(flag_0==1)//flag_0==0時,為正常顯示。等于1時,為設置下限位值。等2時為設置上限為置
- {
- if(key_jia==0)//當設置下限位值時,按下加鍵
- {
- delay(10);//延遲消抖
- if(key_jia==0)//確認加鍵已按下
- {
- t_max=t_max+10;//對下限位值每次加10
- if(t_max>=t_max_1) //防止低溫度高于高溫度//如果下限位值設置時超過了上限位置
- t_max=t_max_1-10; //則讓下限位值-10
- while(!key_jia);//松手檢測
- }
- }
- if(key_jian==0)//如果鍵鍵按下了,同上
- {
- delay(10);
- if(key_jian==0)
- {
- t_max=t_max-10;
- while(!key_jian);
- }
- }
- }
- if(flag_0==2)//對上限位設置時
- {
- if(key_jia==0)
- {
- delay(10);
- if(key_jia==0)
- {
- t_max_1=t_max_1+10;
- while(!key_jia);
- }
- }
- if(key_jian==0)
- {
- delay(10);
- if(key_jian==0)
- {
- t_max_1=t_max_1-10;
- if(t_max_1<=t_max) //防止高溫度小于低溫度
- t_max_1=t_max+10;
- while(!key_jian);
- }
- }
- }
- }
- void display()
- {
- if(flag_0==0)//flag_0==0時,為正常顯示。等于1時,為設置下限位值。等2時為設置上限為置
- display0();//正常顯示
- else if(flag_0==1)
- display1();//設置下限時的顯示
- else if(flag_0==2)
- display2(); //設置上限時的顯示
- }
- void main()
- {
- while(1)
- {
-
- read_18b20();//讀取溫度傳感器中的數據
-
- t=read_temp();//把讀出的數據賦給t
- if(t>=0&&t<=1250) //溫度合法范圍,不在這個范圍就是沒有獲取到合適的值
- {
- wendu=t;
- }
- pro();//按鍵處理
- display();//顯示處理
- shezhi();//設置按鍵處理
- fengshan();//風扇處理
- zi_dong();//自動擋風扇處理
- }
- }
復制代碼
51hei.png (8.43 KB, 下載次數: 56)
下載附件
2021-5-14 03:16 上傳
全部資料51hei下載地址:
小風扇.7z
(269.68 KB, 下載次數: 36)
2021-5-13 22:53 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|