藍橋杯單片機組備賽指南請查看這篇文章:戳此跳轉藍橋杯備賽指南文章
本文章針對藍橋杯-單片機組比賽開發板所寫,代碼可直接在比賽開發板上使用。
型號:國信天長4T開發板(綠板),芯片:IAP15F2K61S2
(使用國信天長藍板也可以完美兼容,與綠板幾乎無差別)
1.編程目的
????????通過對外部中斷的學習,了解外部中斷的操作過程,并實現獨自完成外部中斷的編程,通過控制led燈光進行展示效果。
//設置按鍵S5進行中斷操作,L1閃爍為主函數,自動運行,L8常按亮為中斷執行程序。
2.外部中斷原理
2.1 單片機的中斷系統
????????單片機的中斷系統具有很大的用處,賽題中必定會用到。中斷系統的響應流程如下:當有中斷信號輸入時,單片機停止當前的工作,轉而去先執行中斷服務函數要求的工作,等中斷服務函數要求的工作全部做完,單片機又返回去繼續執行先前的工作。
????????比賽用單片機最多允許兩層中斷的嵌套。即在低級的中斷服務函數執行過程中,收到了更高級的中斷信號,而去先執行更高級的中斷工作,執行完再返回繼續執行低級的中斷工作,低級的中斷工作做完,再回到最原本的代碼繼續執行。
比賽用芯片IAP15F2K61S2?涉及的中斷共有14個,這里介紹常用的5個:
中斷號 | 中斷名 | 中斷名解釋 |
0 | INT0 | 外部中斷0 |
1 | T0 | 定時/計數器中斷0 |
2 | INT1 | 外部中斷1 |
3 | T1 | 定時/計數器1 |
4 | TI/RI | 串口中斷 |
5 | T2 | 定時/計數器中斷2 |
????????本文聚焦外部中斷,只對外部中斷0和外部中斷1進行講解,他們的中斷號對應為0和2。比賽用開發板中還有INT2,INT3,INT4,共計5個外部中斷信號源的介紹,將在專欄“藍橋杯-單片機組進階”中講解。
????????其余中斷的操作請參考本專欄下的其他文章。
2.2 什么叫外部中斷?
????????我們對比賽用開發板的芯片進行觀察,可以發現與INT0和INT1相關的兩個引腳,分別是P3.2和P3.3?
????????此時如果我們要使用外部中斷0,那么可以對P3.2引腳輸入低電平,通過觀察獨立按鍵的原理圖可以得知,當按鍵S5被按下時,剛好會向單片機的P3.2引腳輸入低電平,因此我們可以將按鍵S5作為一個中斷的信號源。
????????當按下S5時,P3.2引腳讀取到低電平,單片機內部產生中斷響應,暫停當前程序而優先執行中斷服務程序,執行完中斷服務程序后返回繼續執行當前程序。編程時,我們不需要對單片機引腳P3.2讀取到低電平、按鍵S5被按下等過程進行編程,因為中斷的響應只需要通過對寄存器的設置,單片機自動識別中斷信號并自動響應。我們只需要關注中斷產生之后,我們要做什么(中斷服務函數)。
2.3 設置外部中斷用到的寄存器
兩級中斷允許控制:IE(interrupt enable)
EA | - | ET2 | ES | ET1 | EX1 | ET0 | EX0 |
IE中各位的功能如下:
EA—中斷允許總開關控制位。EA=0,所有的中斷請求被屏蔽。EA=1,所有的中斷請求被開放。
ES—串行口中斷允許位。ES=0,禁止串行口中斷。ES=1,允許串行口中斷。
ET1—定時器/計數器T1溢出中斷允許位。ET1=0,禁止T1溢出中斷。ET1=1,允許T1溢出中斷。
EX1—外部中斷1中斷允許位。EX1=0,禁止外部中斷1中斷。EX1=1,允許外部中斷1中斷。
ET0—定時器/計數器T0的溢出中斷允許位。ET0=0,禁止T0溢出中斷。ET0=1,允許T0溢出中斷。
EX0—外部中斷0中斷允許位。EX0=0,禁止外部中斷0中斷。EX0=1,允許外部中斷0中斷。
? ? ? ? 該寄存器允許位尋址,在編程時,如果只用到一個外部中斷0,則我們只需要設置總開關EA和外部中斷0允許位EX0 。
兩級優先級控制:IP(interrupt priority)
- | - | PT2 | PS | PT1 | PX1 | PT0 | PX0 |
中斷優先級寄存器IP各位含義:
PS—串行口中斷優先級控制位,1—高級;0—低級。
PT1—T1中斷優先級控制位,1—高級;0—低級。
PX1—外部中斷1中斷優先級控制位,1—高級;0—低級。
PT0—T0中斷優先級控制位,1—高級;0—低級。
PX0—外部中斷0中斷優先級控制位,1—高級;0—低級。
各中斷源的中斷優先級關系的基本規則:
(1)低優先級可被高優先級中斷,高優先級不能被低優先級中斷。
(2)任何一種中斷(不管是高級還是低級)一旦得到響應,不會再被它的同級中斷源所中斷。如果某一中斷源被設置為高優先級中斷,在執行該中斷源的中斷服務程序時,則不能被任何其他的中斷源的中斷請求所中斷。
? ? ? ? 當不對其進行設置時,則按照默認優先級執行。如果我們只用到外部中斷0的話,則不需要對其進行設置。默認優先級與中斷號順序相同。
特殊功能寄存器:TCON(timer controller)
TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
TCON寄存器中與中斷系統有關各標志位功能如下:
TF1—定時器/計數器T1的溢出中斷請求標志位。當啟動T1計數后,T1從初值開始加1計數,當最高位產生溢出時,硬件 置TF1為“1”,向CPU申請中斷,響應TF1中斷時,TF1標志硬件自動清“0”,TF1也可由軟件清“0”。
TF0—定時器/計數器T0溢出中斷請求標志位,與TF1類似。
IE1—外部中斷請求1中斷請求標志位。
IE0—外部中斷請求0中斷請求標志位,與IE1類似。
IT1—選擇外中斷請求1為跳沿觸發還是電平觸發方式。0--電平觸發方式,加到INT0*腳上的外中斷請求輸入信號為低電平有效,并把IE1置“1”。轉向中斷服務程序時,則由硬件自動把IE1清“0”。1--跳沿觸發方式,加到INT1*腳上的外中斷請求輸入信號從高到低的負跳變有效,并把IE1置“1”。轉向中斷服務程序時,則由硬件自動把IE1清“0”。
IT0—選擇外中斷請求0為跳沿觸發方式還是電平觸發方式,與IT1類似。
? 該寄存器允許位尋址,在編程時,如果只用到一個外部中斷0,則我們只需要設置IT0從而確定外部中斷0的觸發方式 。
3.中斷在編程中的函數
3.1 外部中斷初始化函數
????????功能是在主函數運行時,將需要用到的中斷功能進行設置,使得響應的中斷正常運行。例如:
????????在該函數中,通過設置IT0使得外部中斷0為邊沿觸發,設置EX0和EA使得外部中斷0正常開啟。
3.2 外部中斷服務函數
????????功能是在單片機響應中斷后,去執行我們需要他執行的功能。注意,該函數內部不要設置返回值,通過不要寫判斷或循環等語句,可以通過設置全局標志的方式實現數據傳遞。例如:
????????在該段程序中,我們定義了一個全局變量state_INT0,用于在中斷響應后對該變量置一,從而可以在程序中通過對該變量進行查詢,獲知中斷是否產生。編程時,需要注意中斷服務函數后面需要加上關鍵字:interrupt X。X為該中斷的中斷號,外部中斷0為0
4.代碼參考
????????代碼效果://設置按鍵S5進行中斷操作,L1閃爍為主函數,L8常按亮為中斷執行程序
//設置按鍵S5進行中斷操作,L1閃爍為主函數,L8常按亮為中斷執行程序#include < REG52.h >
#include < INTRINS.h >sbit S5 = P3^2;
sbit L1 = P0^0;
sbit L2 = P0^1;void select_HC173 ( unsigned char channal )
{switch ( channal ){case 4:P2 = ( P2 & 0x1f ) | 0x80 ;break;case 5:P2 = ( P2 & 0x1f ) | 0xa0 ;break; case 6:P2 = ( P2 & 0x1f ) | 0xc0 ;break; case 7:P2 = ( P2 & 0x1f ) | 0xe0 ;break; }
}void Delay2ms ()
{unsigned char i,j;_nop_ ();_nop_ ();i=22;j=128;do {while ( --j );}while ( --i );
}void clean_shake ( unsigned char t )
{while ( t-- ){Delay2ms ();}
}//========================================
void Init_INT0 ()
{IT0 = 1;EX0 = 1;EA = 1;
}unsigned char state_INT0 = 0;
void Service_INT0 () interrupt 0
{state_INT0 = 1;
}void LED_INT0 ()
{if ( state_INT0 == 1 ){L2 = 0;clean_shake ( 600000 );L2 = 1;clean_shake ( 600000 );}state_INT0 = 0;}//=========================================void LED_L1_running ()
{select_HC173 ( 4 );L1 = 0;clean_shake ( 20 );L1 = 1;clean_shake ( 20 );
}void main ()
{Init_INT0 ();while ( 1 ){LED_L1_running ();LED_INT0 ();}
}
5.編程思路的小點點
???????中斷的操作主要是涉及兩個步驟:
1.對中斷進行正確的初始化,并在主函數中運行初始化函數;
2.正確利用中斷服務函數,要注意加上中斷號,且其內部盡量減少程序語句。并且通過適當的方式將“中斷產生”這個事件傳遞出來,從而進行執行。對于直接在中斷服務函數中寫入需要執行的程序,以及在中斷服務中設置一個標志變量兩種不同的方式,他們的對比如下:
????????第一種方式:在中斷服務函數中接入程序體,比較簡潔。容易出現一個問題:中斷前的代碼和中斷瞬間的代碼同時執行,如主函數是L1閃爍,中斷是L8燈閃爍,如果中斷發生時L1正好亮了,那么L1會一直亮直到中斷函數L8閃爍結束。
????????第二種方式:在中斷服務函數中修改標志變量的值,在外部函數中判斷標志變量的值來決定是否執行中斷程序。這種方式會將主函數與中斷的運行函數拆成兩個函數,就會在收到中斷后等主函數結束當前階段再進入中斷狀態,避免L1和L8同時亮的情況。注意標志變量要定義全局變量,中斷服務函數主體盡可能減少操作量。