中断的概念:
中断是在程序的运行过程中,受到内部或者外部的相应,按照优先级执行程序(其中复位的优先级最高,详见数据手册——中断部分)
CC2530中断源的中断走向:
- 确定端口触发模式(PICTL)
- 判断中断是否触发(P?IFG)
- 打开端口位中断使能(P?IEN)
- 判断中断是否已经被处理(P?IF)
- 打开中断总开关(EA)
- 打开相应中断使能(IEN?)
- 由51内核进行处理
中断的基本配置:
- PICTI 中断边缘寄存器: 设置端口是输入上升引起中断,还是下降引起中断 0:上升 1:下降
- P?IFG 端口中断状态标志: 设置中断请求是否触发,没有触发为0,有触发,则相应位为1
- P?IEN 端口位中断屏蔽: 设置端口位的中断使能 0:禁止 1:使能
- P?IF 端口位中断标志: 设置中断是否被处理 0:未处理 1:已处理
- EA 中断总开关: 设置是否禁止所有中断 0:禁止 1:分别设置
- IEN? 端口中断使能: 设置端口的中断使能 0:禁止 1:使能
中断处理过程:
当中断被触发,交由51内核进行处理;在我们的RAM中,有一块空间专门用于存储中断向量表,中断向量表按照中断优先级将中断向量存储在这块空间中,一旦一个中断开始执行,只有其他优先级比它高的向量能把它打断;而我们的中断向量其实就是一个GO TO语句,直接指向相应中断服务函数的开头,当中断服务程序执行完毕后,再返回主函数的中断点,继续运行;
下面我们通过程序进行分析:
/***********************************************
* filename: Key_Interrupt.c
* writer : geeknuo
* time : 2017-1-21
* version : 1.0
* effect : 按键中断实验
************************************************/
#include <ioCC2530.h>
//端口定义;
#define led P1_0
#define key P0_1
/***********************************************
* function name : delay_ms
* function : 延时函数,单位为毫秒
* prarmeter : n_ms 为延时时间,最大不超过65535
* returned value: 无
************************************************/
void delay_ms(unsigned int n_ms)
{
unsigned int i,j;
for(i = 0; i < n_ms; i++)
for(j = 0; j < 535; j++);
}
/***********************************************
* function name : LedInit
* function : 配置led相关寄存器并设置led初始状态
* prarmeter : 无
* returned value: 无
************************************************/
void LedInit(void)
{
P1DIR |= 0x01; //P1_0设置为输出模式
P1SEL &= ~0x01; //P1_0设置为通用IO
led = 1; //初始状态为熄灭;
}
/***********************************************
* function name : KeyInit
* function : 配置key相关寄存器
* prarmeter : 无
* returned value: 无
************************************************/
void KeyInit(void)
{
P0DIR &= ~0x02; //P1_0设置为输入模式
P0SEL &= ~0x02; //P1_0设置为通用IO
PICTL |= 0x01; //设置输入下降沿引起中断
P0IFG &= ~0x02; //设置 P0_1 中断状态标志为0,没有触发
P0IF = 0; //设置 P0_1 中断标志为0,表示没有中断未处理
P0IEN |= 0x02; //打开 P0_1 的中断使能
EA = 1; //打开总开关
IEN1 |= (1<<5); //打开端口的中断使能
}
//中断服务函数
#pragma vector = P1INT_VECTOR
__interrupt void P1_ISR(void)
{
/*中断服务程序需要做的事情*/
delay_ms(10);
led = ~led;
P0IFG = 0; //清中断标志
P0IF = 0; //清中断标志
}
/***********************************************
* function name : main
* function : 初始化LED和KEY,当检测到按键按下并松开时,改变led状态
* prarmeter : 无
* returned value: 无
************************************************/
void main(void)
{
LedInit(); //初始化LED
KeyInit(); //初始化KEY
while(1)
{
}
}
此程序实现的效果跟按键程序的效果是一样的,在按键程序中,我们采用的是轮询的方式进行判断,这里我们采用中断的方式来处理,整体应该还是比较容易理解的,只是这里涉及的寄存器相对较多,通过数据手册应该可以很快的理解;我们对中断服务函数再进行一下分析:
#pragma vector = P1INT_VECTOR
__interrupt void P1_ISR(void)
{
/*中断服务程序需要做的事情*/
}
/*************************************************
* #pragma //表示中断向量指向的地址
* vector //存放向量的变量
* P1INT_VECTOR //P1端口的中断向量地址
* __interrupt //将函数的首地址放入中断向量表中
* P1_ISR //相当于函数名
*************************************************/