軟中斷在51單片機(jī)中的實(shí)現(xiàn)及其應(yīng)用_第1頁
軟中斷在51單片機(jī)中的實(shí)現(xiàn)及其應(yīng)用_第2頁
軟中斷在51單片機(jī)中的實(shí)現(xiàn)及其應(yīng)用_第3頁
軟中斷在51單片機(jī)中的實(shí)現(xiàn)及其應(yīng)用_第4頁
軟中斷在51單片機(jī)中的實(shí)現(xiàn)及其應(yīng)用_第5頁
免費(fèi)預(yù)覽已結(jié)束,剩余13頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、軟中斷在51單片機(jī)中的實(shí)現(xiàn)及其應(yīng)用彭樹林摘要本文討論軟中斷在51單片機(jī)(兼容)中的實(shí)現(xiàn)方法以及軟中斷在51單片機(jī)(兼容)系統(tǒng)中的應(yīng)用。詳細(xì)說明了在51單片機(jī)實(shí)現(xiàn)軟中斷的方法,并就軟中斷的應(yīng)用作了簡明扼要的闡述。關(guān)鍵詞軟中斷單片機(jī)51單片機(jī)實(shí)時(shí)操作系統(tǒng)1、序言現(xiàn)代的單片機(jī)應(yīng)用中,某些單片機(jī)為了方便操作系統(tǒng)編程,會保留一些特權(quán)指令給RTOSM乍系統(tǒng),以便實(shí)時(shí)控制整個(gè)機(jī)器;軟件中的一些原子操作不允許中斷破壞,也需要一些特權(quán)指令。軟中斷指令表面上類似于函數(shù)調(diào)用,主要是使單片機(jī)進(jìn)入特權(quán)運(yùn)行狀態(tài),并在這個(gè)狀態(tài)下,操作一些用戶狀態(tài)下不能使用的功能。51兼容單片機(jī)沒有特權(quán)功能,也不存在軟中斷指令。但是我們的一

2、些應(yīng)用確實(shí)需要軟中斷特權(quán)指令來完成一些特殊的操作。本文所討論軟中斷在51兼容單片機(jī)中的實(shí)現(xiàn)方法以及軟中斷在51兼容單片機(jī)系統(tǒng)中的應(yīng)用。2、軟中斷與硬中斷軟中斷,最早出現(xiàn)在Intel8086處理器中,該處理器的指令系統(tǒng)中,可使用INT指令來申請中斷服務(wù)。在DOSM乍系統(tǒng)下,利用INT21這條指令,應(yīng)用軟件可以申請多達(dá)84個(gè)DOS(統(tǒng)服務(wù)。在Linux、WindowsSOLAIRS等操作系統(tǒng)中,都有軟中斷在為系統(tǒng)提供服務(wù)。軟中斷和硬中斷區(qū)別不大,軟中斷是程序中用軟件代碼人為地產(chǎn)生中斷,讓CPUS執(zhí)行相應(yīng)的中斷服務(wù)程序。硬中斷由硬件產(chǎn)生并觸發(fā)中斷,讓CPlfe執(zhí)行相應(yīng)的中斷服務(wù)程序以響應(yīng)該事件??梢?/p>

3、這樣理解,軟中斷以軟件中斷指令所攜帶的參數(shù)作為工作的依據(jù),而硬中斷是以計(jì)算機(jī)系統(tǒng)中硬件所發(fā)生的事件為工作依據(jù)??梢娷浖袛嗟撵`活性非常強(qiáng),可根據(jù)程序的運(yùn)行狀態(tài)、硬件狀態(tài)以及任務(wù)之間的消息作為觸發(fā)條件,中請相應(yīng)的軟中斷功能服務(wù)。軟中斷最大的用途在于RTOSS供系統(tǒng)級服務(wù),提高系統(tǒng)的實(shí)時(shí)性。在沒有RTOS勺情況下,我們也可利用軟中斷服務(wù)對敏感代碼和敏感數(shù)據(jù)進(jìn)行保護(hù)。比如互斥訪問共享硬件以及互斥訪問共享數(shù)據(jù)等。3、51單片機(jī)(兼容)中斷系統(tǒng)的秘密51單片機(jī)(兼容)的中斷系統(tǒng)中,各個(gè)中斷標(biāo)志的置位條件和如何清除,者B在公開的技術(shù)資料中進(jìn)行了詳細(xì)的描述。然而,公開的技術(shù)細(xì)節(jié)實(shí)際上并沒有將中斷系統(tǒng)的工作原

4、理講述清楚。大家使用的51兼容單片機(jī),其中斷系統(tǒng)的工作細(xì)節(jié)以及工作的結(jié)果與公開的技術(shù)資料有些小小的差異。比如關(guān)于外部中斷標(biāo)志IE0的置位,附1是五個(gè)公司對IE0的描述。各個(gè)公司開發(fā)的51單片機(jī)(兼容),其中斷系統(tǒng)也兼容,僅僅是中斷源的多少,中斷優(yōu)先級的級數(shù)以及中斷向量的多少的不同,附2列舉了六家公司51單片機(jī)(兼容)的中斷系統(tǒng)資料。中斷系統(tǒng)的秘密在于:中斷標(biāo)志完全可以通過一定的方式實(shí)現(xiàn)軟件置位和軟件清除??煞裢ㄟ^軟件置位和清除中斷標(biāo)志,是在51單片機(jī)中實(shí)現(xiàn)軟中斷的關(guān)鍵,如果不能用軟件申請中斷,軟中斷的實(shí)現(xiàn)就無從談起。硬件置位中斷申請標(biāo)志只是方法之一而不是唯一的方法,CPUI全可以設(shè)置這些標(biāo)志位

5、為“0”或者“1”。這是理解本文的基礎(chǔ),對于有豐富經(jīng)驗(yàn)的51單片機(jī)開發(fā)者,只要知道這個(gè)道理就好,基本沒有必要再閱讀后面的部分。本文接下來的部分具體描述如何在51單片機(jī)中實(shí)現(xiàn)軟中斷,主要針對51單片機(jī)開發(fā)經(jīng)驗(yàn)還不是十分豐富的讀者。IE0和IE1的秘密在于,如果將中斷檢測的方式(IT0、IT1)設(shè)置為邊沿檢測,就可以用軟件來設(shè)置或清除IE0和IE1(消除也可以讓中斷系統(tǒng)在響應(yīng)中斷時(shí)自動(dòng)完成)。TFRTF1、TF2TI以及RI是已知的可以軟件操控的中斷申請標(biāo)志。對于各個(gè)公司的51單片機(jī)(兼容)增強(qiáng)部分的中斷,可以根據(jù)實(shí)際應(yīng)用,在關(guān)閉模塊功能的情況下一般都可以自由使用其中斷資源。具體應(yīng)用時(shí),應(yīng)編寫一個(gè)

6、測試軟件,測試具體型號的51單片機(jī)各個(gè)中斷資源是否能夠被利用,避免走彎路。讀者應(yīng)當(dāng)注意到,有些單片機(jī)的某些中斷申請標(biāo)志,其清除方法是通過對該標(biāo)志位寫“1”來完成的,這種中斷源就不適合用于軟中斷,比如STC12C5AxxS2單片機(jī)的SPI中斷。如果要使用STC12C5AxxS單片機(jī)的SPI中斷作為軟中斷,就必須放棄該模塊占用的IO弓唧,以實(shí)現(xiàn)軟中斷。例如在40腳DIP封裝的STC12C5AxxS單片機(jī)中,將SPI影射到P4口不會占用外部的引腳,將SPI設(shè)置為MASTE模式,就可以通過對SPDATW入0xFF數(shù)據(jù)來是SPI工作,SPI工作完成后會自動(dòng)設(shè)置中斷申請標(biāo)志,從而完成軟中斷的申請。而在44

7、或48腳封裝的STC12C5AxxS單片機(jī),用SPI中斷源實(shí)現(xiàn)軟中斷就必須考慮放棄SPI占用的引腳(P1口或P4口)。大部分51單片機(jī)(兼容)增強(qiáng)部分,在系統(tǒng)的應(yīng)用中不能全部同時(shí)使用,因?yàn)樗鼈兛赡芄蚕砹薎O端口上的引腳。因此,總是能在一個(gè)51單片機(jī)中找到空閑資源實(shí)現(xiàn)軟中斷。4、軟中斷實(shí)現(xiàn)的方法只要是代碼兼容的51單片機(jī),就可以利用空閑不用的中斷來實(shí)現(xiàn)軟中斷。對于沒有空閑中斷的應(yīng)用系統(tǒng),也可以通過本文描述的方法來實(shí)現(xiàn)共享硬件中斷和軟中斷。在51單片機(jī)應(yīng)用系統(tǒng)中,實(shí)現(xiàn)軟中斷的基本原理是用軟件置位硬件中斷的中請標(biāo)志位,迫使系統(tǒng)承認(rèn)一個(gè)“硬件中斷”發(fā)生進(jìn)而去響應(yīng)這個(gè)“硬件中斷事件”這樣,就實(shí)現(xiàn)了用軟件

8、申請實(shí)現(xiàn)中斷服務(wù)。具體在一個(gè)應(yīng)用系統(tǒng)中實(shí)現(xiàn)時(shí),可能還需要作如下的安排:1)將應(yīng)用系統(tǒng)中已經(jīng)使用的全部硬件中斷設(shè)置為高優(yōu)先級;2)讓軟中斷使用的中斷源的優(yōu)先級為最低優(yōu)先級,以確保軟中斷中可以響應(yīng)硬件中斷,實(shí)現(xiàn)中斷嵌套。4.1 使用外部中斷使用外部中斷0和1作為軟中斷時(shí),應(yīng)當(dāng)使中斷的觸發(fā)方式設(shè)置為邊沿觸發(fā),并且對應(yīng)的引腳只能進(jìn)行輸出,不能為輸入,若設(shè)計(jì)為輸入時(shí)系統(tǒng)不能分辨硬件觸發(fā)和軟件觸發(fā)。即使是對外輸出,也需要限制為軟中斷的服務(wù)來提供輸出,就能避免輸出的變化錯(cuò)誤地觸發(fā)中斷。經(jīng)過上述的設(shè)置后,就可以利用軟件來控制中斷標(biāo)志IE0或IE1的置位和清除,由于51單片機(jī)(兼容)中斷系統(tǒng)能夠在中斷返回時(shí)自動(dòng)

9、清除外部中段標(biāo)志IE0或IE1,因此在結(jié)束軟中斷服務(wù)時(shí)可以不清除中斷標(biāo)志。例如,使用外部中斷0來實(shí)現(xiàn)軟中斷。首先,開放外部中斷0,使EX0=1其次,設(shè)置外部中斷0為沿觸發(fā),使IT0=1;接下來用“IE0=1”來置位IE0申請軟中斷服務(wù),而使用“IE0=0”來清除IE0結(jié)束軟中斷服務(wù)(可以不使用“IE0=0”而由中斷系統(tǒng)在中斷服務(wù)中自動(dòng)清除)。參見例2所示例程。4.2 使用定時(shí)器中斷使用定時(shí)器0、定時(shí)器1和定時(shí)器2中斷,需要考慮的是關(guān)閉定時(shí)器,以避免定時(shí)器溢出產(chǎn)生中斷申請。這時(shí)軟件就能完全控制中斷標(biāo)志TFRTF1或TF2的置位以及清除,以申請軟中斷和結(jié)束軟中斷服務(wù)。應(yīng)當(dāng)注意,51單片機(jī)(兼容)的

10、中斷系統(tǒng)在中斷返回時(shí)不會自動(dòng)消除TFRTF1和TF2,因此,在結(jié)束軟中斷服務(wù)時(shí),一定要清除相應(yīng)得中斷標(biāo)志TFRTF1或TF2。對于具有定時(shí)計(jì)數(shù)器2的單片機(jī),如果將其應(yīng)用于串口的波特率發(fā)生器,就是最好的軟中斷資源。因?yàn)槎〞r(shí)器而一旦被應(yīng)用于串口產(chǎn)生發(fā)送時(shí)鐘或者接收時(shí)鐘,定時(shí)器的溢出就不會設(shè)置TF2(TF2willnotbesetwheneitherRCLK=1orTCLK=1.)。例如,使用定時(shí)器0來實(shí)現(xiàn)軟中斷。首先,關(guān)閉定時(shí)器0,使TR0=Q其次,開放定時(shí)器0的中斷,使ET0=1;接下來用“TF0=1”來置位TF0申請軟中斷服務(wù),而使用“TF0=0”來清除TF0結(jié)束軟中斷服務(wù)。參見例2所示例程。

11、4.3 使用其它中斷資源其他的中斷資源,只要沒有和引腳有關(guān)聯(lián),就可以在關(guān)閉模塊功能的條件下直接,用軟件來設(shè)置或清除相應(yīng)模塊的中斷申請標(biāo)志,以申請軟中斷服務(wù)或結(jié)束軟中斷服務(wù)。例如,在51單片機(jī)(兼容)應(yīng)用系統(tǒng)中沒有使用用口(對于多用口單片機(jī),是串口0)通訊,就可以使用串口的RI中斷標(biāo)志來實(shí)現(xiàn)軟中斷。首先,禁止接收(復(fù)位狀態(tài)就是禁止的),使REN=0其次,開放用口中斷,使ES=1;接下來,利用“RI=1”來置位RI申請軟中斷服務(wù),而使用“RI=0”來清除RI結(jié)束軟中斷服務(wù)。參見例2所示例程。再例如,在STC12C5AxxS2用系統(tǒng)中,不使用ADCB塊,就可以使用ADO塊的ADC_FLA序斷標(biāo)志來實(shí)

12、現(xiàn)軟中斷。首先,禁止ADCS塊(復(fù)位狀態(tài)就是禁止的),使ADC_POWER翔閉ADC®塊的電源;其次,開放ADC中斷,使EADC=1接下來用“ADC_CONTTOx10”來置位ADC_FLA由請軟中斷服務(wù),而使用“ADC_CONTR=0x00”來清除ADC_FLA鰭束軟中斷服務(wù)。參見例2所示例程。4.3定義軟中斷為了使軟件具有很好的移植性,可以使用宏定義來實(shí)現(xiàn)具體應(yīng)用系統(tǒng)的軟中斷。在這個(gè)宏定義中,應(yīng)當(dāng)完成參數(shù)的傳遞以及軟中斷的申請。例1定義了一個(gè)可以攜帶3個(gè)參數(shù)的宏,第一個(gè)參數(shù)是申請的功能號,第二個(gè)參數(shù)是輸入數(shù)據(jù)的地址,第三個(gè)參數(shù)是結(jié)果輸出的地址。利用這三個(gè)參數(shù),就可以處理任意類型的

13、數(shù)據(jù)(參考例2所示的例程)。對于簡單的系統(tǒng),如果軟中斷提供的服務(wù)沒有其他的數(shù)據(jù)需要輸入輸出,就可只使用一個(gè)參數(shù):服務(wù)功能號。例1:軟中斷的宏定義#defineSWI(a,b,c)FunctionNum=a;InputParameter=(unsignedchar*)&b;OutputParameter=(unsignedchar*)&c;SWI_IRQ();_nop_();在例1所示的宏中,SWI_IRQ()也是一個(gè)宏,用來在宏中自動(dòng)地選擇中斷源,而不需要修改代碼。參照例2,一個(gè)SWI_IRQ()定義的例子:/定義軟件中斷使用的中斷號defineSWI_NUM1使用外部中斷0作

14、軟中斷ifSWI_NUM=0defineSWI_IRQ()IE0=1defineCLEAR_SWI()/IE0=0/使用T0中斷祚軟件中斷elifSWI_NUM=1defineSWI_IRQ()TF0=1defineCLEAR_SWI()TF0=0對于復(fù)雜的系統(tǒng),可以動(dòng)態(tài)指定軟中斷服務(wù)的具體函數(shù)以及數(shù)據(jù)輸入輸出的入口地址。參照例3,定義軟中斷攜帶兩個(gè)參數(shù):一個(gè)是功能號,一個(gè)是函數(shù)入口地址,就可在軟中斷服務(wù)中執(zhí)行動(dòng)態(tài)的代碼Func_CallBack,以完成不同類型的任務(wù)。#defineSWI(a,b)FunctionNum=a;Func_CallBack=(void*)b;SWI_IRQ();_

15、nop_();voidSWI_ISR(void)interruptSWI_NUM/測試抬入的參數(shù)CLEAR_SWI();/清除可能需要清除的標(biāo)志Func_CallBack();/執(zhí)行指定的功能函數(shù)FunctionNum=0;清除申請功能號5、軟中斷和硬件中斷共享一個(gè)中斷源的實(shí)現(xiàn)的方法前面所描述的軟中斷實(shí)現(xiàn)方法,是利用系統(tǒng)中不使用的中斷源,將其分配給軟中斷來使用,在大多數(shù)情況下這都是適的方法。然而有的應(yīng)用系統(tǒng)確實(shí)已經(jīng)使用的全部的中斷資源,還想要軟中斷功能,這該怎么辦?下面就來討論這個(gè)題目:如何共享硬件中斷和軟中斷。解決這個(gè)問題的關(guān)鍵在于正確區(qū)分硬件觸發(fā)與軟件觸發(fā)的中斷,既要保證沒有多余的觸發(fā),又

16、要保證不漏掉任何一個(gè)觸發(fā)。由于中斷標(biāo)志只有一個(gè),若軟中斷觸發(fā)時(shí)硬中斷也觸發(fā),就不能分辨了。僅僅加軟件標(biāo)志通常不能解決這個(gè)問題,這時(shí)需要尋求其他的實(shí)現(xiàn)方法。必要時(shí)需要附加硬件來幫助實(shí)現(xiàn)軟中斷功能。選擇共享中斷源的依據(jù)是能夠準(zhǔn)確區(qū)分硬件中斷和軟中斷。比較容易成功的方法是通過附加硬件措施來改造兩個(gè)外部中斷中的一個(gè)。對于用低電平觸發(fā)的外部中斷申請,如果中斷的撤銷是由CPU來完成的,則CPU在中斷服務(wù)程序中就能通過查詢外部中斷線的電平狀態(tài)來判斷是否同時(shí)發(fā)生了硬件中斷的申請,這時(shí)軟中斷的申請標(biāo)志和硬中斷的申請電平就是兩個(gè)相互獨(dú)立的標(biāo)志,也就能夠準(zhǔn)確區(qū)分硬件中斷和軟中斷了。具有一般性的做法是將外部中斷0或外

17、部中斷1的中斷申請改為利用一個(gè)D觸發(fā)器來進(jìn)行電平方式的中斷申請,并將中斷申請的撤銷交給CPU來控制,以便系統(tǒng)能夠準(zhǔn)確識別每一個(gè)中斷申請。圖1是將邊沿觸發(fā)中斷改為電平觸發(fā)的一種實(shí)現(xiàn)方式。圖2是將主動(dòng)撤銷信號電平申請改為由CPU空制信號撤銷電平申請的一種實(shí)現(xiàn)方式。對于其他的應(yīng)用于系統(tǒng)之間通訊的通訊端口,不推薦用于共享方式實(shí)現(xiàn)軟中斷。這是因?yàn)橥ㄓ嵉臄?shù)據(jù)流可能很大,在沒有FIFO緩沖的51兼容單片機(jī)中,很有可能造成接收溢出。在51兼容單片機(jī)中,用口UAR1W使在不使用發(fā)送中斷的情況下,也不推薦應(yīng)用于軟中斷服務(wù),因?yàn)槊恳粋€(gè)數(shù)據(jù)發(fā)送完成都會自動(dòng)置位TI標(biāo)志,會干擾軟中斷的執(zhí)行。圖1邊沿觸發(fā)中斷申請改為低電

18、平觸發(fā)中斷申請圖2低電平觸發(fā)中斷申請改為CPLB銷信號的低電平觸發(fā)中斷申請6、軟中斷在實(shí)時(shí)操作系統(tǒng)環(huán)境下的應(yīng)用在基于51單片機(jī)的嵌入式系統(tǒng)中,數(shù)據(jù)采集處理、程序控制和數(shù)據(jù)通訊是三個(gè)主要的應(yīng)用方面,以下三小節(jié)分別描述數(shù)據(jù)采集處理任務(wù)、程序控制任務(wù)和數(shù)據(jù)通訊任務(wù)中軟中斷的使用,以幫助讀者加深對軟中斷的理解。軟中斷服務(wù)在數(shù)據(jù)采集處理任務(wù)中的應(yīng)用實(shí)時(shí)操作系統(tǒng)下,中斷處理占用的時(shí)間越短,系統(tǒng)的實(shí)時(shí)性越好。在一些應(yīng)用中,數(shù)據(jù)處理的實(shí)時(shí)性要求很高,系統(tǒng)的響應(yīng)時(shí)間在0.5毫秒以內(nèi)。如果數(shù)據(jù)處理的時(shí)間在最壞情況下超過0.3毫秒,系統(tǒng)的軟件設(shè)計(jì)就受到挑戰(zhàn)。如果將數(shù)據(jù)處理全部放入中斷中進(jìn)行處理,系統(tǒng)中其它任務(wù)的實(shí)時(shí)

19、性會受到嚴(yán)重影響。解決的辦法通常是以下兩種:1)不使用51單片機(jī),改用其它處理速度更快的處理器(如ARMM理器);2)不使用操作系統(tǒng)。這兩種解決辦法要受到產(chǎn)品成本和開發(fā)效率的約束。軟中斷的應(yīng)用可以成為上述問題的第3種解決方法,并且是最優(yōu)的解決方法。使用一個(gè)最低優(yōu)先級的中斷源來實(shí)現(xiàn)軟中斷,將數(shù)據(jù)處理放入軟中斷中完成。這樣,軟中斷就可以隨時(shí)剝奪任何一個(gè)正在運(yùn)行的任務(wù)而優(yōu)先執(zhí)行,執(zhí)行完成后可以回到正在執(zhí)行的任務(wù),也可以切換到已就緒的更高優(yōu)先級的任務(wù)。如此,系統(tǒng)的實(shí)時(shí)性就提高了,同時(shí),軟件開發(fā)效率也提高了。具體的辦法是,在數(shù)據(jù)采集中斷中,只完成數(shù)據(jù)的獲取,將數(shù)據(jù)存放到隊(duì)列中,然后申請軟中斷服務(wù)后退出中

20、斷服務(wù)程序。只要系統(tǒng)中沒有其它中斷事務(wù)等待處理,軟中斷就可以開始處理,并且在軟中斷處理過程中可以響應(yīng)其它的硬件中斷,從而保證系統(tǒng)的實(shí)時(shí)性由于軟中斷總是優(yōu)先于任務(wù)執(zhí)行,所以能夠保證數(shù)據(jù)處理的實(shí)時(shí)性。當(dāng)隊(duì)列中沒有數(shù)據(jù)時(shí),軟中斷退出,執(zhí)行其它任務(wù)。在這樣的機(jī)制下,沒有頻繁的上下文切換,因此CPU勺使用效率得到提高,以保證整個(gè)系統(tǒng)的實(shí)時(shí)性。以下代碼片斷是一種車輛檢測器的代碼,使用了軟中斷來處理數(shù)據(jù)??梢钥闯?,找外部中斷0中將數(shù)據(jù)放入隊(duì)列,然后申請軟中斷。在軟中斷中,只要隊(duì)列中還有數(shù)據(jù),就循環(huán)處理直到隊(duì)列為空才退出軟中斷。voidint0_int(void)interruptIE0_VECTOR/外部G

21、斷0TR0=0;/讀計(jì)數(shù)器NewNode=QMalloc();申請分配內(nèi)存if(NewNode<Q_MAX_LEN)/內(nèi)存分配成功LoopQNewNode.LoopChannel=LoopCounter;/TH2,TH1,TH0,TL7,TL6,TL5,TL4,TL3,TL2,TL1,TL0,P27P2.6,P2.5,P24P2.3/讀取21位計(jì)數(shù)值拼成2字節(jié),組成16位計(jì)數(shù)值LoopQNewNode.LoopNv=(TH0&0x03)*8192)+(TL0*32)+(P2>>3)&0x1F);LoopQNewNode.TimeStamp=0;/沒有測速,不需

22、血時(shí)間戳AddLoopNode(NewNode);SWI_IRQ();/申請軟件中斷,以便處理數(shù)據(jù)LoopSet();/計(jì)算并設(shè)置下一個(gè)通道LoopProcTimer=0;,/軟中斷服務(wù)函數(shù)voidSWI_ISR(void)interruptSWI_NUM/while(1)ProcNode=GetLoopNode();/從隊(duì)列中取待處理的數(shù)據(jù)if(ProcNode=0xFF)break;/隊(duì)列中沒有數(shù)據(jù),退出lopcout=LoopQProcNode.LoopChannel;/取通道號nvlopcout=LoopQProcNode.LoopNv;/取測量數(shù)據(jù)QFree(ProcNode);/釋

23、放內(nèi)存以便宿環(huán)使用LoopProc();/通道計(jì)算CLEAR_SWI();/清除可能需要清除的標(biāo)志軟中斷在程序控制任務(wù)中的應(yīng)用在操作系統(tǒng)中的程序控制任務(wù),具運(yùn)行受系統(tǒng)內(nèi)核支配。如果程序控制任務(wù)在邏輯上有嚴(yán)格的時(shí)間安排,很可能被高優(yōu)先級任務(wù)剝奪運(yùn)行而導(dǎo)致邏輯失敗。這種任務(wù)如果全部安排在中斷中完成處理,會影響系統(tǒng)中其它任務(wù)的實(shí)時(shí)性。這時(shí)比較好的方法就是利用軟中斷來處理時(shí)間要求很嚴(yán)格部分。通過軟中斷,中請?jiān)谥付〞r(shí)刻執(zhí)行指定的代碼。以下的代碼是程序控制任務(wù)計(jì)算出來的控制序列,通過申請軟中斷服務(wù),將待執(zhí)行的程序控制交給系統(tǒng),系統(tǒng)在定時(shí)器的嚴(yán)格同步下,將非常準(zhǔn)確地完成控制過程。代碼中,35毫秒后,功能1和

24、功能4將“同時(shí)”啟動(dòng)執(zhí)行,實(shí)際上功能1先于功能4執(zhí)行,時(shí)間上相差大約10uS左右。SWI_REQ(20,func1,data1);/SWI_REQ(25,func2,data2);/SWI_REQ(26,func3,data3);/SWI_REQ(35,func1,data4);/SWI_REQ(35,func4,data5);/SWI_REQ(36,func3,data6);/申請20ms后執(zhí)行功能1,其所需的參數(shù)在data1申請25ms后執(zhí)行功能2,其所需的參數(shù)在data2申請26ms后執(zhí)行功能3,其所需的參數(shù)在data3申請35ms后執(zhí)行功能1,其所需的參數(shù)在data4申請35ms后執(zhí)行

25、功能4,其所需的參數(shù)在data5申請36ms后執(zhí)行功能3,其所需的參數(shù)在data6軟中斷在數(shù)據(jù)通訊任務(wù)中的應(yīng)用在數(shù)據(jù)通訊中,有些通訊協(xié)議對系統(tǒng)的響應(yīng)時(shí)間有嚴(yán)格的要求,兩個(gè)數(shù)據(jù)包之間的空閑時(shí)間有嚴(yán)格的限制,超過一定時(shí)間就認(rèn)為超時(shí)。這種情況下,數(shù)據(jù)通訊任務(wù)如果全部安排在中斷中完成處理,則會影響系統(tǒng)其它任務(wù)的實(shí)時(shí)性,如果放在任務(wù)中運(yùn)行,運(yùn)行的時(shí)間又不可控制。當(dāng)然可以在任務(wù)中關(guān)閉中斷來處理實(shí)時(shí)性要求較強(qiáng)的代碼,可是這樣做會影響其他部分的實(shí)時(shí)性。比較好的方法,就是利用軟中斷,將需要提供的實(shí)時(shí)服務(wù)通過軟中斷申請將目標(biāo)代碼和數(shù)據(jù)在不影響系統(tǒng)實(shí)時(shí)性的條件下優(yōu)先執(zhí)行。首先,在系統(tǒng)中建立一個(gè)軟中斷函數(shù)執(zhí)行的鏈表,

26、將等待執(zhí)行代碼入口地址和數(shù)據(jù)入口地址放在這個(gè)鏈表中。一旦內(nèi)核運(yùn)行完畢,就自動(dòng)來檢測這個(gè)鏈表中是否存在待執(zhí)行的軟中斷代碼。如果有軟中斷代碼,立即按照優(yōu)先順序執(zhí)行。當(dāng)所有的軟中斷代碼執(zhí)行完成后,就檢查是否有高優(yōu)先級的任務(wù)已經(jīng)就緒等待執(zhí)行,若有,進(jìn)行任務(wù)調(diào)度。當(dāng)然,申請軟中斷服務(wù)本身就可能引發(fā)任務(wù)調(diào)度。這得看軟中斷服務(wù)完成后,是否有更高優(yōu)先級任務(wù)進(jìn)入就緒態(tài)。比如,有一個(gè)任務(wù)在發(fā)送完成一個(gè)數(shù)據(jù)包后,有嚴(yán)格的時(shí)間要求在20ms后準(zhǔn)確啟動(dòng)第二個(gè)數(shù)據(jù)包的發(fā)送。如果利用OSWait()或OSTimeDly()的方式,則完全不可能在20ms后準(zhǔn)確開始。如果關(guān)閉中斷等待20ms,系統(tǒng)的效率將十分低下。用軟中斷的方

27、法是,向系統(tǒng)申請一個(gè)軟中斷服務(wù),將服務(wù)要求的啟動(dòng)時(shí)刻、提供服務(wù)函數(shù)入口地址以及數(shù)據(jù)的存儲地址提供給系統(tǒng),就可以在指定的時(shí)刻運(yùn)行這段代碼,完成數(shù)據(jù)的發(fā)送工作。即使當(dāng)前任務(wù)在申請完軟中斷服務(wù)后被剝奪,也能保證指定的數(shù)據(jù)在20ms后發(fā)送出去。軟中斷函數(shù)執(zhí)行鏈表的結(jié)構(gòu)typedefstructSwi_List_MALLOC_MEM_*SwiNode;typedefstructSwi_ListunsignedintTimeDelay;/延遲多少時(shí)間開始執(zhí)行,等于0表示立即執(zhí)行void(*Func)(unsignedchar*pInOut);/執(zhí)行的函數(shù)入口地址unsignedchar*pInOut;/執(zhí)

28、行函數(shù)的數(shù)據(jù)輸入輸出地址SwiNodeNextNode;/下一個(gè)節(jié)點(diǎn)的地址;這樣的偽代碼就是:,/準(zhǔn)備第一個(gè)數(shù)據(jù)包Send(Packet1);/發(fā)送第一個(gè)數(shù)據(jù)包/準(zhǔn)備第二個(gè)數(shù)據(jù)包SWI_REQ(20,Send,Pachet2);申請20ms后發(fā)送第二個(gè)數(shù)據(jù)包7、無操作系統(tǒng)環(huán)境下軟中斷的應(yīng)用在沒有操作系統(tǒng)軟件環(huán)境中,如果要執(zhí)行的事務(wù)比較簡單也比較少,用輪詢的方法調(diào)度各個(gè)模塊就基本可以滿足。然而當(dāng)事務(wù)比較多或事務(wù)比較復(fù)雜時(shí),實(shí)時(shí)性的協(xié)調(diào)就很難。在這種情況下,就可以利用軟中斷來簡化各個(gè)模塊之間的時(shí)間協(xié)調(diào),可大大提高系統(tǒng)的實(shí)時(shí)性和可協(xié)調(diào)性。在一個(gè)沒有操作系統(tǒng)的51單片機(jī)應(yīng)用系統(tǒng)中開發(fā)軟件,軟中斷不僅可

29、以用來幫助對臨界段的管理,以實(shí)現(xiàn)硬件資源的互斥訪問以及共享數(shù)據(jù)的互斥訪問,還可以實(shí)現(xiàn)無阻塞等待。還舉6.3節(jié)的例子,一個(gè)模塊在發(fā)送完成一個(gè)數(shù)據(jù)包后,有嚴(yán)格的時(shí)間要求在20ms后準(zhǔn)確啟動(dòng)第二個(gè)數(shù)據(jù)包的發(fā)送。用軟中斷在系統(tǒng)中申請一個(gè)20ms的延時(shí)定時(shí)器,定時(shí)器到時(shí)執(zhí)行回調(diào)函數(shù)Send(),完成第二個(gè)數(shù)據(jù)包的發(fā)送。這樣的偽代碼就是:unsignedcharPacket_Send(void)If(CanSend=0)return1;/發(fā)送忙,返回1If(IsPendInTimer(Send)return2;/Send函數(shù)被掛起在定時(shí)器的服務(wù)列表中,第二個(gè)數(shù)據(jù)包還沒有啟動(dòng)發(fā)送,返回2/準(zhǔn)備第一個(gè)數(shù)據(jù)包S

30、end(Packet1,len1);/發(fā)送第一個(gè)數(shù)據(jù)包/準(zhǔn)備第二個(gè)數(shù)據(jù)包SWI_REQ(20,Send,Pachet2,len2);/申請20ms后發(fā)送第二個(gè)數(shù)據(jù)包return0;/發(fā)送完成,返回0卜面一個(gè)例子,揭示軟中斷如何實(shí)現(xiàn)硬件資源的互斥訪問大家都使用過I2C總線器件,比如實(shí)時(shí)時(shí)鐘、溫度傳感器、EEPRO除等。不論單片機(jī)自帶的硬件I2C控制器還是用軟件模擬的I2C控制器,我們都必須保證對I2C總線操作的完整性,避免多個(gè)模塊之間同時(shí)爭用I2C總線。在實(shí)時(shí)操作系統(tǒng)環(huán)境下,這個(gè)很容易實(shí)現(xiàn),但在沒有實(shí)時(shí)操作系統(tǒng)來管理時(shí),就需要設(shè)置信號量來幫助各個(gè)模塊之間協(xié)調(diào)使用。我們都知道,I2C總線是低速總線

31、,軟件模擬中線控制器時(shí)將耗費(fèi)很多CPU時(shí)間,并且一個(gè)模塊必須完成訪問后才能釋放訪問權(quán)限。在沒有實(shí)時(shí)操作系統(tǒng)的軟件環(huán)境中,CPUt不得不等待。為了提高CPU勺利用率,在12c總線的驅(qū)動(dòng)程序中使用軟中斷,能夠很好地協(xié)調(diào)各模塊之間使用12c總線訪問不同的器件。軟中斷服務(wù)執(zhí)行指定的發(fā)送或接收函數(shù),并將結(jié)果復(fù)制到指定的內(nèi)存地址中,然后還可以執(zhí)行指定的回調(diào)函數(shù)(如果有的話)。由于軟中斷優(yōu)于任何模塊獲得CPU運(yùn)行,故模塊之間提交的軟中斷獨(dú)立于模塊代碼而完整運(yùn)行(硬件中斷不妨礙其正確執(zhí)行)。由于收發(fā)的硬件操作僅在軟中斷中執(zhí)行,自然實(shí)現(xiàn)了硬件資源的互斥訪問。同時(shí),軟中斷中對共享的變量操作也具有了原子性。參閱例程

32、4所示代碼片斷。/模塊1:VoidM1()(SWI(1,&MySwiNode1);/申請軟中斷/退出該模塊,軟件中斷執(zhí)行完成后,實(shí)時(shí)時(shí)鐘的數(shù)據(jù)自動(dòng)保存在clock口中/模塊2:VoidM2()(省略)SWI(1,&MySwiNode2);/申請軟中斷/退出該模塊,軟件中斷執(zhí)行完成后,溫度數(shù)據(jù)自動(dòng)保存在temp口中voidmain(void)(,/運(yùn)行模塊1M1();/運(yùn)行模塊2M2();,8、結(jié)語在51單片機(jī)中,利用硬件中斷的中斷向量,實(shí)現(xiàn)軟中斷是完全可行的,并且使用軟中斷能夠優(yōu)化應(yīng)用軟件的執(zhí)行效率。例2:一個(gè)SWI演示例程(STC12C5AxxS2片機(jī))#include<

33、;STC_NEW_8051.h>#include<intrins.h>sbitLED=P1A0;定義軟件中斷使用的中斷號,可選09#defineSWI_NUM1/使用外部吊斷0作軟中斷ifSWI_NUM=0defineSWI_IRQ()IE0=1defineCLEAR_SWI()/IE0=0/使用T0中斷存軟件中斷elifSWI_NUM=1defineSWI_IRQ()TF0=1defineCLEAR_SWI()TF0=0/使用外部中斷1作軟中斷elifSWI_NUM=2defineSWI_IRQ()IE1=1defineCLEAR_SWI()/IE1=0/使用T1中斷存軟件

34、中斷elifSWI_NUM=3defineSWI_IRQ()TF1=1defineCLEAR_SWI()TF1=0/使用UART中嬴乍軟件中斷elifSWI_NUM=4defineSWI_IRQ()RI=1defineCLEAR_SWI()RI=0/使用ADC斷作軟件中斷elifSWI_NUM=5defineSWI_IRQ()ADC_CONTR=0x10defineCLEAR_SWI()ADC_CONTR=0x00/使用LVD中斷作軟件中斷elifSWI_NUM=6defineSWI_IRQ()PCON|=0x20defineCLEAR_SWI()PCON&=0xDF/使用PCA中麻作

35、軟件中斷elifSWI_NUM=7defineSWI_IRQ()CF=1defineCLEAR_SWI()CF=0/使用UART巾斷作軟件中斷elifSWI_NUM=8defineSWI_IRQ()S2CON|=0x01defineCLEAR_SWI()S2CON&=0xFE/使用SPI中斷作軟件中斷elifSWI_NUM=9defineSWI_IRQ()SPDAT=0xFFdefineCLEAR_SWI()SPSTAT=0xC0#endif#ifdefSWI_NUMunsignedcharFunctionNum;/unsignedchar*InputParameter;unsigne

36、dchar*OutputParameter;#defineSWI(a,b,c)FunctionNum=a;InputParameter=(unsignedchar*)&bOutputParameter=(unsignedchar*)&c;SWI_IRQ();_nop_();#endifvoidSwiFunction_Init(void)一/將硬件中斷源置于高優(yōu)先級,IP=0xFF;IP2=0xFF;IPH=0x00;IPH2=0x00;/將軟中斷所使用的中斷源置于低優(yōu)先級ifSWI_NUM<8IP&=(0x01<<SWI_NUM);elifSWI_NU

37、M<10IP2&=(0x01<<(SWI_NUM-8);#endif/使用外部中斷0作軟中斷ifSWI_NUM=0IT0=1;/邊沿觸發(fā)EX0=1;/使用T0中斷作軟件中斷elifSWI_NUM=1ET0=1;/使用外部中斷1作軟中斷elifSWI_NUM=2IT1=1;/邊沿觸發(fā)EX1=1;/使用T1中斷作軟件中斷elifSWI_NUM=3ET1=1;/使用UAR伸斷作軟件中斷elifSWI_NUM=4ES=1;/使用ADC斷作軟件中斷elifSWI_NUM=5EADC=1;/使用LVD中斷作軟件中斷elifSWI_NUM=6ELVD=1;/使用PCA中斷作軟件中斷

38、elifSWI_NUM=7CMOD|=0x01;/ECF=1/使用UART珅斷作軟件中斷#elifSWI_NUM=8IE2|=0x01;/ES2=1/使用SPI中斷作軟件中斷#elifSWI_NUM=9AUXR1|=0x20;/SPI切換到P4口SPCTL=0xD0;/MASTE秋式IE2|=0x02;/ESPI=1#endifEA=1;voidmain(void)unsignedcharSwiFun_Num;intDataIn,result,i;P0=0xFF;P1=0xFF;P2=0xFF;P3=0xFF;SwiFunction_Init();/初始化軟中斷功能DataIn=0;resul

39、t=0;SwiFun_Num=0;while(1)SwiFun_Num+;DataIn+;SWI(SwiFun_Num,DataIn,result);申請軟中斷服務(wù)if(result!=(DataIn+SwiFun_Num)for(;)_nop_();/錯(cuò),停在這里for(i=0;i<32767;i+)_nop_();#ifdefSWI_NUMvoidSWI_ISR(void)interruptSWI_NUM/軟中所服務(wù)函數(shù)提供的功能是輸出=輸入+申請功能號LEDA=1;/便于觀察是否進(jìn)入軟中斷服務(wù)CLEAR_SWI();/清除可能需要清除的標(biāo)志*(int*)OutputParamete

40、r=*(int*)InputParameter+FunctionNum;FunctionNum=0;/清除申請功能號#endif例3:一個(gè)具有動(dòng)態(tài)代碼執(zhí)行能力的SWI演示例程(STC12C5AxxS單片機(jī))#include<STC_NEW_8051.h>#include<intrins.h>voidSet_LED0(void);voidSet_LED1(void);省略,同例2sbitLED=P1A0;/定義軟件中斷使用的中斷號:#ifdefSWI_NUMunsignedcharFunctionNum;void(*Func_CallBack)(void);#define

41、SWI(a,b)FunctionNum=a;Func_CallBack=(void*)b;SWI_IRQ();_nop_();省略,代碼同例2#endifvoidSwiFunction_Init(void)/voidSet_LED0(void)LED=0;voidSet_LED1(void)LED=1;voidmain(void)unsignedcharSwiFun_Num;inti;P0=0xFF;P1=0xFF;P2=0xFF;P3=0xFF;SwiFunction_Init();/初始化軟中斷功能SwiFun_Num=0;while(1)SwiFun_Num+;/申請欣中斷服務(wù)if(LE

42、D=1)SWI(SwiFun_Num,Set_LED0);ElseSWI(SwiFun_Num,Set_LED1);for(i=0;i<32767;i+)_nop_();#ifdefSWI_NUMvoidSWI_ISR(void)interruptSWI_NUM/軟中而服務(wù)函數(shù),提供的服務(wù)是執(zhí)行指定的功能函數(shù)CLEAR_SWI();/清除可能需要清除的標(biāo)志Func_CallBack();/執(zhí)行指定的功能函數(shù)FunctionNum=0;/清除申請功能號#endif例程4:一個(gè)SWI演示例程,互斥訪問I2C總線(STC12C5AxxS單片機(jī))typedefstructSwi_List*Swi

43、Node;typedefstructSwi_ListunsignedintTimeDelay;/延遲多少時(shí)間開始執(zhí)行,等于0表示立即執(zhí)行void(*Func)(unsignedchar*pInOut);/執(zhí)行的函數(shù)入口地址unsignedchar*pInOut;/執(zhí)行函數(shù)的數(shù)據(jù)輸入輸出地址SwiNodeNextNode;/下一個(gè)節(jié)點(diǎn)的地址;SwiNodeSWI_Head_Node;/原統(tǒng)內(nèi)核使用的指針變量#ifdefSWI_NUMunsignedcharFunctionNum;SwiNodeSwiIRQNode;#defineSWI(a,b)FunctionNum=a;SwiIRQNode=b

44、;SWI_IRQ();_nop_();#endifuint8IICRead(uint8*Ret,uint8Addr,uint8NByte)/硬件上操作總線,完成讀取功能(省略)uint8IICWrite(uint8Addr,uint8*Data,uint8NByte)/硬件上操作總線,完成寫入功能(省略)voidPCF8563Read(uint8*Data)uint8NByte;NByte=*Data+;IICWrite(PCF8563Addr,Data,1);IICRead(Data-1,PCF8563Addr,NByte);voidPCF8563Write(uint8*Data)uint8

45、NByte;NByte=*Data+;NByte+;IICWrite(PCF8563Addr,Data,NByte);voidGet_Temperature(int*RegTemperature)/讀傳忌器的溫度,力感器的地址本*RegTemperature指定uint8SensorAddr;uint8TempReg2;SensorAddr=(uint8*)RegTemperature;/訪問的傳感器地址TempReg0=SENSOR_REG_TEMPERATUREW感器的溫度值寄存器IICWrite(WRITE_SENSOR_ADDR0+(SensorAddr&0x07)*2,Tem

46、pReg,1);/寫一個(gè)字節(jié)IICRead(Temp,READ_SENSOR_ADDR0+(SensorAddr&0x07)*2,2);/讀兩個(gè)字節(jié)*RegTemperature=(Temp0<<8)+Temp1;voidSWI_ISR(void)interruptSWI_NUM/軟中所服務(wù)函數(shù)提供的服務(wù)是執(zhí)行鏈表中的函數(shù)if(FunctionNum=1)/功能1:增加軟中斷服務(wù),將軟中斷申請放到隊(duì)列中等待執(zhí)行if(SWI_Head_Node=0)/申請內(nèi)存SWI_Head_Node=(SwiNode)malloc(sizeof(Swi_List_Struct);if(SW

47、I_Head_Node!=0)SWI_Head_Node->TimeDelay=SwiIRQNode->TimeDelay;SWI_Head_Node->Func=SwiIRQNode->Func;SWI_Head_Node->pInOut=SwiIRQNode->pInOut;SWI_Head_Node->NextNode=0;)一一)else(省略)/尋找是否有就緒的軟中斷任務(wù)需要執(zhí)行pNode=SWI_Head_Node;pRightNode=SWI_Head_Node;for(;)if(pNode!=0)if(pNode->TimeDel

48、ay)=0)/發(fā)現(xiàn)一個(gè)等待執(zhí)行的軟中斷if(pNode=SWI_Head_Node)/是第一個(gè)節(jié)及一if(pNode->NextNode)!=0)/還有下一個(gè)節(jié)點(diǎn)/撤銷節(jié)點(diǎn)SWI_Head_Node=pNode->NextNode;pRightNode=SWI_Head_Node;/執(zhí)行函數(shù)pNode->Func(pNode->pInOut);/釋放內(nèi)存free(pNode);pNode=pRightNode;/指向下一個(gè)節(jié)點(diǎn))else/沒有下一個(gè)節(jié)點(diǎn)(省略)else/不是第一個(gè)節(jié)點(diǎn)(省略)else/移動(dòng)指針pRightNode=pNode;pNode=pNode-&g

49、t;NextNode;)elsebreak;)FunctionNum=0;/清除申請功能號CLEAR_SWI();/清除可能需要清除的標(biāo)志)/模塊1:VoidM1()Swi_List_StructMySwiNode1;/用于讀寫PCF856裳時(shí)時(shí)鐘staticuint8clock8=0,0,0,0,0,0,0,0;/根據(jù)溫度執(zhí)行相應(yīng)的操作(省略)/讀取PCF8563勺時(shí)間數(shù)據(jù)MySwiNode1.Func=PCF8563Read;/胞行的函數(shù)是PCF8563ReadMySwiNode1.pInOut=clock;/輸入輸出的參數(shù)clock8clock0=7;/讀7個(gè)字節(jié)clock1=2;/從PCF寄存器2開始讀MySwiNodel.TimeDelay=0;/執(zhí)行功能的延遲時(shí)間為0,要求立即開始執(zhí)行SWI(1,&MySwiNode1);/申請軟中斷/退出該模塊,軟件中斷執(zhí)行完成后,實(shí)時(shí)時(shí)鐘的數(shù)據(jù)自動(dòng)保存在clock口中/模塊2:VoidM2()Swi_List_StructMySwiNode2;/staticuint8temp2=0,0;/用于讀寫AD741魏度傳感器int*T;T=(int*)temp;/指向存儲溫度的內(nèi)存/根據(jù)溫度執(zhí)行相應(yīng)的操作(省略),/讀取AD7416勺溫度數(shù)據(jù)MySwiNode2.Func=Get_

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論