新闻| 论坛| 博客| 在线研讨会
Zigbee基础实验(2)—通过中断控制LED
luker| 2016-02-24 16:11:19 阅读:4268 发布文章

通过本次实验,将会清楚如何捕获一个外部中断和CC2530捕获外部中断后的处理流程

本次实验所学到的新寄存器为:

P0IEN:各个控制口的中断使能,0为中断禁止,1为中断使能。
D7
D6
D5
D4
D3
D2
D1
D0
P0_7 P0_6 P0_5 P0_4 P0_3 P0_2 P0_1 P0_0

P0INP:设置各个I/O口的输入模式,0为上拉/下拉,1为三态模式
D7
D6
D5
D4
D3
D2
D1
D0
P0_7模式
P0_6模式 P0_5模式 P0_4模式 P0_3模式 P0_2模式 P0_1模式 P0_0模式

PICTL:D0~D3设置各个端口的中断触发方式,0为上升沿触发,1为下降沿触发。
D7控制I/O引脚在输出模式下的驱动能力。选择输出驱动能力增强来补偿引脚DVDD的低I/O电压,确保在较 低的电压下的驱动能力和较高电压下相同。0为最小驱动能力增强。1为最大驱动能力增强。
D7
D6
D5
D4
D3
D2
D1
D0
I/O驱动能力
未用
未用
未用
P2_0~P2_4
P1_4~P1_7
P1_0~P1_3
P0_0~P0_7

IEN1:中断使能1,0为中断禁止,1为中断使能
D7
D6
D5
D4
D3
D2
D1
D0
未用
未用
端口0 定时器4
定时器3
定时器2 定时器1 DMA传输

P0IFG:中断状态标志寄存器当输入端口有中断请求时,相应的标志位将置1。
D7
D6
D5
D4
D3
D2
D1
D0
P0_7
P0_6 P0_5 P0_4 P0_3 P0_2 P0_1 P0_0


源代码:
#include
#define uint unsigned int
#define uchar unsigned char
//定义控制灯的端口
#define RLED P1_0 //定义LED1为P10口控制
#define YLED P1_1 //定义LED2为P11口控制
#define GLED P1_4 //定义LED3为P14口控制
#define KEY1 P0_1 //定义按键为P01口控制
//函数声明
void Delay(uint); //延时函数声明
void Initial(void); //初始化函数声明
void InitKey(void); //初始化按键函数声明
uchar KeyScan(void); //按键扫描函数声明

uchar Keyvalue = 0 ; //定义变量记录按键动作
uint KeyTouchtimes = 0 ; //定义变量记录按键次数

void Delay(uint n)
{
uint i;
for(i = 0;i for(i = 0;i for(i = 0;i for(i = 0;i for(i = 0;i }

void InitKeyINT(void)
{
P0SEL &= ~0X02; //普通功能
P0DIR &= ~0X02; //P0_1I/O口,设置为输入模式
P0INP |= 0x02; //上拉

P0IEN |= 0X02; //P01设置为中断方式
PICTL |= 0X01; //下降沿触发
EA = 1;
IEN1 |= 0X20; // P0设置为中断方式;
P0IFG |= 0x00; //初始化中断标志位
}

void InitIO(void)
{
P1DIR |= 0x13; //P10、P11、P14定义为输出
RLED = 0;
GLED = 0;
YLED = 0; //LED灯初始化为灭
}

#pragma vector = P0INT_VECTOR //中断服务子程序
__interrupt void P0_ISR(void)
{
if(P0IFG0) //按键中断
{
P0IFG = 0;
Delay(25000);
if(P0IFG==0) //按键中断
{
Delay(100);
KeyTouchtimes = KeyTouchtimes+1; //每次中断发生时记录按键次数加1
}
}
P0IF = 0; //清中断标志
}

void main(void)
{
InitIO();
InitKeyINT(); //调用初始化函数

while(1)
{
if(KeyTouchtimes ==1) //红灯亮、其余灯不亮
{
RLED = 1;
GLED = 0;
YLED = 0;
}
if(KeyTouchtimes == 2) //红灯亮、黄灯亮、绿灯不亮
{
RLED=1;
YLED=1;
GLED=0;
}
if(KeyTouchtimes == 3) //三盏灯全亮
{
RLED=1;
YLED=1;
GLED=1;
}
if(KeyTouchtimes == 4) //全部灯灭
{
RLED = 0;
GLED = 0;
YLED = 0;
KeyTouchtimes =0; //重置按键次数记录变量
}
}
}

实验总结
CC2530中断机制:
①当按键S1按下时,因为S1所对应的I/O口为P0_1,所以P0端口将会发出一个中断请求,并自动将P0IFG寄存器对应位(即D1位)置1,等待CPU响应
②CPU在执行完一条指令之后就会检测是否有中断请求,如果检测到中断请求并且IEN1的D5位为1和P0IEN的D1为 1时,对应的中断使能位中断使能,则根据中断类型号获得中断向量,根据中断向量得到中断服务子程序的地址,执行终端服务子程序。当中断服务子程序执行完毕 后返回执行原来的程序。

P0IEN寄存器与IEN1寄存器的区别:
P0IEN和IEN1同样都是中断屏蔽寄存器,P0IEN控制P0口每一个端口的中断使能,IEN1控制整个P0的中断使能。当IEN1中设置了P0口中 断屏蔽时(D5=0),无论P1IEN中对应的使能位设置成屏蔽还是使能,该I/O发出的中断请求CPU都不予接受。例如:若将本例中 InitKeyINT()函数中的 IEN1 |= 0X20; 代码行注释掉,S1按下后LED将没有变化。


中断服务子程序的写法:
我们先看头文件中的部分代码:
#define T1_VECTOR VECT( 9, 0x4B ) /* Timer 1 (16-bit) Capture/Compare/Overflow */
#define T2_VECTOR VECT( 10, 0x53 ) /* Timer 2 (MAC Timer) */
#define T3_VECTOR VECT( 11, 0x5B ) /* Timer 3 (8-bit) Capture/Compare/Overflow */
#define T4_VECTOR VECT( 12, 0x63 ) /* Timer 4 (8-bit) Capture/Compare/Overflow */
#define P0INT_VECTOR VECT( 13, 0x6B ) /* Port 0 Inputs */

通过datasheet可知,0X6B为P0口的中断向量,#define P0INT_VECTOR VECT( 13, 0x6B )将P0口的中断向量定位为P0INT_VECTOR。同理,上面所列出的代码还将其他的中断向量分别作了定义。得知了中断向量后,我们就可以编写中断服务子程序。格式如下:
#pragma vector = 中断向量
__interrupt void 任意函数名(void)
{
//中断处理,处理完成后通常需要清除中断标志。
}

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客