其中部分内容为本人自我认知,仅供参考,如有不足请补充。
。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。 --------------------- 第一步---------------------。。。。
。。。。 ——————介绍相关寄存器——————。。。
。。。。 --------------------- 第二步---------------------。。。。
。。。。 ——介绍由整体代码拆分后的部分内容——。。。
。。。。 --------------------- 第三步---------------------。。。。
。。。。 ——————呈现整体代码——————。。。。
。。。。 --------------------- 第四步---------------------。。。。
。。。。 ————————总结————————。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。
————直接上案例来解释中断————
任务:用按键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
void HAL_Delay(uint32_t num)
{
for(uint32_t x=0;x<=num;x++)
for(uint32_t y=0;y<=535;y++);
}
void Init_Port()
{
P1SEL &= ~0x1b;
P1DIR |= 0x1b;
P1 &= ~0x1b;
}
void Init_T1()
{
EA = 1;
T1IE = 1;
T1CCTL0 |= 0x04;
T1CC0L = 0xd4;
T1CC0H = 0x30;
}
void Init_P1INT()
{
IEN2 |= 0x10;
P1IEN |= 0x04;
PICTL |= 0x02;
}
void main()
{
Init_Port();
Init_T1();
Init_P1INT();
while(1)
{ }
}
uint8_t P1_Flag = 0; //按键当前状态
uint32_t count = 0; //定时器计数
#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;
}
}
#pragma vector = T1_VECTOR
__interrupt void T1_Serivce(void)
{
if((P1_Flag == 1) && (count != 65535))
count++;
}
总结
难点为进入端口1中断后在按键按下时需要提高优先级才可进入定时器1中断