[Zigbee] CC2530外部中断

[复制链接]
 楼主| gwsan 发表于 2019-7-31 10:46 | 显示全部楼层 |阅读模式
1 理论分析
1.1 CC2530 通用 IO 中断详解
通用 I/O 引脚设置为输入后,可以用于产生中断。中断可以设置在外部信号的上升或下降沿触发。P0、P1 或 P2 端口都有中断使能位,对位于 IENl-2 寄存器内的端口所有的位都是公共的,如下:
        IENI.P0 IE:P0 中断使能
        IEN2.PI IE:P1 中断使能
        IEN2.P2IE:P2 中断使能

除了这些公共中断使能之外,每个端口的位都有位于 SFR 寄存器 P0IEN、P1IEN和 P2IEN 的单独的中断使能。即使配置为外设 I/O 或通用输出的 I/O 引脚使能时都有中断产生。

当中断条件发生在 I/O 引脚之一上面,P0-P2 中断标志寄存器 P0IFG、P1IFG 或 P2IFG 中相应的中断状态标志将设置为 1。不管引脚是否设置了它的中断使能位,中断状态标志都被设置。当中断已经执行,中断状态标志被清除,该标志写入 0。这个标志必须在清除 CPU 端口中断标志(PxIF)之前被清除。
用于中断的 SFR 寄存器描述在下一节。寄存器总结如下:

        P0IEN: P0 中断使能
        P1IEN:P1 中断使能
        P2IEN:P2 中断使能
        PICTL:P0、P1 和 P2 触发沿设置
        P0FG:P0 中断标志
        P1IFG:P1 中断标志
        P2IFG:P2 中断标志


 楼主| gwsan 发表于 2019-7-31 10:49 | 显示全部楼层
1.2 流程图

下面是很实验的流程图,大家可以结合这个图来学习编写程序。


 楼主| gwsan 发表于 2019-7-31 10:49 | 显示全部楼层
2 实验详解
2.1实验目的
1)、通过实验掌握CC2530芯片GPIO的配置方法,带你一步步走进嵌入式大门
2)、握Led驱动电路及开关Led的原理
3)、过按键S1产生外部中断改变LED1\LED2\LED3状态

2.2实验设备
硬件:PC 机一台 ZB2530(底板、核心板、仿真器、USB 线) 一套
软件:win7 系统,IAR 8.20 集成开发环境
 楼主| gwsan 发表于 2019-7-31 10:50 | 显示全部楼层
2.3实验相关电路图

图2 LED电路图

图3 按键电路图
 楼主| gwsan 发表于 2019-7-31 10:50 | 显示全部楼层
2.4实验分析
        启用通用 IO 中断步骤

(1)清除中断标志;
(2)如果有,则设置 SFR 寄存器中对应的各中断使能位为 1;
(3)设置寄存器 IEN0、IEN1 和 IEN2 中对应的中断使能位为 1;
(4)设置 IEN0 中的 EA 位为 1 使能全局中断;
(5)在该中断对应的向量地址上,运行该中断的服务程序。
 楼主| gwsan 发表于 2019-7-31 10:51 | 显示全部楼层
寄存器配置

也就是说,通用 IO 端口使用中断模式时,需要配置 PxIEN、PICTL、PxIFG、IENx、EA、PxSEL、PxDIR、PxINP 这些寄存器(或其相关位) ;而 LED 灯控制端口配置的是 PxSEL、PxDIR、PxINP 这三个寄存器:
通用寄存器的作用和配置方法如表1、2、3所示(以P1为例):

表1 端口1的功能选择
626975d41020ed8891.png

表2 端口1的方向

825045d410212a7d9e.png
表3 端口1的输入模式

521715d410217c0ec5.png
CC2530外部中断需要配置P0IEN 、PICTL 、P0IFG、IEN1寄存器。外部中断寄存器


 楼主| gwsan 发表于 2019-7-31 10:51 | 显示全部楼层
说明如表4、5、6、7所示(以端口0为例):

表4 端口0的中断屏蔽
631615d4102340bf1a.png

表5 端口中断控制
404875d41023885444.png

表6 端口0的中断状态标志
241275d41023e90616.png

表7 中断使能
181295d4102441a084.png

按照表格寄存器的内容,对LED3配置如下:
P1SEL &=~0x01; //配置P1.0为通用IO口,默认为0的,可以不设
P1DIR |= 0x01; //P10 定义为输出

按键S1配置如下:
P0IEN |= 0x02; // P0.1 设置为中断方式1:中断使能
PICTL |= 0x00; //上升沿触发
IEN1 |= 0x20; //允许P0口中断;
P0IFG = 0x00; //初始化中断标志位
EA = 1; //打开总中断


 楼主| gwsan 发表于 2019-7-31 10:52 | 显示全部楼层
2.5参考代码
/**Includes*********************************************************************/
#include <ioCC2530.h>

/**宏定义***********************************************************************/
//定义数据类型
#define uint unsigned int
#define uchar unsigned char

//定义控制LED灯的端口
#define LED1 P1_0        //定义LED1为P1.0口控制
#define KEY1 P0_1       //中断口

/**函数声明*********************************************************************/

void Delayms(uint);                //延时函数
void InitLed(void);                //初始化P1口
void InitKey();                 //按键初始化

/**
  * @brief     中断处理
  * @param     None
  * @retval    None
  */
#pragma vector = P0INT_VECTOR    //格式:#pragma vector = 中断向量,紧接着是中断处理程序
  __interrupt void P0_ISR(void)
{
  Delayms(10);            //去除抖动
  LED1=~LED1;             //改变LED1状态
  P0IFG = 0;              //清中断标志
  P0IF = 0;               //清中断标志
}

/**
  * @brief     主函数
  * @param     None
  * @retval    None
  */
void main(void)
{
  InitLed();                //调用初始化函数
  InitKey();
  while(1)
  {
  }
}

/**
  * @brief     普通延时函数
  * @param     xms 延时长度
  * @retval    None
  */
void Delayms(uint xms)   //i=xms 即延时i毫秒
{
  uint i,j;
  for(i=xms;i>0;i--)
    for(j=587;j>0;j--);
}

/**
  * @brief     LED初始化
  * @param     None
  * @retval    None
  */
void InitLed(void)
{
  P1DIR |= 0x01; //P1_0定义为输出
  LED1 = 1;       //LED1灯熄灭     
}

/**
  * @brief     KEY初始化程序--外部中断方式
  * @param     None
  * @retval    None
  */
void InitKey()
{
  P0IEN |= 0X02;  //P01设置为中断方式
  PICTL |= 0X00; // 上升沿触发中断   
  IEN1 |= 0X20;   // 允许P0口中断;
  P0IFG = 0x00;   // 初始化中断标志位
  EA = 1;
}
 楼主| gwsan 发表于 2019-7-31 10:52 | 显示全部楼层
2.6实验现象
使用外部中断,通过按键控制LED的反转。
 楼主| gwsan 发表于 2019-7-31 10:52 | 显示全部楼层
2.7 实验总结
2.7.1 CC2530 中断机制
(1) 当按键 KEY1 按下时,因为 KEY1 所对应的 I/O 口为 P0_1,所以 P0 端口将会发出一个中断请求,并自动将 P0IFG 寄存器对应位(即 D4 位)置 1,等待 CPU 响应;

(2) CPU 在执行完一条指令之后就会检测是否有中断请求,如果检测到中断请求并且 IEN1 的 D5 位为 1 和 P0IEN 的 D4 为 1 时,对应的中断使能位中断使能,则根据中断类型号获得中断向量,根据中断向量得到中断服务子程序的地址,执行终端服务子程序。当中断服务子程序执行完毕后返回执行原来的程序

2.7.2 P1IEN 寄存器与 IEN2 寄存器的区别
P0IEN 和 IEN1 同样都是中断屏蔽寄存器, P0IEN 控制 P0 口每一个端口的中断使能,IEN1 控制整个 P0 的中断使能。当 IEN1 中设置了 P0 口中断屏蔽时(D5=0) ,无论 P0IEN 中对应的使能位设置成屏蔽还是使能,该 I/O 发出的中断请求 CPU 都不予接受。例如:若将本例中 InitKey ()函数中的 IEN1|= 0X20; 代码行注释掉,KEY 按下后 LED1将没有变化。
 楼主| gwsan 发表于 2019-7-31 10:53 | 显示全部楼层
2.7.3中断向量
我们先看头文件中关于中断向量定义的代码:
364095d41028b6ca85.png


图4 IAR 里打开文件的方法

829955d4102914ff2d.png
图 5CC2530 中断向量表
看图5中注释或者通过 datasheet 可知,0X6B 为 P0 口的中断向量,#define P0INT_VECTOR VECT( 13, 0x6B )将 P0 口的中断向量定位为 P0INT_VECTOR。同理,上面所列出的代码还将其他的中断向量分别作了定义。

表8 CC2530datasheet 中断概览
413785d4102975babc.png


 楼主| gwsan 发表于 2019-7-31 10:53 | 显示全部楼层
2.7.4中断服务子程序格式
#pragma vector = 中断向量
__interrupt void 任意函数名(void)
{
//中断处理,处理完成后通常需要清除中断标志
}
 楼主| gwsan 发表于 2019-7-31 10:53 | 显示全部楼层
2.7.5启用通用 IO 中断步骤
(1)清除中断标志;
(2)如果有,则设置 SFR 寄存器中对应的各中断使能位为 1;
(3)设置寄存器 IEN0、IEN1 和 IEN2 中对应的中断使能位为 1;
(4)设置 IEN0 中的 EA 位为 1 使能全局中断;
(5)在该中断对应的向量地址上,运行该中断的服务程序
conjunction 发表于 2019-7-31 14:06 | 显示全部楼层
感谢楼主分享!很不错的经验
您需要登录后才可以回帖 登录 | 注册

本版积分规则

69

主题

3439

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部