摘要
自動化和節能化是目前洗衣機發展的主流趨勢。本文根據對洗衣機節能指標的要求,通過方案對比,選擇89C52單片機作為控制核心,實施以節水為主要目標的節能洗衣機理念的設計與實現。
本文詳細闡述了系統的各個功能模塊及其工作過程。洗衣機由鍵盤設定洗衣模式,并采用傳感器檢測洗衣過程中的水量、水的混濁程度等參數,通過單片機的八個子程序的處理,實現對洗衣機自動識別水量,自動識別濁度,自動決定漂洗時間和漂洗次數等功能的控制。
1 緒論
1.1 課題背景
1.2 課題的意義
1.3 設計內容
2 系統硬件設計
2.1 方案選擇
2.2 系統總體結構設計
2.3 模塊電路設計與元件選擇
3 系統軟件設計
3.1 系統主程序
3.2 計算時間子程序
3.3 中斷程序
3.4 顯示時間子程序
3.5 濁度數據AD轉換及漂洗控制子程序
3.6 鍵盤掃描子程序
3.7 鍵盤服務子程序
3.8 工作模式設定程序
3.9 系統動作服務程序
4 系統調試與分析
5 總結
參考文獻
致 謝
附錄一 系統原理圖
附錄二 源程序
本系統實現了對洗衣機整個洗衣過程的控制,包括用戶參數輸入,洗滌,漂洗,濁度檢測,脫水等幾大步驟。洗衣機就會在每次漂洗完成后智能判斷洗滌水的混濁情況,對于不同的污濁度設計了不同的漂洗時間。若在任何一次漂洗結束時進行的濁度檢測結果表明洗滌水已足夠清凈,程序就會直接跳轉至“脫水”模式進行衣物脫水,從而節約了大量的冗余漂洗時間和能源。波輪式全自動洗衣機的結構如圖2.2所示[10]。
2.3 模塊電路設計與元件選擇2.3.1 電源設計電源模塊是為整個電路系統和伺服機構提供能源和動力的重要保證。一般的直流穩壓電源由整流電路、濾波電路和穩壓電路等幾部分組成[11]。 本機電源采用雙路輸出+5V和+12V,分別用于提供電子電路工作電源和電磁閥驅動電源。使用交流變壓器將220V市電降壓至15V,經過二極管整流橋整流、電容濾波和穩壓管穩壓,能輸出穩定的直流5V和12V電壓。電源模塊的電路原理圖如圖2.3所示。 圖2.3 雙路穩壓電源模塊
2.3.3 LED燈顯示與74HC573鎖存器節能洗衣機系統有六個基本的狀態,分別是厚物洗滌,薄物洗滌,漂洗,脫水,暫停,停止和報警。本系統用六個發光二極管作為狀態指示燈,使用共陽極接法,由單片機P1口通過一個鎖存器來控制它們的亮滅。LED燈的電路接法如圖2.6所示。 BACK 
圖2.6 LED狀態指示燈 鎖存器(Latch)是一種對脈沖電平敏感的存儲單元電路,它們可以在特定輸入脈沖電平作用下改變狀態。典型的鎖存器邏輯電路是 D 觸發器電路[13]。本設計使用的74HC573鎖存器的真值表如表2.2所示。 BACK 表2.2 鎖存器的真值表
74HC573的八個鎖存器都是透明的D型鎖存器,當使能引腳LE為高電平時,Q輸出將隨數據D輸入而變化;反之,鎖存器進入鎖存狀態,D將保持原有信號的輸出而不受輸入信號變化的影響[14]。鎖存器的引腳功能與封裝如圖2.7所示。 圖2.7 鎖存器的引腳及其功能 在在本課題的應用中,單片機P0口和P1口的八路 I/O 口上分別需要外接鎖存器,這是為了實現數據和地址在I/O口上的復用。BACK 2.3.4 七段數碼管顯示LED(Light Emiting Diode)是發光二極管英文名稱的縮寫。常用的LED有共陽極和共陰極2種。共陰極LED顯示器的發光二極管的陰極連在一起,通常此公共陰極接地[15]。本次設計是用于顯示時間,采用共陰極LED顯示就可以有較好的顯示效果。 在多位LED顯示時,通常將所有位的段碼線相應段并聯在一起,由1個8位I/O口控制,形成段碼線的多路復用,而各位的共陰極或共陽極分別由相應的地址線控制,形成各位的分時選通[16]。七段數碼管電路如圖2.8所示。 BACK 圖2.8 七段數碼管顯示 2.3.5 濁度檢測模塊設計TS濁度傳感器是GE公司開發的一種專門用于家電產品的低成本傳感器,主要用于洗衣機、洗碗機等產品的水污濁程度的測量,其內部結構原理圖如圖2.9所示。此種濁度傳感器體積小,兼容TTL電平,使用方便[17],故本次設計采用TS濁度傳感器。 BACK 
圖2.9 TS濁度傳感器結構原理圖 濁度傳感器的工作原理是:當光線穿過一定量的水時,光線的透過量取決于該水的污濁程度:水越污濁,透過的光就越少。光接收端把透過的光強度轉換為對應的電壓大小。通過測量接收端的電壓,就可以計算出水的污濁程度。洗滌水的透光度與洗滌時間t的關系曲線如圖2.10所示。 BACK (a)圖為洗滌全過程的濁度變化 (b)圖為輕污和重污的透光度比較 圖2.10 洗滌水的透光度與洗滌時間t的關系曲線 在節能洗衣機系統中,濁度傳感器安裝在洗衣機的排水管口附近,如圖2.11所示,在洗衣機開始排水時啟動數據采集進行水質檢測,并將檢測結果送單片機。 
圖2.11 濁度傳感器的工作示意圖 濁度值是由TS濁度傳感器測得濁度數據,送ADC0804進行模數轉換后所得的數值。實際應用中,應根據不同容量的洗衣機進行實驗來確定更準確的濁度值與對應的洗滌時間。表2.3表明衣物濁度與洗滌參考時間的關系。 BACK 表2.3 洗滌水濁度與洗滌參考時間的關系 ADC0804是用CMOS集成工藝制成的逐次比較型摸數轉換芯片。該芯片內有輸出數據鎖存器,當與控制器連接時,無須附加邏輯接口電路。逐次比較型AD由一個比較器和DA轉換器通過逐次比較邏輯構成,從MSB開始,順序地對每一位將輸入電壓與內置DA轉換器輸出進行比較,經多次比較而輸出數字值。其優點是速度高、功耗低。ADC0804引腳如圖2.12所示。 BACK 圖2.12 ADC0804引腳功能 在本系統中,濁度信號轉換為0V~5V電壓信號,濁度傳感器連接ADC0804的輸入接口進行采樣處理,然后將電壓信號轉換為8位數值0x00~0xff送入單片機P1口。TS濁度傳感器及其數據AD采樣電路如圖2.13所示。 BACK 圖2.13 TS濁度傳感器及其數據AD采樣電路 2.3.6 電機控制本設計采用家用洗衣機常用的單相交流電機,這種電機有兩個繞組:主繞組和副繞組,兩個繞組在空間上相差90度。在啟動繞組上串聯一個容量較大的啟動電容,由于電容器作用使啟動繞組中的電流在時間上比運行繞組超前90度角,先到達最大值。在時間和空間上形成兩個相同的脈沖磁場,使定子與轉子之間產生一個旋轉磁場,電機轉子中產生感應電流,與旋轉磁場互相作用產生電磁場轉矩,使電機旋轉起來。 BACK 普通單相電機這兩個繞組完全一樣,互相可以交換。要使電機反轉,只要交換兩個繞組中的一個繞組的首尾接線就可反轉。電機的調速是通過一個串接線圈實現。單相交流電機的正反轉控制原理如圖2.14所示。 BACK 圖2.14 單相交流電機的正反轉控制 在本設計中,采用兩只HJR1-2C電磁繼電器控制電機正反轉,一只HRS2H-S電磁繼電器控制電機的旁路繞阻以實現脫水時電機的高轉速工作。電機控制部分的電路原理圖如圖2.15所示。 
圖2.15 電機控制部分 2.3.7 水閥水閥的動作采用電磁閥控制,使用兩只HRS2H-S電磁繼電器耦合來控制兩個大功率電磁閥。進水或排水時,由單片機發出指令,使繼電器觸點吸合,接通水閥的電磁鐵,帶動閥門執行進水或排水操作。水閥電路如圖2.16所示。 BACK
圖2.16 水閥控制電路 2.3.8 水位傳感器 水位傳感器采用吸簧式浮子傳感器,它本身輸出的就是數字信號。當水位有變化時,浮子隨著水位上下浮動,內置磁石使對應高度的簧片吸合,觸點導通;浮子離開時,當前觸點斷開,到下一個觸點吸合。單片機掃描觸點變化信號就可判斷當前洗衣桶內的水位。水位傳感器結構示意圖如圖2.17所示。 BACK 圖2.17 水位傳感器結構示意圖 2.3.9 電磁繼電器本電路系統是低壓控制高壓類型的程控電子線路,由芯片輸出的邏輯電平+5V來控制交流220V的負載電機。當繼電器線圈兩端有電流時,線圈產生的磁通使銜鐵吸向鐵芯極面,從而推動常閉觸點斷開,常開觸點閉合;當線圈兩端電流小于一定值時,機械反力大于電磁吸力,銜鐵回到初始狀態,常開觸點斷開,常閉觸點接通。繼電器原理圖如圖2.18所示。 BACK 圖2.18 繼電器原理圖 3 系統軟件設計3.1 系統主程序根據硬件設計要求,控制主程序流程如圖3.1所示。洗衣機通電后,單片機上電進行程序的初始化操作,默認洗衣機工作模式為“厚物洗滌”,并顯示此工作模式下的預設時間,然后掃描鍵盤,等待用戶命令。當按下“開始”鍵后,系統就開始倒計時,并進入相應的工作模式程序開始洗滌.
系統調試與分析在完成節能洗衣機控制系統的設計后,將程序在系統硬件上進行功能驗證。系統硬件組成部分如圖4.1所示。 圖4.1 節能洗衣機系統硬件部分 系統上電后,會進入默認的“厚物洗滌”模式并等待操作,如圖4.2所示。通過模式選擇按鍵可切換至“薄物洗滌”模式。這時只要按下“開始”鍵,洗衣機就會按照程序設定開始工作。 圖4.2 系統上電后的等待狀態 在選定洗滌模式之后按下開始鍵,系統開始倒計時,并打開進水閥進水,如圖4.3所示。在預定水位達到后,控制器關閉進水閥,主電機在程序的控制下間歇正反轉,帶動波輪和洗衣桶轉動進行洗滌,如圖4.4所示。 BACK       圖4.3 進水狀態
     圖4.4 洗滌狀態 洗衣機完成漂洗后進入歷時2分鐘的脫水模式工作。如圖4.5所示,脫水狀態指示燈點亮,排水閥打開,電機在高速檔運作。若此時在時間剩余1分鐘內水位降至最低,則洗衣機直接跳出脫水程序,完成洗滌,進入停機等待狀態。      圖4.5 系統“脫水”工作狀態 在系統的正常工作中,若有異常情況出現,系統會立刻中斷當前工作任務,進入“報警”狀態:使電機停車等待,蜂鳴器發出告警音響,如圖4.6所示。當處理異常情況后,按下“開始”鍵洗衣機就會恢復到原來的工作狀態,繼續洗滌工作。 圖4.6 系統進入“報警”狀態 經過硬件驗證,本系統除具備洗衣機基本功能外,也具有智能判斷濁度,自主決策漂洗時間,根據水位情況制定洗滌任務等功能,本課題設計最終實現節能洗衣機的預期功能。 BACK
5 總結本課題采用STC89C52單片機對家用洗衣機進行智能控制,設計的節水控制洗衣機系統充分應用了濁度檢測技術,通過硬件設計與軟件編程,實現了洗衣機的節能控制,一個按鈕就能完成洗衣的全過程,且將洗衣機水耗降至最低。本設計系統的特點有: BACK (1) 由TS濁度傳感器和水位傳感器檢測到衣物的污濁度與洗滌所用水量,既能保證洗凈衣物又使洗滌時間縮短,最大限度地提高洗滌效果,節約能源及用水量,達到了本設計設定的節水這一主要目的。 (2) 本設計還考慮到半自動時的情況,用戶可以根據自己的需求自由選擇洗衣機的工作方式與洗滌時間。在洗衣機工作的任一過程中,用戶可根據需要隨時暫停洗衣機,機蓋檢測和過載保護能有效保證用戶安全與洗衣機穩定工作,延長使用壽命。 BACK 在本課題的設計過程中,也出現了不少問題。如濁度傳感器暫時找不到,找到的雖然精度高質量好,但是價格不菲。經過分析,發現濁度傳感器在工作中輸出的是0V~5V的模擬電壓信號,而這個信號可用電位器輸出,給設計和實物檢驗帶來極大方便。 BACK 本設計仍存在一些不足之處,如洗衣機水位調節只有二級水位變化,在實際應用中可以增加水位調節級別,以便把洗衣機的節能功效發揮到最大;雖然系統消除了繼電器動作單元對控制單元的影響,但在同塊萬用板上焊接的幾個電磁繼電器之間又相互影響,看來只有使用更規范的PCB電路板和更合理的布線才能消去這種干擾。在軟件設計方面,本課題的軟件設計只考慮了各功能模塊都正常運行的情況,而沒設計在某個關鍵器件故障時系統的自檢與保護性停機的程序,故在不同的系統中可視具體情況在程序中加入更加全面的故障處理與保護功能以使系統完善。由于時間所限,本設計的硬件模擬只能做出節能洗衣機的幾大基本功能,不能做出較完善和較全面的多功能控制系統,也是本設計的遺憾之處。
附錄一 系統原理圖
單片機源程序如下: - <font color="rgb(0, 0, 0)">/*=======================================
- 基于STC89C52單片機的
- 節能洗衣機控制程序設計
- =========================================*/
- #include<reg52.h>
- #include<intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
-
- sbit dula = P2^6; //段鎖存。P0是數碼管數據端
- sbit wela = P2^7;
- sbit beep = P2^3;
- sbit diola= P2^5; //LED指示燈鎖存
-
- sbit mod_hou = P1^0; //厚物指示
- sbit mod_bao = P1^1; //薄物指示
- sbit mod_rewash = P1^2; //漂洗指示
- sbit mod_dry = P1^3; //甩干指示
- sbit mod_pause =P1^4; //暫停指示
- sbit mod_stop = P1^5; //停止指示
- sbit mod_error= P1^6; //錯誤指示
-
- sbit mola = P2^4; //伺服控制的鎖存器使能
- sbit molf = P1^0;
- sbit mort = P1^1;
- sbit mosp = P1^2;
- sbit wtin = P1^3;
- sbit wtot = P1^4;
- sbit adwr = P3^6; //ADC的控制針
- sbit adrd = P3^7;
-
- uint mh, ml, sh, sl;
- uchar we, du, count, fen, miao; //LED位鎖,段鎖,中斷計數,分,秒
- uchar key_num, mod_flag, tmp_mod; //按鍵返回值,模式標志,臨時模式標志
- uchar adc_rewash, adc_display_mod; //AD判斷是否漂洗,AD結果是否顯示;
- uchar adc_samp; //ADC轉換結果變量
- uchar wt_h, wt_m, wt_l; //水位指示:高,中,低,水位標志
- uchar action_mod, wt_io_action; //工作標志緩存,進排水動作標志
- uchar rewash_times; //記錄漂洗次數
- bit flag_1s; //1s標志位
- uint flag_1s_counter; //1s計數
-
- uchar code table_of_duanma[] = { //共陰碼段
- 0x3f, 0x06, 0x5b, 0x4f, // 0, 1, 2, 3,
- 0x66, 0x6d, 0x7d, 0x07, // 4, 5, 6, 7,
- 0x7f, 0x6f, 0x40, 0x00 }; // 8, 9, -, ,
-
- //=== 延時子程序 ====================================
- void delay(uchar z)
- {
- uchar x, y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- //=== 蜂鳴子程序 ====================================
- void beep_on(uchar beep_mod) //蜂鳴器發聲模式:
- { //1-短促(按鍵響應 和 模式切換) 2-稍長(結束提示) 3-很長(報警)
- uchar bp_ct; //計算發聲次數的局部變量
- switch(beep_mod)
- {
- case 1: { //模式 1 -短促(用于按鍵)
- for( bp_ct=3;bp_ct>0;bp_ct-- )
- {
- beep = 0;
- delay(100);
- beep = ~beep;
- }
- beep = 1;
- }
- break;
- case 2: { //模式 2 -稍長(結束提示)
- for( bp_ct=5;bp_ct>0;bp_ct-- )
- { beep = 0;
- delay(500);
- beep = ~beep;
- }
- beep = 1;
- }
- break;
- case 3: { //模式 3 -很長(報警)
- for( bp_ct=7;bp_ct>0;bp_ct-- )
- {
- beep = 0;
- delay(500);
- beep = ~beep;
- }
- beep = 1;
- }
- break;
- default:{ //其他情況視為錯誤,長2聲
- for( bp_ct=11;bp_ct>0;bp_ct-- )
- {
- beep = 0;
- delay(500);
- }
- beep = 1;
- }
- break;
- }
- }
-
- //=== 系統初始化 ==============================
- void init()
- {
- fen = 15;
- miao = 0;
- count = 0;
- wt_h = 0;
- wt_m = 0;
- wt_l = 1;
-
- P0 = 0x00; //端口置位,防止干擾
- P1 = 0xff;
- P2 = 0x00;
- wela = 0;
- dula = 0;
- diola= 0;
- mola = 0; //關閉電機控制,等待指令操作
- beep_on(2); //開機聲音響應
- beep = 1; //關閉蜂鳴器
- rewash_times = 0; //漂洗次數初值:0次
-
- key_num=16; //按鍵返回值:無按鍵
- mod_flag=1; //模式標志
- tmp_mod=0; //臨時模式寄存標志
-
- TMOD = 0x01;
- TH0 = (65536-50000)/256;
- TL0 = (65536-50000)%256;
- IE = 0x82; //中斷使能位置1: EA = 1,ET0 = 1。或直接設IE也得
- }
-
- //=== 倒計時 =========================
- void count_time()
- {
- if(count==20)
- {
- count=0; //倒計時:
- if(fen>0) //分鐘大于0時
- {
- if(miao>0 && miao<60) // 0 < miao < 60
- {
- miao--;
- } //秒減1
- else //if(miao<0 || miao>59) //若秒不在0~59內
- {
- miao=59; //說明進位了,就拉回值域
- fen--; //然后分鐘減1
- }
- }
- else if(fen==0) //分鐘為0時,即在最后一分鐘內時
- {
- if(miao>0 && miao<=59) //秒還沒進位的話
- miao--; //秒就減1
- else if(miao==0) //若秒走到0了,則計時時間到
- { TR0 = 0; //停定時器
- //時間到00:00,當前模式工作完成,進入下一模式繼續:
- beep_on(1); //蜂鳴模式1:模式切換
- }
- }
- }
- }
-
- //=== 顯示時間 ===========================
- void display_time()
- {
- if(adc_display_mod != 1) //若ADC結果不顯示(≠1時),就進入時間顯示
- { //否則跳出。以此來消去AD顯示時的時間部分干擾
- for(we=0xdf;we!=0xfe;we=_cror_(we,1))
- { //we==1101 1111 開始右移
- wela = 0;
- P0 = we;
- wela = 1; //位選
- wela = 0;
- delay(1);//這個delay只能是1,大于3嚴重閃爍,大于5時間不走...
- dula = 0; //段選
- switch(we)
- {
- case 0xdf: P0=table_of_duanma[miao%10];
- break;
- case 0xef: P0=table_of_duanma[miao/10];
- break;
- case 0xf7: P0=0x40; // - 間位符
- break;
- case 0xfb: P0=table_of_duanma[fen%10];
- break;
- case 0xfd: P0=table_of_duanma[fen/10];
- break;
- case 0xfe: P0=0x00; //關閉最高位
- we=0xdf;
- break;
- }
- dula = 1;
- delay(1);
- P0 = 0x00; //關數碼管
- dula = 0;
- }
- }
- }
-
- //=== 工作模式指示燈 =========================
- void display_mod() //顯示:僅用于點亮LED工作模式指示燈
- {
- mola = 0; //關閉電機控制鎖存器使能
- P1 = 0xff; //改變 mod_flag
- diola = 1;
- delay(1);
- switch(mod_flag)
- {
- case 1: { mod_hou = 0; } //標志 1:厚物洗滌
- break;
- case 2: { mod_bao = 0; } //標志 2:薄物洗滌
- break;
- case 3: { mod_rewash = 0; } //標志 3:漂洗
- break;
- case 4: { mod_dry = 0; } //標志 4:甩干
- break;
- case 5: { mod_pause = 0; } //標志 5:暫停
- break;
- case 6: { mod_stop = 0; } //標志 6:停止
- break;
- case 7: { mod_error = 0; } //標志 7:報警
- break;
- }
- diola = 0;
- }
-
- //=== ADC Display =========================
- void adc_display(uchar bai_c,uchar sh_c,uchar g_c) /
- {
- P0=table_of_duanma[bai_c]; //顯示百位
- dula=1;
- dula=0;
-
- P0=0xfe; //確定顯示用數碼管的位地址
- wela=1;
- wela=0;
- delay(10); //延時放在這是為了消除鬼影
-
- dula=0;
- P0=table_of_duanma[sh_c]; //顯示十位
- dula=1;
- dula=0;
-
- wela=0;
- P0=0xfd;
- wela=1;
- wela=0;
- delay(10);
-
- P0=table_of_duanma[g_c]; //顯示個位
- dula=1;
- dula=0;
-
- P0=0xfb;
- wela=1;
- wela=0;
- delay(10);
- }
- //=== AD轉換 =============================
- void adc_serve()
- {
- uchar a,A1,A2,A2t,A3;
- dula=0; //關閉7段數碼管的顯示
- wela=1; //打開有ADC片選的鎖存器
- P0=0; //P0^7針為0時,選通ADCS
- adwr=0; //AD寫入,低電平有效(主要是為了啟動AD轉換)
- display_mod(); //顯示一下工作模式,(為了給AD轉換延時)
- adwr=1; //關ADC寫入使能
- P0=0xff; //關閉ADCS
- if(adc_display_mod==1) //ADC顯示標志為1(0就不顯示結果)。
- { wela=0;
- for(a=10;a>0;a--)
- {
- delay(10);
- adc_display(A1,A2,A3); //送去顯示各個數位。
- }
- }
- wela = 1; //重新打開有AD片選信號鎖存器的鎖存端
- P1 = 0xff; //讀取P1口之前先給其寫全1
- P0 = 0; //選通ADCS
- adrd = 0; //AD讀使能
- adc_samp = P1; //AD數據讀取賦給P1口
- adrd = 1; //關閉AD讀使能
- P0 = 0xff; //關閉ADCS片選
- adwr =0 ; //打開AD寫
- if(adc_display_mod==1) // 若允許AD顯示
- { A1=adc_samp/100; //分出百,十,和個位
- A2t=adc_samp%100;
- A2=A2t/10;
- A3=A2t%10; //AD原理:透過的光多,電流大,說明水清,反之水濁
- } //仿真輸出是0~255數字。0(0v)為污濁,清凈為255(5v).
- if(adc_samp < 200)
- adc_rewash = 1;
- else
- {
- adc_rewash = 0;
- }
- }
- //=== 鍵盤掃描 =============================
- void key_serve() //按鍵服務
- { //讀取鍵值后進行相應的操作
- uchar tmp_mod_memory=0, tmp_fen=0, tmp_miao=0;
- diola=0;
- P1 = 0xff; //關閉LED燈,防按鍵干擾
- switch(key_num)
- {
- case 0: { //厚物洗滌
- if(TR0==0 && (fen==0 || fen==10))
- {
- fen = 15;
- miao = 0;
- mod_flag = 1; //工作模式1:厚物
- tmp_mod = 1;
- rewash_times = 0;
- adc_rewash = 1;
- beep_on(1);
- }
- }
- break;
- case 4: { //薄物洗滌
- if(TR0==0 && (fen==0 || fen==15))
- {
- fen = 10;
- miao = 0;
- mod_flag = 2; //工作模式2:薄物
- rewash_times = 0;
- adc_rewash = 1;
- tmp_mod = 2;
- beep_on(1);
- }
- }
- break;
- case 1: { // 開始 鍵
- if(TR0==0) //定時器不工作時,才響應
- {
- mod_flag = tmp_mod; //從臨時變量讀取原工作模式
- TR0 = 1;
- beep_on(1);
- }
- }
- break;
- case 5: { // 暫停 鍵
- if(mod_flag != 5 && TR0==1)
- {
- tmp_mod = mod_flag; //當前工作模式存入臨時變量中
- TR0 = 0;
- mod_flag = 5; //工作模式5:暫停
- beep_on(1);
- }
- }
- break;
- case 9: { //停止 鍵:
- if(TR0 == 1) //定時器在工作時,才響應
- {
- tmp_mod = mod_flag; //當前工作模式存入臨時變量中
- P1 = 0xff;
- TR0 = 0; //關定時器
- fen = 00;
- miao= 00;
- rewash_times = 0; //重置漂洗次數
- adc_rewash = 1; //重置漂洗允許標志位
- mod_flag = 6; //工作模式6:停止
- beep_on(2); //蜂鳴器模式2:停止
- }
- } //然后停止,等待
- break;
- case 2: { // 報警
- if( (mod_flag != 5) && (mod_flag != 6) && TR0==1 )
- {
- tmp_mod = mod_flag; //當前工作模式存入臨時變量中
- P1 = 0xff; //LED防干擾,先關閉
- TR0 = 0;
- mod_flag = 7; //工作模式7:報警
- beep_on(2); //蜂鳴器模式2:停止
- }
- }
- break;
- case 6: { // 機蓋打開(6鍵是 機蓋)
- if( (mod_flag != 5) && (mod_flag != 6) && TR0==1 )
- {
- tmp_mod = mod_flag; //當前工作模式存入臨時變量中
- P1 = 0xff; //LED防干擾,先關閉
- TR0 = 0;
- mod_flag = 5; //工作模式7:報警
- beep_on(2); //蜂鳴器模式2:停止
- }
- }
- break;
- //演示專用:水位模擬鍵的動作
- case 12: {
- P1 = 0x0ff;
- wt_h = 1; //高水位
- wt_m = 0;
- wt_l = 0;
- }
- break;
- case 13: {
- P1 = 0x0ff;
- wt_h = 0;
- wt_m = 1; //中水位
- wt_l = 0;
- }
- break;
- case 14: {
- P1 = 0x0ff;
- wt_h = 0;
- wt_m = 0;
- wt_l = 1; //低水位
- }
- break;
- //演示專用:分鐘速減鍵
- case 3: {
- P1 = 0xff;
- mola=0;
- diola=0; //以上防干擾用
- if(fen != 1)
- fen=1;
- }
- break;
- //演示專用:秒鐘速減鍵
- case 7: {
- P1 = 0xff;
- mola=0;
- diola=0; //以上防干擾用
- if(miao!=1)
- miao=1;
- }
- break;
- //演示專用:從 時間顯示 切換到 AD轉換結果顯示
- case 11: {
- if(adc_display_mod==0) //顯示模式不在AD顯示時,響應
- {
- tmp_fen = fen; //先保存當前計時時間
- tmp_miao = miao;
- adc_display_mod = 1; //模式1為AD結果顯示;
- adc_serve(); //(0為不顯示,后臺運行)
- EA = 0; //關中斷,優化顯示效果(消鬼影)
- TR0 = 0;
- }
- }
- break;
- //演示專用:從 AD轉換結果 切換到 時間顯示
- case 15: { //切換到Time時間顯示
- if(adc_display_mod==1)
- {
- fen = tmp_fen; //讀取暫存的時間數據
- miao = tmp_miao;
- adc_display_mod = 0; //不顯示ADC結果
- EA = 1; //開中斷,回到時間顯示
- TR0 = 1;
- }
- }
- break;
- }
- }
- //=== 鍵盤掃描 ===============================
- void key_scan() //鍵盤掃描:將獲取新的key_num值
- {
- uchar temp, tempp=30;//臨時鍵值
- uchar key_en=1; //鍵盤監視:有按鍵動作時才執行Key_serve,否則僅僅作掃描。不然延時太嚴重,LED會閃爍
-
- P3 = 0x0f; //低4位置1,放入4行。
- temp = P3^0x0f; //異或,把相異的一行變成1,其它全為0
- switch(temp) //判斷是哪行有鍵按下了(0-3行)
- { //就給相應鍵值的行提前量
- case 1: key_num = 0; break;
- case 2: key_num = 1; break;
- case 4: key_num = 2; break;
- case 8: key_num = 3; break;
- default: { //無按鍵
- key_num= 16;
- key_en=0;
- } break;
- }
-
- P3 = 0xf0; //高4位置1,放入4列。
- temp = (P3>>4)^0x0f; //將高位移到低位,用異或找出按下的列
- switch(temp) //判斷列按下,在先前的鍵值中加入列數得鍵值
- {
- case 1: key_num += 0; break;
- case 2: key_num += 4; break;
- case 4: key_num += 8; break;
- case 8: key_num += 12;
- }
- if(key_en==1 && temp!=tempp) //如果有鍵盤操作,才執行按鍵服務
- {
- tempp = key_num;
- key_serve();
- }
- temp = key_num;
- display_mod(); //指示工作模式的LED燈變化
- }
-
- //=== 系統動作控制 =====================
- void action_serve(uchar action_mod) //主電機動作
- {
- P0 = 0xff;
- diola = 0;
- switch(action_mod)
- {
- case 1: { //模式1 - 1分鐘電機間歇正反轉 ==》洗滌
-
- if( ((miao<55)&&(miao>45)) || ((miao<25)&&(miao>15)) )
- {
- mola = 1;
- P1 = 0xfe; //電機正轉
- mola = 0;
- }
- else if( ((miao<40)&&(miao>30))||((miao<10)&&(miao>0)) )
- {
- mola = 1;
- P1 = 0xfd; //電機反轉
- mola = 0;
- }
- else
- {
- mola = 1;
- P1 = 0xff; //電機停車
- mola = 0;
- }
- }
- break;
- case 2: { //模式2 -電機加速 ==》脫水
- mola = 1;
- P1 = 0xea; //speed
- mola = 0;
- if(fen==0 && miao==0) //計時時間到
- action_mod = 7;
- }
- break;
- case 3: { //模式3 -進水
- mola = 1;
- P1 = 0xf7; //開進水閥
- mola = 0;
- }
- break;
- case 4: { //模式4:-排水
- mola = 1;
- P1 = 0xef; //開排水閥
- mola = 0;
- }
- break;
- case 7: { //模式7:空(停機,等待)
- mola = 1;
- P1 = 0xff; //關停全部伺服
- mola = 0;
- }
- break;
- default:{ //其他不可預知的狀態
- mola = 1;
- P1 = 0xff; //關停全部伺服
- mola = 0;
- }
- break;
- }
- }
- //=== 工作模式子程序 ====================================
- void working_mod() //工作模式:讀取模式標志 mod_flag,判斷系統任務
- {
- uchar t; //報警次數設定
- uchar dirty_level; //水的污濁級別
- switch(mod_flag)
- {
- case 1: { //---‘厚物’洗滌--- (按鍵處設定時間了)
- tmp_mod = mod_flag; //當前工作模式存入臨時變量中
- if(wt_h==0 && (fen+2)>=15 && TR0==1)
- action_serve(3); //進水
- if(wt_h==1 && fen!=0) //水位控制
- action_serve(1); //進行厚物洗滌
- if(fen==0 && miao!=0) //結束前1分鐘
- {
- action_serve(4); //排水
- adc_serve(); //在排水時檢測濁度
- delay(1); //ADC needs time
- }
- if((fen==0 && wt_l==1)) //如果時間到最后1min 或 水位低
- {
- beep_on(1);
- miao=0;
- adc_rewash=1; //漂洗標志置1
- TR0 = 0;
- mod_flag = 3; //就進入漂洗程序
- }
- }
- break;
- case 2: { //---‘薄物’洗滌--- (按鍵處設定時間了)
- tmp_mod = mod_flag; //當前工作模式存入臨時變量中
- if(wt_m==0 && (fen+1)>=10 && TR0==1)
- action_serve(3); //進水(1min)
- if(wt_m==1 && fen!=0) //從8min開始
- action_serve(1); //進行薄物洗滌
- if(fen==0 && miao!=0) //提前1分鐘排水
- action_serve(4); //排水
- if((fen==0 && wt_l==1)) //如果時間到 或 水位低
- {
- beep_on(1);
- miao=0;
- adc_rewash=1; //漂洗標志置1
- TR0 = 0;
- mod_flag = 3; //就進入漂洗程序
- }
- }
- break;
- case 3: { //---漂洗---
- tmp_mod = mod_flag; //當前工作模式存入臨時變量中
- adc_serve(); //AD判斷水的污濁程度
- if((rewash_times <= 4) && (adc_rewash==1))
- {
- if(TR0==0) //若定時器還沒開啟,就進入 時間設定 { //4級洗衣水污濁程度判斷后設定rewash時間
- if( adc_samp < 100 ) //若AD檢測結果 小于100:很污濁
- { fen = 10;
- miao = 0;
- dirty_level = 3; //3級污濁
- }
- else if( (adc_samp >= 100) && (adc_samp < 150))
- //AD結果 在 100 到 150 之間:比較污濁
- { fen = 7;
- miao = 0;
- dirty_level = 2; //2級污濁
- }
- else if( (adc_samp >=150) && (adc_samp < 200) )
- //AD結果 在 150 到 200 之間:輕微污濁
- { fen = 5;
- miao = 0;
- dirty_level = 1; //1級污濁
- } //時間設定完成
- rewash_times++; //漂洗次數加1
- TR0 = 1;
- }
- else if(TR0==1 && fen!=0 && wt_l==1)
- {
- action_serve(3); //開進水閥
- } //定時器是開著的,就執行下面
- else if(fen!=0 && miao!=0 && wt_l!=1) action_serve(1); //開電機,漂洗
- else if( fen==0 && miao!=0 && wt_l!=1 ) {
- action_serve(4); //排水
- adc_serve(); //同時進行濁度檢測
- }
- }
- else if( fen==0 && miao!=0 && wt_l==1)
- //在結束漂洗前1min內 and 低水位到
- {
- miao = 0;
- wt_l = 0;
- }
-
- else if((rewash_times > 4) || (adc_rewash==0))
- //若漂洗超過4次 或 由AD結果說明不需要再漂洗了
- {
- adc_rewash = 0; //停止漂洗
- mod_flag = 4; //進入甩干程序
- TR0 = 0; //進入甩干模式前先停定時器
- }
- }
- break;
- case 4: { //---脫水---
- tmp_mod = mod_flag; //當前工作模式存入臨時變量中
- if(adc_rewash==0 && TR0 == 0) //如果滿足甩干初始條件
- { fen=2; //設定甩干時間為2分鐘
- miao=0;
- TR0 = 1; //開始計時
- }
- if(TR0==1)
- action_serve(2); //伺服動作2:甩干
- if(wt_l==1) //若低水位到
- {
- if(fen==1 && miao>10)
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
- </font>
復制代碼
所有資料51hei提供下載:
單片機洗衣機節水控制系統的設計.doc
(1.81 MB, 下載次數: 41)
2018-5-10 06:49 上傳
點擊文件名下載附件
|