其中部分内容為本人自我認知,僅供參考,如有不足請補充。
。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。 --------------------- 第一步---------------------。。。。
。。。。 ——————介紹相關寄存器——————。。。
。。。。 --------------------- 第二步---------------------。。。。
。。。。 ——介紹由整體代碼拆分後的部分内容——。。。
。。。。 --------------------- 第三步---------------------。。。。
。。。。 ——————呈現整體代碼——————。。。。
。。。。 --------------------- 第四步---------------------。。。。
。。。。 ————————總結————————。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。
————直接上案例來解釋中斷————
任務:用按鍵1長按或短按控制LED6與LED4(使用端口1中斷和定時器1中斷來實作)
有關LED的相關寄存器
P1SEL(Port 1 set level)——端口1功能寄存器

P1DIR(Port 1 direction register)——端口1方向寄存器
P1(Port 1)——端口1
存儲P1_0到P1_7的狀态資訊。
有關端口1中斷的相關寄存器
PICTL(Port input communication trigger level)——端口輸入信号
P1IFG (Port 1 interrupt flag group)——P1端口狀态标志寄存器
P1IEN (Port 1 interrupt enable)——P1端口中斷使能
IEN0 (Interrupt enable 0)——中斷使能寄存器0
IEN2 (Interrupt enable 2)——中斷使能寄存器2
有關定時器1中斷的相關寄存器
T1CCTLx(Time1 Capture Control)——端口輸入信号
使用通道0作為定時器通道
IEN1 (Interrupt enable 1)——中斷使能寄存器1
T1STAT (Time1 State Thoroughfare)——P1端口狀态标志寄存器
使用通道0作為定時器通道
簡易延遲部分
由于CPU執行一條指令需要時間,是以讓CPU堆滿指令條可做到視覺上的延遲
void HAL_Delay(uint32_t num)
{
for(uint32_t x=0;x<=num;x++)
for(uint32_t y=0;y<=535;y++);
}
初始化LED部分
引腳的對應物件
P1_1 ==> 燈4
P1_4 ==> 燈6
void Init_Port()
{
P1SEL &=~ 0x1b; //設定P1_0、P1_1、P1_3、P1_4為通用I/O功能。
P1DIR |= 0x1b; //設定P1_0、P1_1、P1_3、P1_4的傳輸方向為輸出。
P1 &=~ 0x1b; //設定P1_0、P1_1、P1_3、P1_4為0(D3、D4、D5、D6關閉)
}
初始化端口1中斷的部分
void Init_P1INT()
{
IEN2 |= 0x10; //設定端口1中斷使能為1
P1IEN |= 0x04; //設定端口P1_2中斷使能
PICTL |= 0x02; //設定端口P1_3到P1_0中斷觸發方式為下降沿觸發
}
初始化定時器1中斷的部分
void Init_T1()
{
EA = 1;
T1IE = 1;
T1CCTL0 |= 0x04; //設定通道0為定時器1的
T1CC0L = 0xd4; //設定T1CC0的初始值
T1CC0H = 0x30;
}
定時器中斷服務函數部分
#pragma vector = T1_VECTOR //定義中斷向量
__interrupt void T1_Serivce(void) //設定中斷服務函數名
{
if((P1_Flag == 1) && (count != 65535)) //防止count溢出
count++;
}
定時器中斷服務函數部分
#pragma vector = P1INT_VECTOR //定義中斷向量
__interrupt void P1INT_Serivce(void) //設定中斷服務函數名
{
if((P1IFG & 0x04) == 0x04) //是否檢測到下降沿産生的中斷标志
{
P1IFG = 0;
P1IF = 0;
IP0 |= 0x02; //提高定時器1優先級
T1CTL |= 0x0e; //開啟定時器1
PICTL &= ~0x02; //切換端口1為上升沿觸發
P1_Flag = 1;
while((P1IFG & 0x04) != 0x04); //等待按鍵松開
P1IFG = 0;
P1IF = 0;
P1_Flag = 0;
PICTL |= 0x02; //切換端口1為下降沿觸發
T1CTL = 0; //關閉定時器1
if(count <= 5)
D4 = ~D4;
else
D6 = ~D6;
count = 0;
}
}
整體代碼
#include<iocc2530.h>
#define uint32_t unsigned int
#define uint8_t unsigned char
#define D4 P1_1
#define D5 P1_3
#define D6 P1_4
/**************************************************************
函數名稱:HAL_Delay
功 能:軟體延時
入口參數:延時循環執行次數
出口參數:無
返 回 值:無
**************************************************************/
void HAL_Delay(uint32_t num)
{
for(uint32_t x=0;x<=num;x++)
for(uint32_t y=0;y<=535;y++);
}
/**************************************************************
函數名稱:Init_Port
功 能:初始化端口
入口參數:無
出口參數:無
返 回 值:無
**************************************************************/
void Init_Port()
{
P1SEL &= ~0x1b;
P1DIR |= 0x1b;
P1 &= ~0x1b;
}
/**************************************************************
函數名稱:Init_T1
功 能:定時器初始化,不啟動定時器
入口參數:無
出口參數:無
返 回 值:無
**************************************************************/
void Init_T1()
{
EA = 1;
T1IE = 1;
T1CCTL0 |= 0x04;
T1CC0L = 0xd4;
T1CC0H = 0x30;
}
/**************************************************************
函數名稱:Init_P1INT()
功 能:端口1中斷初始化
入口參數:無
出口參數:無
返 回 值:無
**************************************************************/
void Init_P1INT()
{
IEN2 |= 0x10;
P1IEN |= 0x04;
PICTL |= 0x02;
}
/**************************************************************
函數名稱:main
功 能:程式主函數
入口參數:無
出口參數:無
返 回 值:無
**************************************************************/
void main()
{
Init_Port();
Init_T1();
Init_P1INT();
while(1)
{}
}
uint8_t P1_Flag = 0; //按鍵目前狀态
uint32_t count = 0; //定時器計數
/**************************************************************
函數名稱:P1INT_Serivce
功 能:中斷服務函數,切換LED狀态
入口參數:無
出口參數:無
返 回 值:無
**************************************************************/
#pragma vector = P1INT_VECTOR
__interrupt void P1INT_Serivce(void)
{
if((P1IFG & 0x04) == 0x04)
{
P1IFG = 0;
P1IF = 0;
IP0 |= 0x02; //提高定時器優先級
T1CTL |= 0x0e; //開啟定時器
PICTL &= ~0x02; //切換端口1為上升沿觸發
P1_Flag = 1;
while((P1IFG & 0x04) != 0x04); //等待按鍵松開
P1IFG = 0;
P1IF = 0;
P1_Flag = 0;
PICTL |= 0x02; //切換端口1為下降沿觸發
T1CTL = 0; //關閉定時器
if(count <= 5)
D4 = ~D4;
else
D6 = ~D6;
count = 0;
}
}
/**************************************************************
函數名稱:T1_Serivce
功 能:0.1s計時
入口參數:無
出口參數:無
返 回 值:無
**************************************************************/
#pragma vector = T1_VECTOR
__interrupt void T1_Serivce(void)
{
if((P1_Flag == 1) && (count != 65535))
count++;
}
總結
難點為進入端口1中斷後在按鍵按下時需要提高優先級才可進入定時器1中斷