CC2530的中断系统及外部中断应用

Posted 364.99°

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CC2530的中断系统及外部中断应用相关的知识,希望对你有一定的参考价值。


1.中断的相关概念

  1. 内核外设之间的主要交互方式:轮询中断

轮询的方式貌似公平,但实际工作效率很低,不能及时响应紧急事件
中断系统使得内核具备了应对突发条件的能力

  1. 中断

程序在执行过程中由于外界的原因而被中间打断的情况称为中断:

  1. 在执行CPU当前程序时,由于系统中出现了某种急需处理的情况,CPU暂停正在执行的程序,转而去执行另一段特殊程序来处理出现的紧急事务
  2. 处理结束后CPU自动返回到原来暂停的程序中去继续执行
  1. 两个重要概念

中断服务函数: 内核响应中断后执行的相应处理程序
中断向量: 中断服务程序的入口地址


每个中断源都对应一个固定的入口地址。当内核响应中断请求时,就会暂停当前的程序执行,然后跳转到该入口地址执行代码

2.CC2530中断系统

  1. 18个中断源,由一系列特殊功能寄存器来进行控制
  2. 可以编译设置优先级以及使能中断申请响应等
  3. 常用中断源
    在这里插入图片描述

3.CC2530中断处理函数编写方法

中断服务函数与一般的自定义函数不同,有特定的书写格式

#pragma vector = <中断向量>
__interrupt void<函数名称>(void){  //注意:此处是两个下划线连在一起
    /*编写具体的中断处理程序*/
}
  1. 在每一个中断服务函数之前,都要加上一句起始语句:#pragma vector = <中断向量>

<中断向量>:表示接下来要写的中断服务函数是为哪个中断源服务的,由两种写法:

  1. 中断向量的入口地址:#pragma vector = 0x7B
  2. 头文件"ioCC2530.h"的宏定义:#pragma vector = P1INT_VECTOR
  1. __interrupt:表示该函数是一个中断服务函数

<函数名称>:可以自定义,函数体不能带有参数,也不能有返回值

4.CC2530外部中断

  1. P0、P1和P2端口分别使用P0IF、P1IF和P2IF作为中断标志位,任何一个端口组上的引脚产生外部中断时,都会将对应端口组的中断标志自动置位
  2. 端口状态标志寄存器P0IFG、P1IFG和P2IFG,分别对应三个端口中各引脚的中断触发状态,当某引脚发生外部中断触发时,对应的标志位会自动置位

注意: 1.外部中断标志必须在中断服务函数中手动清除
       2.端口状态标志也需要手动清除

5.案例:外部中断输入控制LED灯

要求:

将ZigBee小模块上SW1按键设置为外部中断输入引脚。在中断服务函数中,控制一个LED6灯的开关切换,也就是原来的LED是点亮的熄灭,原来是熄灭的点亮。同时在主程序中,运行一段跑马灯程序,使LED3和LED4灯轮流点亮熄灭

设计思路:

  1. 端口初始化和跑马灯程序,参考CC2530的通用IO端口(GPIO)输入和输出控制
  2. 定义一个外部中断初始化函数,将SW1即P1_2引脚配置成外部中断输入端口,将其中断触发方式设置为下降沿触发
  3. 为外部中断定义一个中断服务函数,要按照中断服务函数的书写格式,注意:在中断服务函数中把相应的中断标志位清除必须先清除引脚的中断标志,再清除端口组的中断标志
  1. 涉及外部中断初始化函数Init_INTP()
    外部中断初始化函数:主要完成跟中断相关的特殊功能寄存器的配置工作
  1. 配置IENx寄存器,使能端口组中断功能
    在这里插入图片描述
  2. 配置PxIEN寄存器,使能具体的外部中断引脚
  3. 配置PICTL寄存器,设置中断触发方式
  1. 涉及外部中断服务函数Int1_Sevice()
  1. 在编写中断服务函数时,注意书写格式和中断向量要正确
  2. 注意: 在函数里面把端口组和引脚的标志为手动清除,否则CPU将反复进入中断,必须先清除引脚标志位PxIFG,再清除端口组标志位PxIF

完整源代码

#include "ioCC2530.h"

#define LED6 P1_4
#define LED3 P1_0
#define LED4 P1_1

/*========================延时函数===========================*/

void Delay(unsigned int t){
  while(t--)
}

/*========================端口初始化函数=====================*/

void Init_Port(){
  //将P1_0、P1_1和P1_4设置为通用I/O口
  P1SEL &= ~0X13;
  //将P1_0、P1_1和P1_4设为输出
  P1DIR |= 0x13;
  
  //设置LED灯不亮
  LED6 = 0;
  LED3 = 0;
  LED4 = 0;
}

/*========================跑马灯子函数=======================*/

void LED_Running(){
  LED3 = 1;
  Delay(50000);
  LED4 = 1;
  Delay(50000);
  LED3 = 0;
  Delay(50000);
  LED4 = 0;
  Delay(50000);
}

/*========================外部中断初始化函数================*/

void Init_INTP(){
  //端口1中断使能
  IEN2 |= 0x10;
  //端口P1_2外部中断使能
  P1IEN |= 0x04;
  //端口P1_0到P1_3下降沿触发
  PICTL = 0x02;
  //使能总中断
  EA = 1;
}

/*========================外部中断1服务函数=================*/

//外部中断1的向量输入
#pragma vector = P1INT_VECTOR
__interrupt void Int1_Sevice(){
  LED6 = ~lED6;
  /*先清除引脚标志位,再清除端口标志位,否则会不断进入中断*/
  P1IFG &= ~0x04;//软件清楚P1_2引脚的标志位
  P1IF = 0;//软件清除P1端口组的标志位
}

/*========================主函数============================*/

void main(){
  //初始化通用i/o端口
  Init_Port();
  //初始化外部中断
  Init_INTP();
  
  while(1){
    //跑马灯
    Led_Running();
  }
}

以上是关于CC2530的中断系统及外部中断应用的主要内容,如果未能解决你的问题,请参考以下文章

CC2530的外部中断

#导入Word文档图片# CC2530 外部中断配置说明

cc2530的I/O中断

CC2530的定时/计数器原理与应用

简述cc2530与8051单片机的区别

STM32外部中断用一根中断线怎样配置两个中断口,优先级设置