我的單片機智能溫控風扇制作,優點是比較詳細(尤其是代碼的解釋),可能對論壇同好來說不值一提,不管怎樣,分享一下。我上傳了c文件、hex、還有uvproj和pdsprj的仿真。還有doc和pdf。
最后也做出來了實際電路。
第一次發帖,不知道說啥,發幾張圖吧。
1.完成電路原理圖的設計:本設計以STC89C52 單片機作為控制核心,采用高精度溫度傳感器DS18B20 檢測環境溫度,把經過ADC 轉換模塊輸出的數字溫度信號發送給STC89C52 單片機進行處理,在LCD 顯示屏上顯示當前環境溫度值和用按鍵預設的每個檔位溫度值,并采用PWM 脈寬調制方式改變直流風扇電機的轉速。系統結構如圖 1系統結構所示。 圖 1系統結構
2.用Proteus軟件畫電路原理圖,設計相關硬件,并通過Keil編輯C語言程序,并將編譯后生成的HEX文件放在所畫的硬件電路中仿真。 3.仿真成功后,焊接與調試電路板。 4.安裝驅動,將程序燒錄至單片機,觀察并調試直至達到設計要求。 二、設計要求1.讀取DB18B20溫度傳感器數據 2.風扇根據溫度變化自動調節轉速檔位:當前溫度在小于下限為0檔;在上下 限之間為1檔,大于上限為2檔。 3. 按一次K1進入溫度上限設置,K2,K3設置溫度的增加或者減少;按兩次K1進入溫度下限設置,K2,K3設置溫度的增加或減少;按三次K1退出設置模式。 4. 1602顯示屏顯示當前溫度、設置溫度的上下限,風扇當前檔位,進入設置模式后在相應位置用光標顯示。 三、設計過程(包括設計仿真圖)這張圖顯示了:單片機最小系統理應有的晶振和復位電路,這芯片里有ROM和RAM,所以也不加入片外的數據存儲器和程序存儲器了。 本實驗要用的三個按鈕資源接在了P3.5,P3.6,P3.7口,同時連接時線與接在單片機外部中斷口INT0之上,這里我用了觸發中斷,原因就是硬件可以自動清零,而且電平中斷的硬件設置還是比較麻煩的。(此處靈感來自于單片機原理與應用及C51程序設計第三版清華大學出版社的例題7.9) 電機 P3.3口處,可以看到標簽為motorDC;溫度傳感器P3.4,可以看見DSPORT標簽。 LCD的數據口是P1,可以看見我用總線連接,自動標好了D7-D0,對應了LCD的8根數據線。P2.5,P2.6,P2.7對應了LCD的RS,RW,E這三個端口。 
程序主函數大致意義如下:外部中斷0初始化 液晶初始化 循環以下: 小燈顯示 液晶顯示 風扇轉動 讀取溫度 讀取按鈕 計算擋位 中斷程序: 按鈕設置
小燈顯示
1.LED0
LED0用來顯示按鈕1也就是設置按鈕按了幾下:
void led(){
if(flag==0) LED0=0;
if(flag==1) LED0=1;
if(flag==2) {LED0=1;delay(250);LED0=0;delay(250);LED0=1;}}
flag
意義
0
默認是0,按鈕沒按,或者已經按了3下,小燈泡不亮
1
按了一下設置按鈕,小燈泡亮,意味進入了上限溫度調整狀態
2
按了兩下設置按鈕,小燈泡閃爍,意味進入了下限溫度調整狀態
2.LED1
void int0() interrupt 0 {
LED1=0;
keySet();
delay(500);
LED1=1;
}
LED1:只要你按了任何一個鍵,意味著進入了中斷,LED1都會閃一下

即得到右圖的畫面: 代碼解析: 1. 幾個端口的設置: #define LCD1602_DATAPINS P1 sbit LCD1602_E=P2^7; sbit LCD1602_RW=P2^6; sbit LCD1602_RS=P2^5; 2.局部變量講解 unsigned char printData[8] = {0,0,':',0,0,0,0,' '}; unsigned char Prompt[4][2]= {{'U','L'},{'L','L'},{'C','T'},{'G','R'}}; 這個就是等一會放8個小塊的字符數組,前面兩個字符會被Prompt替換。順便一提,這幾個英文字符分別為:上限(Upper Limit)和下限(Lower Limit),當前溫度(Current Temperature),擋位(GeaR)。第3-7個字符等一會會被LcdDisplay() 召喚calNumPrint()給替換掉。 3.寫命令/數據操作 void Lcd1602_WriteCom(uchar com); void Lcd1602_WriteData(uchar dat) ;這兩個得按照這個時序圖來,沒什么好說的,這個是抄廠家給的例程,毫無創新,畢竟對時序不敏感。 5. void calNumPrint(int temp); 這個就是用來填入printData4-7位。 | | if(temp>0)printData[3]='+'; elseprintData[3]='-'; | 判斷溫度的正負,理論上DS18B20 的測量范圍為 -55 ℃ ~+ 125 ℃ | for( i=4; i<7; i++) { dividend=1; for( j=6-i; j>0; j--)dividend*=10; printData[ i]=temp/dividend%10+'0';} | 就是為了根據所給的溫度填寫4-6位,之所以有dividend和下面的一條for語句是為了安全地(雖然可能沒有必要)確保只截取了一位 | | |
6. void Lcd1602_Init(); 

初始化,main()函數用的,不加這個你開不了LCD,更別提設定LCD的種種工作模式細節。這個是廠家給的例程,意義注釋有。
7. void LcdDisplay(int temp);

這個自創函數值得大說特說,1602一共16列2行,每一行放兩個8列1行的小塊。所以用了一個for循環for( loop=0; loop<4; loop++) 專門循環放這四個小塊,每一次循環都得改提示符,然后進入選擇根據當前循環分支語句,loop為0和1是溫度的上下限,調用calNumPrint函數算3-7個位置究竟是什么;loop為2得換行了,然后calNumPrint算當前的溫度怎么顯示;3時是擋位,不是溫度所以不能調用calNumPrint,我直接3-5位為空格,第6位直接算擋位顯示即可。最后每輪循環把算出的printData這一個字節八位ASCII符號送入LCD1602_WriteData讓LCD顯示即可。這個函數封裝和調用精致,沒有多余代碼殘余;缺點也有,有點費時間。 電機的驅動是由NPN以及PNP兩個不同類型的晶體管組成的復合管,復合后可等效為一個NPN晶體管,但是它理想情況下,能夠獲得兩個原本兩個管的乘積的放大倍數,這樣就可以有足夠的電流驅動集電極之上的直流電機旋轉。
如何根據擋位來控制單片機的轉動速率?只要單片機輸出占空比可調的方波,即PWM信號即可控制電機兩端的電壓發生變化,從而實現電機轉速的控制。占空比越大,所得到的平均電壓也就越大,幅值也就越大;占空比越小,所得到的平均電壓也就越小,幅值也就越小。我們利用軟件延時的方法調節占空比,當高電平延時時間到的時候,對I/O口電位取反,使變成低電平,再進行延時,低電平延時時間到,再進行取反使其轉化成為高電平,如此循環得到PWM信號。1.Ds18b20ReadTemp() | | | | | | tml = Ds18b20ReadByte(); tmh = Ds18b20ReadByte(); | | currtemp = tmh; currtemp <<= 8; currtemp |= tml; | | if(currtemp<0) {currtemp=currtemp-1; currtemp=~currtemp; } tp=currtemp; currtemp=tp*0.0625+0.5; | 轉化溫度為攝氏度,字節是溫度的補碼,所以其中正負有不同的處理,并且四舍五入 |
2.Ds18b20ChangeTemp() | | |
| |
| Ds18b20WriteByte(0xcc);Ds18b20WriteByte(0x44); | | | |
3.uchar Ds18b20Init() 做為從器件的DS18B20在一上電后就一直在檢測總線上是否有480-960微秒的低電平出現,如果有,在總線轉為高電平后等待15-60微秒后將總線電平拉低60-240微秒做出響應存在脈沖,告訴主機本器件已做好準備。 | | DSPORT = 0;i = 100;while(i--); | | | 釋放總線變為高電平,以等待溫感的成功回一,否則回零 |
4.void Ds18b20WriteByte(uchar dat): 寫周期最少為60微秒,最長不超過120微秒。寫周期一開始做為主機先把總線拉低1微秒表示寫周期開始。隨后若主機想寫0,則將總線置為低電平,若主機想寫1,則將總線置為高電平,持續時間最少60微秒直至寫周期結束,然后釋放總線為高電平至少1微秒給總線恢復 。而DS18B20則在檢測到總線被拉底后等待15微秒然后從15us到45us開始對總線采樣,在采樣期內總線為高電平則為1,若采樣期內總線為低電平則為0。 5.uchar Ds18b20ReadByte() 讀周期是從主機把單總線拉低1微秒之后就得釋放單總線為高電平,以讓DS18B20把數據傳輸到單總線上。作為從機DS18B20在檢測到總線被拉低1微秒后,便開始送出數據,若是要送出0就把總線拉為低電平直到讀周期結束。若要送出1則釋放總線為高電平。主機在一開始拉低總線1微秒后釋放總線,然后在包括前面的拉低總線電平1微秒在內的15微秒時間內完成對總線進行采樣檢測,采樣期內總線為低電平則確認為0。采樣期內總線為高電平則確認為1。完成一個讀時序過程,至少需要60微秒才能完成。 | | | | | | |
| | | |
| | | 如果這位有輸入,就讀入到byte上,從最低一位開始讀取 | | | | |
6.void Ds18b20ReadTempCom() | | | | Ds18b20WriteByte(0xcc);Ds18b20WriteByte(0xbe); | |
7.各個函數之間的關系
1.void keySet() 此函數中根據nowkey選擇不同的分支,想見表。其中,default就是nowkey==0,什么也不做,case 1情況下稍后再提,先講一下case 2或者3究竟做了什么:tempLim[0]是溫度上限,tempLim[1]是溫度下限,flag-1只可能為1或者2; value[0]是正一,value[1]是負一,nowkey-2只可能為1或者2; 所以這里其實就是改上/下限值與+/-:用flag區分到底是上/下限值,用nowkey區分到底是+/-。最后還要檢查上限不小于下限,如果下限比上限還要大,那么讓上限和下限趨同。可以參考下面兩張狀態表理清思路。
2. uchar keyscan()
電路圖可以看到三個按鈕分別接了P3.5,P3.6,P3.7;同時它們線與接入外部中斷零,當外部中斷零檢測到低電平時候,中斷調用keySet(),keySet()又會召喚keyscan(),keyscan()的用處就是返回為nowkey,這是去抖處理后判斷的按下的按鈕符號。 
根據currtemp和tempLim[0/1]也就是當前溫度和上下限值判斷在哪一個擋位,更改全局變量gears以作為結果:大于等于上限就開二檔;小于上限,大于等于下限開一檔;比下限還小就是零檔。四、設計結果(硬件實現結果圖,包括各個部件) 當前溫度24度,默認的上限和下限設置是35度和25度,所以當前擋位為零檔,電機當前KRPM為正0.02,零檔沒開。D1是暗的因為沒有按設置按鈕。 當前溫度被調整為27度,所以當前擋位為一檔,電機現在走走停停。
按設置按鈕(第一個按鈕)一次,D1變亮。再按第二個加法按鈕三下,第三個減法按鈕一下,上限加一三次后又減一,結果如圖UL:+037;擋位隨之變1,風扇開始忽慢忽快地轉動。按按鈕時候可以觀察到D2因為進入中斷而閃動一次,不按時恢復。 再按設置按鈕(第一個按鈕)一次,D1開始閃動(圖里面變暗是因為靜態捕捉到的是變暗的時候)。再按第二個加法按鈕一下,第三個減法按鈕三下,下限減一三次后又加一,結果如圖LL:+023;擋位不變,風扇繼續忽慢忽快地轉動。按按鈕時候可以觀察到D2因為進入中斷而閃動一次,不按時恢復。 當前溫度被調整為50度時候,當前擋位變為2檔,電機全力旋轉,LCD有相應顯示。
在經過硬件、軟件的單獨調試之后,即可進入硬件和軟件聯合仿真調試的階段。將下圖中統一發放的元件進行焊接,并用杜邦線按照仿真示意圖連接。
五、實驗器件(器件清單)
1) 萬用板(小) 一塊
2) 7015風扇 一個
3) STC89C52RC單片機最小系統板 一塊
4) 1602液晶顯示屏 一塊
5) 10k電阻 兩個
6) 1k電阻 三個
7) DS18B20 一個
8) 8550三極管 一個
9) 8050三極管 一個
10) 排針 20針
11) 按鍵 三個
12) 杜邦線 25條
13) 焊錫若干
14) DC電源粗頭電源線 一條
15) 排座
16) CH340下載
全部資料51hei下載地址(仿真程序):
溫控風扇.zip
(2.06 MB, 下載次數: 255)
2021-3-6 15:50 上傳
點擊文件名下載附件
我的設計 下載積分: 黑幣 -5
|