CC2530学习(三)CC2530中断系统以及一些点亮小灯实验

对中断的理解

首先我们知道内核与外设需要交互,那交互的方式有哪些呢?
了解过一些单片机或者操作系统等知识的应该能想到是:轮询中断

轮询其实就是由CPU定时发出询问,依序询问每一个周边设备是否需要其服务,有即给予服务,服务结束后再问下一个周边,接着不断周而复始。这样我们也就能想到轮询的方式貌似公平,实际工作效率很低,且不能及时响应紧急事件;

中断其实就是在执行CPU当前程序时,由于系统中出现了某种急需处理的情况,CPU暂停正在执行的程序,转而去执行另外一段特殊程序来处理出现的紧急事务,处理结束后,CPU自动返回到原来暂停的程序中去继续执行。

本次我们主要说说CC2530中断这种交互方式
有两个重要概念:
<1> 中断服务函数: 内核响应中断后执行的相应处理程序,即上面提到的特殊程序。
<2> 中断向量:中断服务程序的入口地址。每个中断源都对应一个固定的入口地址。当内核响应中断请求时,就会暂停当前的程序执行,然后跳转到该入口地址执行代码。

CC2530中断系统

CC2530具有18个中断源,每个中断源都由各自的一系列特殊功能寄存器来进行控制。可以编程设置相关特殊功能寄存器,设置18个中断源的优先级以及使能中断申请响应等。我们常用的中断源有下面几个:
CC2530学习(三)CC2530中断系统以及一些点亮小灯实验_第1张图片
大家也不需要将全部给记住,我们只需要将一些常用的记熟,然后对于其他的当遇见了网上查查资料就行了。

CC2530的中断处理函数

当发生中断请求,需要暂停CPU目前的工作转去执行另外一份特殊程序。而这个特殊程序就是我们所说的中断处理函数
中断服务函数与一般自定义函数不同,有特定的书写格式
CC2530学习(三)CC2530中断系统以及一些点亮小灯实验_第2张图片
<1> 在每一个中断服务函数之前,都要加上一句起始语句
#pragma vector = <中断向量>
<中断向量>表示接下来要写的中断服务函数是为那个中断源服务的,该语句有两种写法:
#pragma vector = 0x7B 或者 #pragma vector = P1INT_VECTOR
前者是中断向量的入口地址,后者是头文件**“ioCC2530.h”中的宏定义。
<2> _ _interrupt
关键字表示该函数是一个中断服务函数,<函数名称>可以 自定义,函数体 不能带有参数,也不能有返回值

CC2530的外部中断

CC2530的P0P1P2端口中的每个引脚都具有外部中断输入功能,要使某些引脚具有外部中断功能,需要对IENx寄存器、PxIEN寄存器和PICTL寄存器进行适当的设置。 除了各个中断源都有自己的中断使能开关之外,中断系统还有一个总开关,可以同“EA = 1;”来打开总中断。

中断产生后当然后有一个中断标志位来标志有中断产生。
P0、P1和P2端口分别使用P0IFP1IFP2IF作为中断标志位,任何一个端口组上的引脚产生外部中断时,都会将对应端口组的中断标志自动置位。注意,外部中断标志必须在中断服务函数中手工清除,否则CPU会反复进入中断。 端口状态标志寄存器P0IFGP1IGFP2IFG,分别对应3个端口中各引脚的中断触发状态,当某引脚发生外部中断触发时,对应的标志位会自动置位,这个标志同样需要手工清除。

对于这些中断寄存器的具体介绍就请大家参考这个博客吧
中断寄存器介绍

点小灯实验

依次点亮两灯

首先我们应该初始化led1(蓝灯),led2(黄灯)即设置以前讲过的PxSEL,PxDIR,PxINP等寄存器。
这里再次贴下流程图:
CC2530学习(三)CC2530中断系统以及一些点亮小灯实验_第3张图片
代码:

#include "led.h"
#include "delay.h"
#include "iocc2530.h"
void main(void)
{
  P1SEL &=~0x03;//设置两个led为通用io
  P1DIR |=0x03;//设置两个led为输出模式
  led1=1;//初始化小灯1亮
  led2=0;//初始化小灯2灭
  while(1)
  {
    led1=!led1;
    delay(30000);
    led2=!led2;
    delay(30000);
    
  }
}

具体的led1,led2的引脚定义我也定义在delay.h文件里面,具体的引脚需要大家根据芯片的硬件原理图进行定义。delay延迟函数我也在delay.h文件定义好了。延迟函数很简单大家网上可以搜搜。

按键实现亮灯效果

这个任务多了按键,其实也是一样,我们只需要多初始化一个按键为通用io,输入模式,三态就行。

亮灯效果:按一下蓝灯亮,黄灯灭;再按一下蓝灯灭,黄灯亮;再按一下两灯都亮;再按一下两灯都灭

代码:

#include "led.h"
#include "delay.h"
#include "iocc2530.h"
void main(void)
{
  uint count=0;
  uint temp=0;
  P1SEL &= ~0x04;//设置按键1 P1_2为通用io
  P1DIR &= ~0x04;//设置按键1 P1_2为输入模式
  P1INP |= 0x04;//设置为三态上拉模式

  P1SEL &=~0x03;//设置两个led为通用io
  P1DIR |=0x03;//设置两个led为输出模式
  
  led1=0;//初始化小灯1灭
  led2=0;//初始化小灯2灭
  
  while(1)
  {
    if(key1==0) //等待按键按下
    {
      delay(100);
      if(key1==0)  //消抖
      {
        while(key1==0);//等待按键松开
        count++; //记录按键次数
        temp=count%4;
      }
    }
    switch(temp)  //对按键取余
    {
    case 0:    //两个灯灭
      led1=0;
      //delay(30000);
      led2=0;
      //delay(30000);
      break;    
    case 1:    //小灯1亮小灯2灭
      led1=1;
      delay(30000);
      led2=0;
      delay(30000);
      break;
    case 2:    //小灯1灭小灯2亮
      led1=0;
      delay(30000);
      led2=1;
      delay(30000);
      break;
    case 3:    //两个灯亮
      led1=1;
      delay(30000);
      led2=1;
      delay(30000);
      break;
    }
  }
}

按键中断实现两灯效果

这次就是我们用今天所介绍的中断方式来实现亮灯效果

亮灯效果:按一下蓝灯亮,黄灯灭;再按一下蓝灯灭,黄灯亮;再按一下两灯都亮;再按一下两灯都灭

实现一个基本的中断功能我们所要完成的步骤有:

<1> 配置IENx寄存器,使能端口组的中断功能。
<2> 配置PxIEN寄存器,使能具体的外部中断引脚。
<3> 配置PICTL寄存器,设置中断触发方式
<4>设计外部中断服务函数
在编写中断服务函数的时候,书写格式要正确,中断向量不能搞错。特别要注意:在函数里面把端口组和引脚的标志位清除,否则CPU将会反复进入中断,必须清除引脚标志位PxIFG清除端口组标志位PxIF

代码:

#include "led.h"
#include "delay.h"
#include "iocc2530.h"

//外部中断1服务函数
#pragma vector=P1INT_VECTOR  //外部中断1的向量入口
__interrupt void led_show(void)
{
  int count=1;
  do{
      switch(count)  //对按键取余
        {
        case 1:    //小灯1亮小灯2灭
          led1=1;
          delay(50000);
          led2=0;
          delay(50000);
          break;
        case 2:    //小灯1灭小灯2亮
          led1=0;
          delay(50000);
          led2=1;
          delay(50000);
          break;
        case 3:    //两个灯亮
          led1=1;
          delay(50000);
          led2=1;
          delay(50000);
          break;
        case 4:    //两个灯灭
          led1=0;
          //delay(50000);
          led2=0;
          //delay(50000);
          break;    
        }
      delay(50000);
      count++;
  }while(count<=4);
  P1IFG &= ~0x04;//软件清除P1_2引脚标志位
  P1IF =0;//软件清除P1端口组的标志位
}
void main(void)
{
  
  P1SEL &= ~0x04;//设置按键1 P1_2为通用io
  P1INP |= 0x04;//设置为三态上拉模式
  P1IEN |= 0x04;//P1_2设置为中断方式
  PICTL |= 0x04;//下降沿触发
  
  EA=1;//打开总中断
  IEN2 |=0x10;//端口1中断使能
  P1IFG |=0x00;//初始化中断标志位

  P1SEL &=~0x03;//设置两个led为通用io
  P1DIR |=0x03;//设置两个led为输出模式
  
  led1=0;//初始化小灯1灭
  led2=0;//初始化小灯2灭
  while(1)
  {
    
  }
}

本次介绍就到这了,谢谢大家的观看!

你可能感兴趣的:(ZigBee)