![]() 此繼電器由一顆 STC15S204EA芯片為主構(gòu)成,使用3位數(shù)碼管(LD_3361AS)靜態(tài)共陰極顯示,帶動(dòng)松樂(lè)5V繼電器工作。 其中輸入電路使用317P280-1光耦做隔離,輸出使用9012和S8550做繼電器驅(qū)動(dòng)。 整機(jī)功耗在50mA左右,輸入電壓在3.6-5V之間工作??墒褂么赑11,P12寫(xiě)入程序。 STC15S204EA參數(shù):CPU類型:?jiǎn)螘r(shí)鐘8051兼容。內(nèi)置時(shí)鐘:33MHz,可通過(guò)內(nèi)部設(shè)置調(diào)整工作頻率。2-16bitTimer,256BRAM,4KROM,1KEEPROM。內(nèi)置看門狗電路。8路10bitADC.5-ExtInt.不支持IAP,但支持ISP(串口編程)。 硬件原理圖: ![]() 當(dāng)前管腳分配: Pin1(P1.2):外部觸發(fā)輸入信號(hào)(已經(jīng)過(guò)光耦隔離). Pin2_3_4(P1.3,P1.4,P1.5):按鍵檢測(cè)端口,分別連接至功能選擇,數(shù)碼位選擇,數(shù)字調(diào)整等3個(gè)功能。 Pin5_Pin6(P1.6,P1.7):閑置未用。用作監(jiān)控信號(hào)輸出,或該做串口使用。 Pin7(P0.0/P5.4):輸出信號(hào),用作繼電器控制信號(hào)。 Pin8(VDD),Pin10(VSS):電源信號(hào)。 Pin11(P3.0/Rx),Pin12(P3.1/Tx):串口信號(hào)。可通過(guò)設(shè)置端口控制寄存器重新映射到未使用的端口P1.6/P1.7(Pin5/Pin6) Pin9(P0.1/P5.5):數(shù)碼管1陰極。 Pin19(P1.1):數(shù)碼管2陰極。 Pin20(P1.0):數(shù)碼管3陰極。 Pin15(P3.4):數(shù)碼管字段A. Pin17(P3.6):數(shù)碼管字段B. Pin14(P3.3):數(shù)碼管字段C. Pin12(P3.1):數(shù)碼管字段D. Pin11(P3.0):數(shù)碼管字段E. Pin16(P3.5):數(shù)碼管字段F. Pin18(P3.7):數(shù)碼管字段G. Pin13(P3.2):數(shù)碼管字段DP. 在以上硬件連接的基礎(chǔ)上,實(shí)現(xiàn)多步可重定義的開(kāi)關(guān)定時(shí)開(kāi)關(guān)功能。主要簡(jiǎn)述如下: 1. 系統(tǒng)時(shí)鐘頻率選擇 :為了便于和PC通訊,以及和受控設(shè)備通訊,選擇系統(tǒng)主頻M=11.0592MHz。這樣可以使用115200,n,8,1的串口參數(shù)與PC或受控設(shè)備通訊。 2. 定時(shí)中斷的應(yīng)用: Timer0:用作顯示掃描或串口通訊時(shí)的波特率發(fā)生器。用作顯示掃描時(shí),在11.0592MHz主頻下,掃描頻率設(shè)置到33Hz ,可消除人眼可見(jiàn)的閃爍。 Timer1: 用于定時(shí)(1ms準(zhǔn)確定時(shí)),按鍵信號(hào)檢測(cè),輸入觸發(fā)信號(hào)檢測(cè)等。在11.0592MHz主頻下,掃描頻率設(shè)置到4KHz,可以保證短時(shí)延時(shí)的準(zhǔn)確性,輸入觸發(fā)信號(hào)的最高可分辨頻率可達(dá)到100Hz。 3. EEPROM的應(yīng)用 STC15F204EA的1K EEPROM按照512字節(jié)大小分為2個(gè)Bank。Bank0用來(lái)記錄系統(tǒng)配置數(shù)據(jù)(程序初始化時(shí)寫(xiě)入,包括不同主頻下的中斷配置信息等),Bank1用來(lái)記錄用戶所需要的通斷序列,每個(gè)動(dòng)作序列由順序號(hào),繼電器閉合時(shí)間,繼電器斷開(kāi)時(shí)間,本動(dòng)作重復(fù)次數(shù)等4個(gè)整數(shù)組成,共占8個(gè)字節(jié)。在512個(gè)字節(jié)內(nèi),可以存放最多63組動(dòng)作(最后一個(gè)動(dòng)作序列全0,表示動(dòng)作結(jié)束)。 系統(tǒng)上電后,程序完成初始化動(dòng)作,然后逐步從EEPROM中讀出一個(gè)動(dòng)作序列執(zhí)行。用戶可以控制在整個(gè)動(dòng)作執(zhí)行多少次以后,繼電器停止動(dòng)作,完全處于待機(jī)狀態(tài)。也可以無(wú)限重復(fù)循環(huán)執(zhí)行。動(dòng)作時(shí)間以0.1s為時(shí)間基準(zhǔn),每個(gè)動(dòng)作的時(shí)間長(zhǎng)度可由0-6553.5s之間變化。 4. 用戶數(shù)據(jù)的寫(xiě)入 在系統(tǒng)啟動(dòng)后,用戶通過(guò)按鍵,進(jìn)入與PC聯(lián)機(jī)模式,然后用PC端給繼電器寫(xiě)入要執(zhí)行的動(dòng)作序列。寫(xiě)入完成后,即可開(kāi)始執(zhí)行。 5. 與PC的實(shí)時(shí)通訊 因Timer0正常應(yīng)用為L(zhǎng)ED顯示控制,如果用戶選擇使用PC聯(lián)機(jī)通訊,則把Timer0設(shè)置為波特率發(fā)生器(LED關(guān)閉),用戶可以通過(guò)串口,直接將執(zhí)行狀態(tài)顯示在PC上,隨時(shí)執(zhí)行停止或啟動(dòng),或執(zhí)行更長(zhǎng),更復(fù)雜的命令序列,并記錄執(zhí)行結(jié)果。因?yàn)镾TC15F204EA中僅一個(gè)UART通道,無(wú)法同時(shí)執(zhí)行與被控設(shè)備通信和PC通訊,只能選擇。 6. 關(guān)于外部觸發(fā)的控制信號(hào) 因?yàn)樵摾^電器使用了雙向光耦作為輸入與單片機(jī)引腳的隔離,而輸入信號(hào)是直接與光耦的輸入端相連,因此需要保證輸入信號(hào)(需要讓光耦中的LED工作,電流2-5mA)足夠驅(qū)動(dòng)光耦工作,否則結(jié)果不可靠。 7. 關(guān)于松樂(lè)5V繼電器。 使用這個(gè)繼電器的好處是使用單一5V電源就可工作,但是會(huì)對(duì)系統(tǒng)的電源穩(wěn)定性造成影響。在繼電器閉合器件,在電源上形成一個(gè)約2.5us的電源紋波(PP:3.8 - 6.3V)。如果在單片機(jī)設(shè)置上設(shè)置為4.05V自動(dòng)復(fù)位,有可能導(dǎo)致系統(tǒng)自動(dòng)復(fù)位。 8. 關(guān)于使用I/O管腳直接驅(qū)動(dòng)LED顯示 使用I/O驅(qū)動(dòng)LED的好處是外圍電路最為簡(jiǎn)單,但是增加了系統(tǒng)的電流負(fù)載。對(duì)于這種 共陰極LED數(shù)碼管,需要輸出較大的工作電流才能達(dá)到正常的顯示亮度。因此使用了STC單片機(jī)的I/O模式控制寄存器PxM0,PxM1將輸出模式設(shè)置為推挽輸出方式。此時(shí)每個(gè)I/O管腳可提供20mA以上電流,但是在LED上需要串接一個(gè)330-470ohm的限流電阻,防止LED燒毀。 9. 定時(shí)的準(zhǔn)確程度 該單片機(jī)使用內(nèi)部RC振蕩器工作,頻率范圍在5-33MHz(產(chǎn)品手冊(cè)是35MHz,但不知如何設(shè)置到35MHz)內(nèi)調(diào)節(jié),精度1%以內(nèi)。但是當(dāng)I/O口工作與推挽模式,并且有電流輸出時(shí),I/O口的速度會(huì)降低很多,使得循環(huán)的定時(shí)精度極大變化,不能用作通用定時(shí)使用(工作頻率越高,這個(gè)現(xiàn)象越明顯)。 該單片機(jī)與51系列兼容性高,因此可以使用Proteus做完全仿真,比起每次把程序?qū)戇M(jìn)單片機(jī)看運(yùn)行效果要方便很多。對(duì)于問(wèn)題的Debug,大部分情況下,可以直接使用Keil C51下的模擬器進(jìn)行,使用便捷有效。對(duì)于類似的小型應(yīng)用系統(tǒng),是一個(gè)很好的選擇。 單片機(jī)控制的定時(shí)計(jì)數(shù)繼電器 - 軟件部分 這個(gè) 軟件部分按照開(kāi)發(fā)過(guò)程的順序,分為顯示部分、定時(shí)部分和外部觸發(fā)信號(hào)的檢測(cè)部分。 1. 顯示驅(qū)動(dòng): 這個(gè)電路中使用的3位共陰極7段式LED(LD-3361AS)共11個(gè)管腳,經(jīng)過(guò)網(wǎng)上搜索,查找了其基本電路連接關(guān)系。為了便于在Proteus中進(jìn)行仿真,因此就利用Proteus元件庫(kù)中帶點(diǎn)的1位數(shù)碼管3只,外加一個(gè)接口,自己構(gòu)成了這個(gè)顯示元件。這樣就方便使用Proteus直接仿真運(yùn)行。 ![]() ![]() 下一步是顯示字模的組成。因?yàn)樗淖侄蝍-g與單片機(jī)P3口的連接順序并不是按照P3.0-P3.7這樣的順序一一對(duì)應(yīng),因此,需要按照連接的順序,建立在P3口上顯示每個(gè)字符時(shí)的字模表。 ![]() 上圖是一般7段數(shù)碼管的筆畫(huà)定義,如果要顯示字符0,則需要a,b,c,d,e,f都要點(diǎn)亮,標(biāo)記為1. 如果顯示字符1,則需要b、c點(diǎn)亮即可。其它可顯示的字符也是按照這個(gè)方法定義。因此,在這個(gè)實(shí)際電路中,字符的定義如下: LED顯示控制端口連接及字符字形定義: /* 顯示字符字模定義表 端口P3: 7 6 5 4 3 2 1 0 7SEG: G B F A C DP D E 字符 字碼定義 0: 0 1 1 1 1 0 1 1 7B 1: 0 1 0 0 1 0 0 0 48 2: 1 1 0 1 0 0 1 1 D3 3: 1 1 0 1 1 0 1 0 DA 4: 1 1 1 0 1 0 0 0 E8 5: 1 0 1 1 1 0 1 0 BA 6: 1 0 1 1 1 0 1 1 BB 7: 0 1 0 1 1 0 0 0 58 8: 1 1 1 1 1 0 1 1 FB 9: 1 1 1 1 1 0 0 0 F8 a: 1 1 1 1 1 0 0 1 F9 b: 1 0 1 0 1 0 1 1 AB c: 1 0 0 0 0 0 1 1 83 d: 1 1 0 0 1 0 1 1 CB e: 1 0 1 1 0 0 1 1 B3 f: 1 0 1 1 0 0 0 1 B1 g: 1 1 1 1 1 0 1 0 FA H: 1 0 1 0 1 0 0 1 A9 I: 0 0 1 0 0 0 0 1 21 J: 0 1 0 0 1 0 1 0 4A K: 0 0 0 0 0 0 0 0 00 L: 0 0 1 0 0 0 1 1 23 M: 0 0 0 0 0 0 0 0 00 N: 0 0 0 0 0 0 0 0 00 o: 1 0 0 0 1 0 1 1 8B P: 1 1 1 1 0 0 0 1 F1 Q: 0 0 0 0 0 0 0 0 00 r: 1 0 0 0 0 0 0 1 81 S: 1 0 1 1 1 0 1 0 BA //和5相同 t: 1 0 1 0 0 0 1 1 A3 u: 0 0 0 0 1 0 1 1 0B v: 0 0 0 0 0 0 0 0 00 W: 0 0 0 0 0 0 0 0 00 X: 0 0 0 0 0 0 0 0 00 y: 1 0 1 0 1 0 1 0 AA Z: 0 0 0 0 0 0 0 0 00 -: 1 0 0 0 0 0 0 0 80 _: 0 0 0 0 0 0 1 0 02 [: 0 0 1 1 0 0 1 1 33 ]:0 1 0 1 1 0 1 0 5A ~: 0 0 0 1 0 1 0 0 14 //表示錯(cuò)誤字符。 字符表結(jié)束*/ 轉(zhuǎn)換成 C語(yǔ)言的標(biāo)準(zhǔn)定義如下: static unsigned char code CharCode[] = {0x7B, 0x48, 0xD3, 0xDA, 0xE8, 0xBA, 0xBB, 0x58, // 0 - 7 0xFB, 0xF8, 0xF9, 0xAB, 0x83, 0xCB, 0xB3, 0xB1, // 8 - f 0xFA, 0xA9, 0x21, 0x4A, 0x00, 0x23, 0x00, 0x00, // g - N 0x8B, 0xF1, 0x00, 0x81, 0xBA, 0xA3, 0x0B, 0x00, // o - v 0x00, 0x00, 0xAA, 0x00, 0x80, 0x02, 0x33, 0x5A, // w - z,-, _, [, ], 0x14}; //~. 不過(guò),在上表中,有不少是用0x00表示的,表明這個(gè)字符用數(shù)碼管無(wú)法顯示,因此全部滅掉,變成空白了。如果你要顯示"W,M,N,K,V,X,Z ,....都無(wú)法顯示的。因此在使用時(shí),盡量避免用到以上的顯示內(nèi)容。但是常用的如:”Start“,"Hlt","Stop" "End" ”0-9“,”A-F“等都可以正常顯示。 在字模表定義好以后,就要顯示兩類信息,一類是字符串,另一類是整數(shù)數(shù)字。我們通常使用的字符串是用ASCII(American Standard Code for Information Interchange, 美國(guó)標(biāo)準(zhǔn)信息交換碼)碼表示的,并不是我們這里的字模。因此需要把常用的ASCII字符串,轉(zhuǎn)換成所需要顯示對(duì)應(yīng)的字模數(shù)據(jù),然后把字模數(shù)據(jù)再放到對(duì)應(yīng)的P3端口上,就可以在數(shù)碼管上顯示出來(lái)了。 下面是ASCII字符到字模表的轉(zhuǎn)換過(guò)程。 1. 首先定義了一個(gè)顯示緩沖區(qū),就是PC里面的顯存。把要顯示的內(nèi)容放到顯存中,然后由顯示程序自動(dòng)顯示出來(lái)就好了。因?yàn)檫@個(gè)數(shù)碼管只有3位,無(wú)法顯示很多內(nèi)容,因此這里的顯存僅定義為10個(gè)字節(jié)。其中8個(gè)字節(jié)可以用來(lái)顯示內(nèi)容,另外2個(gè)字節(jié)用作循環(huán)時(shí)的間隔符使用。在這個(gè)基礎(chǔ)上,最多顯示的字符長(zhǎng)度是8位ASCII碼,對(duì)應(yīng)于數(shù)字,則最大是99999999。超過(guò)這個(gè)范圍的顯示內(nèi)容,會(huì)被處理掉而不予處理。 #define BUFLEN 10 //顯示緩沖區(qū), 顯示起始指針和終止指針,要顯示的數(shù)據(jù)的長(zhǎng)度(1-8)。 unsigned char DispBuf[BUFLEN]; //數(shù)據(jù)長(zhǎng)度8位,加2位隔離空格 unsigned char DISPLEN; //要顯示的數(shù)據(jù)的長(zhǎng)度,1-8. 2. 將單個(gè) ASCII字符轉(zhuǎn)換為L(zhǎng)ED對(duì)應(yīng)的字模代碼。其中CharCode[]就是前面定義的字模表。 unsigned char CChar(char c) { unsigned char i; if (c >= '0' && c <= '9') i=c-'0'; else if (c >='A' && c<='Z') i=c-'A'+10; else if (c >='a' && c<='z') i=c-'a'+10; else if (c == '-') i=36; else if (c == ' ') i=35; //空格 else if (c == '_') i=37; else if (c == '[') i=38; else if (c == ']') i=39; else i=40; //其它字符全部轉(zhuǎn)換為小數(shù)點(diǎn) return CharCode[i]; } 這個(gè)轉(zhuǎn)換過(guò)程比較簡(jiǎn)單,就是將ASCII字符與0-9,A-Z, a-z分別比較,然后找到位置值,轉(zhuǎn)換到字模表中的順序值,最后返回字模表該位置對(duì)應(yīng)的字模值即可。因此無(wú)法區(qū)分大小寫(xiě),識(shí)別主要靠想象力了。 3. 顯示字符串的程序是顯示的一個(gè)核心部分。因?yàn)橹荒茱@示3位,因此當(dāng)要顯示的長(zhǎng)度不超過(guò)3位時(shí),靠右顯示。前面顯示為空白(不顯示)。而對(duì)于超過(guò)3位長(zhǎng)度的部分,則是按順序存放在顯存中,由顯示程序自動(dòng)顯示(顯示程序后面介紹)。 void Disp(char *str) { unsigned char i; DISPLEN =sLen(str); if (DISPLEN==1) { //長(zhǎng)度為1,前面2個(gè)空白,最后一個(gè)數(shù)值。 DispBuf[2]=CChar(str[0]); DispBuf[1]=0; DispBuf[0]=0; DISPLEN=3; } else if (DISPLEN ==2) { //長(zhǎng)度為2,前面1個(gè)空白,后面兩個(gè)數(shù)值。 DispBuf[1]=CChar(str[0]); DispBuf[2]=CChar(str[1]); DispBuf[0]=0; DISPLEN=3; } else for (i=0;i<DISPLEN;i++){ DispBuf[i]=CChar(str[i]); //按順序放進(jìn)顯存。 } //顯示區(qū)的最大長(zhǎng)度是8,最后增加2個(gè)0,作為空格,隔離循環(huán)顯示。 for (i=DISPLEN;i<10;i++) DispBuf[i]=0; //如果dCount =0, 則立即開(kāi)始刷新(Timer0的下次中斷開(kāi)始就刷新)。 //否則等這次正常顯示完成才刷新??赡軙?huì)丟失部分顯示內(nèi)容,但是看著正常。 dCount=0; } 上面用到了一個(gè)字符串長(zhǎng)度函數(shù)sLen。因?yàn)椴幌胧褂肅標(biāo)準(zhǔn)庫(kù),因此自己定義這個(gè)函數(shù),并且限定最大長(zhǎng)度是8。 unsigned char sLen(char *str) { unsigned char i=0; while(*str != 0) {i++;str++;} if (i>8) i=8; //獲取字符串長(zhǎng)度,不大于8。大于8時(shí)等于8. return i; } 4. 對(duì)于長(zhǎng)整數(shù)的顯示。范圍 0 - 9999,9999。雖然程序內(nèi)部能夠處理無(wú)符號(hào)長(zhǎng)整數(shù)(0-2(32)范圍),但是顯示時(shí)只處理這個(gè)較小的范圍。 /*-------------------------------------------------------------------------------------------- 無(wú)符號(hào)長(zhǎng)整數(shù)顯示程序 限制:只能顯示8位,否則顯示 OFL - 表示 Overflow,溢出。 ----------------------------------------------------------------------------------------------*/ void DispLInt(unsigned long m) { unsigned long i; unsigned char j,k; unsigned char Res[8]; //對(duì)于超大數(shù)據(jù)的處理,顯示“---”,閃爍。"OFL" if (m>99999999) { DispBuf[0]=0x8B; // O DispBuf[1]=0xB1; // F DispBuf[2]=0x23; // L DISPLEN = 3; return; } //將整數(shù)轉(zhuǎn)換成十進(jìn)制字符數(shù)組Res[], 如873245轉(zhuǎn)換成{'8','7','3','2','4','5'}。 i=m/10; j=m%10; k=0; Res[k]=j; while(i>0) { j=i%10; i=i/10; k++; Res[k]=j; } //對(duì)于僅1位數(shù)字的顯示,前面填充2個(gè)空格,最后一位顯示數(shù)字。 if (m<10) { DispBuf[0]=0; DispBuf[1]=0; DispBuf[2]=CharCode[Res[0]]; DISPLEN=3; } //對(duì)于2為數(shù)字顯示,前面填1個(gè)空格,后面兩位填數(shù)字。 if (m >=10 && m<100) { DispBuf[0]=0; DispBuf[1]=CharCode[Res[1]]; DispBuf[2]=CharCode[Res[0]]; DISPLEN=3; } //對(duì)于3位及以上的數(shù)字處理。按照順序填充在顯存中。 if (m>=100) { for (j=k;j>0;j--) DispBuf[k-j]=CharCode[Res[j]]; //uchar i-- 會(huì)導(dǎo)致死循環(huán),無(wú)法停下來(lái)的。 DispBuf[k]=CharCode[Res[0]]; DISPLEN=k+1; } if (k<3) k=3; //對(duì)于長(zhǎng)度超過(guò)3位的數(shù)字,需要循環(huán)顯示,并且在需要循環(huán)顯示的緩沖區(qū)中增加兩個(gè)空格(0)。 DispBuf[k+1]=0; DispBuf[k+2]=0; //是否需要立即刷新?影響顯示的美觀程度。 dCount = 0; } 至此,要顯示的內(nèi)容存放到顯示緩沖區(qū)的工作已經(jīng)完成。剩下就是如何把顯示緩沖區(qū)的內(nèi)容放到P3端口上,讓LED數(shù)碼管點(diǎn)亮了。這里為了讓程序獨(dú)立的工作,使用了Timer0服務(wù)中斷作為定時(shí)掃描顯示使用。 5. LED的掃描頻率設(shè)定。因?yàn)槭褂肐/O口直接驅(qū)動(dòng)LED的管腳進(jìn)行顯示,因此任何時(shí)候,都只可能在3個(gè)數(shù)碼管中,僅有一個(gè)是點(diǎn)亮的。但是因?yàn)槿搜鄣囊曈X(jué)暫留現(xiàn)象,我們看到多次循環(huán)掃描點(diǎn)亮后的數(shù)碼管是一直亮著的。根據(jù)電影和電視的顯示頻率來(lái)看,一般每個(gè)數(shù)碼管最少掃描頻率在24次/秒以上時(shí),才能感覺(jué)到一直亮著。掃描頻率再低時(shí),就會(huì)感覺(jué)到數(shù)字在閃爍。 另外,因?yàn)槲覀円@示的字符最多是8位,因此每3個(gè)字符顯示一段時(shí)間后,必須移動(dòng)一下,流水形式顯示下一位,這個(gè)流水的速度不能太快,太快了一樣會(huì)感到字符閃爍。因此,根據(jù)感受,這個(gè)移動(dòng)的頻率在1.5-2次/秒左右。這就是下面確定掃描程序的頻率的依據(jù)。 為了精確確定掃描的周期,使用系統(tǒng)定時(shí)器Timer0作為基準(zhǔn)。 另外,因考慮到后期還會(huì)使用Timer0復(fù)用做UART通訊時(shí)的波特率發(fā)生器,因此選擇系統(tǒng)的主時(shí)鐘在11.0592MHz或大于它的0.5倍的整倍數(shù)。這樣可以較為精準(zhǔn)的產(chǎn)生115200Baud的通訊速率。這里選擇基準(zhǔn)時(shí)鐘為11.0592MHz(因STC15F204EA使用內(nèi)部RC振蕩器工作,會(huì)有0.2%以內(nèi)的實(shí)際誤差)。 Timer0的初始化如下: /*------------------------------------------------ 定時(shí)器中斷程序/用于顯示 ------------------------------------------------*/ void Init_Timer0(void) { TMOD |= 0x01; //定時(shí)模式1,16位定時(shí)方式 TH0=0xEE; //定時(shí)器初值: 11.0592MHz晶振, 中斷周期5ms TL0=0x04; PT0=1; //Timer0中斷優(yōu)先 EA=1; //總中斷打開(kāi) ET0=1; //定時(shí)中斷打開(kāi) TR0=1; //定時(shí)開(kāi)始 cp=0; dispPtr =0; //顯示位置指針清零 TIMER0INIT=1; //TIMER0初始化標(biāo)志,其它地方用到。 } /*------------------------------------------------------------------------- 顯示服務(wù)中斷:TIMER0_ISR 說(shuō)明: LED的刷新頻率在30Hz以上時(shí),沒(méi)有閃爍感。 此時(shí)中斷的刷屏頻率要大于90Hz。 在時(shí)鐘M=11.0592MHz時(shí),TH0=0xEC,TL0=0x04即可。 --------------------------------------------------------------------------*/ void Timer0_isr(void) interrupt 1 { unsigned char t; unsigned char i; TH0=0xEE; //0xFD,0x57 :32.954MHz --->2.00527KHz TL0=0x04; //0xFA,0xB0 :32.954MHz --->1.00686KHz cp++; //cp為刷新周期計(jì)數(shù),每中斷幾次,刷新一次。如果系統(tǒng)主頻很高,此時(shí)的刷新頻率數(shù)值可以調(diào)整到更大。
if (cp == LED_REFRESH_FREQ) { //5ms * 4 = 20ms LED_REFRESH_FREQ 拖過(guò)調(diào)整顯示延遲常數(shù), cp =0; dispPtr++; //顯示指針指向下一個(gè)要顯示的字段 if (dispPtr ==1) { //顯示第一位,先關(guān)閉上一個(gè)顯示位,更新要顯示的數(shù)值,然后打開(kāi)要顯示的字段。實(shí)際顯示時(shí)間等于2次中斷的間隔。 DIG_3=LED_OFF; P3=DispBuf[dispPtr-1]; DIG_1=LED_ON; } if (dispPtr ==2) {//顯示第二位,做法同上。 DIG_1=LED_OFF; P3=DispBuf[dispPtr-1]; DIG_2=LED_ON; } if (dispPtr ==3) {//顯示第三位,完成后把顯示指針dispPtr變成0,表示一次顯示完成。 DIG_2=LED_OFF; P3=DispBuf[dispPtr-1]; DIG_3=LED_ON; dispPtr=0; } dCount++; //是否要做流水移動(dòng)的計(jì)數(shù)器。這里每刷新50次,移動(dòng)一次。移動(dòng)頻率=(單字刷新頻率*3)/50,約1.8-2.0Hz if (dCount>50 && DISPLEN>3) { //循環(huán)次數(shù),每個(gè)位置顯示相同次數(shù)后,開(kāi)始更新下一輪字符。字符移位開(kāi)始。 //在兩次循環(huán)中間插入段行識(shí)別2個(gè)空格或上劃線? 否則首尾相連無(wú)法識(shí)別。 dCount=0; //流水移動(dòng)計(jì)數(shù)器清零 t=DispBuf[0]; //保存顯存中的第一位 for (i=0; i<DISPLEN+1;i++) DispBuf[i]=DispBuf[i+1]; //循環(huán)引動(dòng)第2位到DISPLEN+1位,向前移動(dòng)一位 DispBuf[i]=t; //將第一位補(bǔ)在循環(huán)隊(duì)列的尾部 } } } 經(jīng)過(guò)以上動(dòng)作,數(shù)據(jù)就可以正常在LED上顯示了。 6. Timer0參數(shù)設(shè)置,主頻與中斷頻率的測(cè)量值。 對(duì)于STC15F204EA的Timer0, 其它主頻下可參照調(diào)整。具體的測(cè)試數(shù)據(jù)如下(使用P1.7端口電平翻轉(zhuǎn)進(jìn)行測(cè)量的實(shí)際頻率,非計(jì)算值): 當(dāng)TH0=0xEE, TL=0x11時(shí),主頻變化與P1.7的端口翻轉(zhuǎn)頻率的關(guān)系如下: 32.958MHz 輸出:298.82Hz 5.995MHz 輸出:54.375Hz 12.011MHz 輸出:108.955Hz 19.966MHz 輸出:181.082Hz 23.980MHz 輸出:217.476Hz 29.988MHz 輸出:271.944Hz 當(dāng)系統(tǒng)的主頻固定設(shè)置到33MHz(實(shí)際值32.950MHz)時(shí),定時(shí)參數(shù)設(shè)置對(duì)輸出頻率的變化: TH0=0xFF, TL0=0x01 :5.307KHz TH0=0xEF TL0=0xA0 :327.236 TH0=0xF6 TL0=0xA0 :571.172 TH0=0xF6 TL0=0x00 :535.521 TH0=0xF5 TL0=0x00 :486.952 TH0=0xF5 TL0=0x40 :498.271 TH0=0xF5 TL0=0x48 :499.761 TH0=0xF5 TL0=0x4A :500.080 TH0=0xCA TL0=0x62 :100.006 TH0=0xE5 TL0=0x33 :200.000 TH0=0xEA TL0=0x90 :250.040 TH0=0xEE TL0=0x23 :300.040 TH0=0xF2 TL0=0x9C :400.043 在主頻固定設(shè)置在M=11.0592MHz, 并且同步打開(kāi)Timer1 ON(4KHz速率中斷,輕負(fù)載)時(shí),TH0,TL0與輸出頻率的關(guān)系如下: TH0, TL0, 翻轉(zhuǎn)頻率 0xF2, 0x9C, 134.267Hz 0xEE, 0x04, 100.003Hz LED_REFRESH_FREQ=2時(shí),LED閃爍,LED_REFRESH_FREQ=1, 則不再閃爍。 0xE2, 0x08, 60.016, LED_REFRESH_FREQ=1,輕微閃爍。 0xE8, 0x03, 75.000, LED_REFRESH_FREQ=1. 0xEC, 0x04, 89.904, LED_REFRESH_FREQ=1, 此時(shí)單個(gè)字的刷新周期為29.994Hz(實(shí)際測(cè)試值)。 這些測(cè)量數(shù)據(jù)和計(jì)算值之間有一定的差距。特別是當(dāng)顯示的負(fù)載增大時(shí),點(diǎn)亮LED和不點(diǎn)亮LED的中斷速率是不一樣的。實(shí)際使用時(shí),如果需要準(zhǔn)確的數(shù)據(jù),最好用示波器測(cè)量實(shí)際值為準(zhǔn)。 7. LED的顯示亮度問(wèn)題。 對(duì)于普通的51單片機(jī),無(wú)法直接驅(qū)動(dòng)共陰極LED數(shù)碼管直接顯示。因此需要將端口設(shè)置為推挽輸出模式。 //關(guān)閉所有顯示。 LED_Init(); //STC單片機(jī)特殊寄存器 PxM0,PxM1設(shè)置工作狀態(tài)。 M1M0=01 推挽式輸出,可以直接點(diǎn)亮LED。但是需要增加470ohm分壓電阻限流。 P3M0=0xFF; P3M1=0x0; (因QQ文字編輯器異常,無(wú)法編寫(xiě)下去了。這一節(jié)就此結(jié)束。) |
|
來(lái)自: 快樂(lè)讀書(shū)法 > 《51單片機(jī)》