MC9S的中斷編程主要有兩種方式:
1.使用符號“TRA_PROC” ,TRAP_PROC 提示編譯器下面的函數是中斷服務例程。編譯器會用一個特殊的中斷返回指令來結束這個函數(對大多數處理器來說,一般是RTI指令).
2.使用“interrupt”關鍵字,“interrupt”關鍵字是一個非標準ANSI-C的關鍵字,因此,它不能被所有ANSI-C編譯器廠商所支持。同樣,對不同的編譯器,“interrupt”關鍵字的用法可能會改變。“interrupt”關鍵字同樣會提示編譯器下面的函數是一箇中斷服務例程。
一旦中斷服務函數寫好了,必須把中斷服務例程和中斷向量表聯繫起來,這通過初始化中斷向量表來實現,可以通過下面兩種方法來初始化中斷向量表:
1.在PRM文件中,使用“VECTOR ADDRESS”或“VECTOR”命令。連接器提供兩個命令來初始化中斷向量表:VECTOR ADDRESS 或 VECTOR,你使用VECTOR ADDRESS 命令中斷服務例程的地址寫到中斷向量表裏。
2.使用“interrupt”關鍵字,在寫中斷服務例程的時候,可以在ANSI-C源文件裏直接把中斷服務例程和特殊的中斷號聯繫起來。
下面是MC9SDG128B的16位自由定時器溢出中斷處理程序,已調試通過:
#include <hidef.h> /* common defines and macros */
#include <mc9s12dg128.h> /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dg128b"
int intcount = 0;
void timer_init(void)
{
TSCR2_PR0 = 1; //prescale factor is 128
TSCR2_PR1 = 1;
TSCR2_PR2 = 1;
TSCR2_TOI = 1; //overflow enable
TFLG2_TOF = 1;
TSCR1_TEN = 1; //timer enable
}
#pragma CODE_SEG NON_BANKED
interrupt 16 void timer_interrupt_handle(void)
{
intcount++;
TFLG2_TOF = 1; //clear interrupt flag
}
#pragma CODE_SEG DEFAULT
void main(void)
{
EnableInterrupts;
timer_init();
for(;;) {}
}
以下是採用TRAP_PROC符號編寫的中斷服務程序:
#include <hidef.h> /* common defines and macros */
#include <mc9s12dg128.h> /* derivative information */
#pragma LINK_INFO DERIVATIVE "mc9s12dg128b"
int intcount = 0;
void timer_init(void)
{
TSCR2_PR0 = 1; //prescale factor is 128
TSCR2_PR1 = 1;
TSCR2_PR2 = 1;
TSCR2_TOI = 1; //overflow enable
TFLG2_TOF = 1;
TSCR1_TEN = 1; //timer enable
}
#pragma CODE_SEG NON_BANKED
#pragma TRAP_PROC
void timer_interrupt_handle(void)
{
intcount++;
TFLG2_TOF = 1;
};
#pragma CODE_SEG DEFAULT
void main(void)
{
EnableInterrupts;
timer_init();
for(;;) {}
}
中斷服務程序編寫完後你需要在.prm文件裏添加如下一句:
VECTOR 16 timer_interrupt_handle
這樣中斷服務程序才和相應的中斷號聯繫起來。
中斷服務例程必須被定位於non-banked 區域,通過使用“#pragma CODE_SEG NON_BANKED”可以把中斷例程定位於non-banked 區域。同時你必須確保“sectionNON_BANKED”不能出現在.prm文件中。在中斷服務例程的末尾你需要添加“#pragma CODE_SEG DEFAULT”,否則的話,後面的函數也會被定位在“non-banked”區域。
所以說我們的中斷服務例程必須被“#pragma CODE_SEG NON_BANKED”和“#pragma CODE_SEG DEFAULT”包圍起來。