Zigbee之旅(三):几个重要的CC2430基础实验——外部中断

本文介绍了基于CC2430芯片的外部中断实验,通过按键触发P0.1中断并控制LED灯的亮灭。文章详细解析了实验原理、流程图以及源码,并总结了中断使能及位赋值语法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Zigbee之旅(三):几个重要的CC2430基础实验——外部中断

一、承上启下

  上一讲,我们通过一个最简单的LED闪烁小实验,熟悉了IAR开发CC2430程序的基本过程。刀好歹磨过了(虽然我这块磨刀石不咋地),现在就开始屠虫了:)。接下来,我们一起来学习几个CC2430的基础实验。每个小实验,分“实验简介”、“程序流程图”,“实验源码及剖析”三个部分阐述。

  本篇讲解外部中断。

二、外部中断

(1)实验简介

  中断是单片机实时地处理内部或外部事件的一种内部机制。当某种内部或外部事件发生时,单片机的中断系统将迫使CPU暂停正在执行的程序,转而去进行中断事件的处理,中断处理完毕后,又返回被中断的程序处,继续执行下去。

  中断分外部中断和内部中断,CC2430共包含18个中断源(具体中断描述及中断向量的定义,可参考《CC2430中文手册》)。

  现在我们来看一下本开发板的电路图:

  开发板上已把S1按键与P0.1相连,本实验想要达到的效果就是,通过按键S1触发P0.1的中断,进而在中断服务子程序中控制LED1的亮/灭。

(2)实验原理及流程图

  实验流程图如下:

  

(3)实验源码

//头文件
#include <ioCC2430.h>

//延时子函数
#define  led1 P1_0
#define  led2 P1_1
#define  led3 P1_2
#define  led4 P1_3

void  Delay( unsigned n)   
{
   unsigned  tt;
   for( tt  =  0; tt <n; tt ++);
   for( tt  =  0; tt <n; tt ++);
   for( tt  =  0; tt <n; tt ++);
   for( tt  =  0; tt <n; tt ++);
   for( tt  =  0; tt <n; tt ++);
}

//32M晶振初始化
void  xtal_init( void)
{
   SLEEP  &=  ~ 0x04;              //都上电
   while( !( SLEEP  &  0x40));      //晶体振荡器开启且稳定
   CLKCON  &=  ~ 0x47;            // 选择32MHz 晶体振荡器
   SLEEP  |=  0x04;
}

//LED灯初始化
void  led_init( void)
{
   P1SEL   =  0x00;           //P1为普通 I/O 口
   P1DIR  |=  0x0F;           //P1.0 P1.1 P1.2 P1.3 输出
  
   led1  = 0;
   led2  =  0;
   led3  =  0;
   led4  =  0;
}

//io及外部中断初始化
void  io_init( void)
{
     P0INP  &=  ~ 0 X02;    //P0.1有上拉、下拉

     EA  =  1;            //总中断使能
    
    P0IE  =  1;    //P0中断使能
    
     PICTL  |=   0 X09;    //P0.1口中断使能,下降沿触发
    
     P0IFG  &=  ~ 0x02;    //P0.1中断标志清0
};

//主函数
void  main( void)    
{
   xtal_init();
   led_init();  
   io_init();

   while( 1);     //等待中断
}

//中断服务子程序
#pragma vector = P0INT_VECTOR
__interrupt  void  P0_ISR( void)
{
   EA  =  0;                          //关中断  

   Delay( 10000);  
   Delay( 10000);
   Delay( 10000);
   Delay( 10000);
   Delay( 10000);

   if(( P0IFG  &  0x02 )  > 0 )          //按键中断
   {
     P0IFG  &=  ~ 0x02;                //P0.1中断标志清0
     led1  =  ! led1;
   }
   P0IF  =  0;                        //P0中断标志清0

   EA  =  1;                          //开中断
}

  首先初始化统时钟:选用32MHz晶体振荡器。

  然后初始化LED:设置P1为通用I/O口,设置 P1.0 ~ P1.3 方向为输出,然后关闭4个LED灯。

  再来配置外部中断的相关SFR寄存器,开启各级中断使能,涉及3个SFR:EA、IEN1、PICTL(各SFR详细介绍请查阅《CC2430中文手册》):

    EA —— 总中断使能;

    IEN1.5 —— P0中断使能;

    PICTL.3 —— P0.1口中断使能;

    PICTL.0 —— 设置P0.1口输入下降沿引起中断触发。

  然后在主函数中使用 while(1) 等待中断即可。

CC2430 小贴士

(1)位赋值语法小结

  很多时候,我们需要对单字节的SFR中的某一位赋值(0或1),以精确控制硬件设备。

  有的SFR支持位寻址,比如说TCON、P0等,此时,对位的赋值非常简单,只需查询 ioCC2430.h 头文件中 SFR Bit Access 部分的位定义即可:

  P0_0 = 0; //对P0第一位赋值0

  P0_0 = 1; //对P0第一位赋值1  

  但有的SFR并不支持位寻址,就如本实验中的 PICTL,此时想要对其中的某一位赋值,语法如下:

  PICTL &= ~0x01;   //对第1位赋值0

  PICTL |= 0x01;     //对第1位赋值1

  大家可以记住 &= ~,|= 这两个常用的位赋值语法。

(2)中断使能小结

  在程序中涉及到某中断时,必须在触发中断前使能此中断。

  C51的中断使能系统,其层次结构非常明显:

  中断老大:EA 是老大,负责总的中断使能:

  EA = 1;

  各中断分队队长:接下来是针对每一个功能部件(如P0、定时器1等)的使能控制,此类SFR一般可位寻址,命名中一般含有 IE(Interrupt Enable):

  P0IE = 1;

  各中断队员:分队但由于每个功能部件内部也含有多个中断,所以最后一级就是针对这每一个中断的使能控制,此类SFR一般不可位寻址,命名中一般含有IE(Interrupt Enable)或 IM(Interrupt Mask):

  PICTL |=0x01;

  不需死记硬背中断SFR,只要了解其层次结构,然后用时查询手册或头文件即可。

(3)中断程序的编写

  在一个程序中使用中断,一般包括、两个部分:中断服务子程序的编写、中断使能的开启。中断使能已在上面介绍过,下面简单介绍一下中断服务子程序的编写:

  首先指定中断向量,可以在 ioCC2430.h 头文件中的 Interrupt Vectors 部分查询,语法如下:

  #pragma vector = 中断向量

   然后紧跟着编写中断处理程序,结构如下:

  __interrupt void 函数名(void)

  {

    //开中断

    //中断处理

    //中断标志清0

    //关中断

  }

三、结语

  本篇介绍了基于CC2430的简单的外部中断的实现方法,有了中断的基础之后,接下来我们介绍另外一个非常重要的模块——定时器。CC2430共有4个定时器,可分三类:定时器1、定时器2、定时器3/4(3与4的用法基本一样)。

转载于:https://www.cnblogs.com/leytton/p/8253341.html

CC2430 的应用开发中,定时器中断是非常常用的一个功能。下面我们将介绍几个关于定时器中断基础实验。 ## 实验一:定时器中断实验 ### 实验目的 了解 CC2430 的定时器模块,并掌握其中断的使用方法。 ### 实验原理 CC2430 的定时器模块有个定时器:T1、T2 和 T3。其中,T1 和 T2 是 16 位的定时器,T3 是 8 位的定时器。在本实验中,我们将以 T1 定时器为例,介绍定时器中断的使用方法。 T1 定时器的计数器是一个 16 位的寄存器,它可以通过以下寄存器进行配置: - T1CC0H/T1CC0L:T1 的比较器 0,可以用来产生比较中断。 - T1CC1H/T1CC1L:T1 的比较器 1,可以用来产生比较中断。 - T1CC2H/T1CC2L:T1 的比较器 2,可以用来产生比较中断。 - T1IE:T1 中断使能寄存器,用来使能 T1 的中断。 - T1CTL:T1 控制寄存器,用来配置 T1 的计数模式、时钟源等参数。 在本实验中,我们将使用 T1 的比较器 0,配置为每隔 1 秒钟产生一次中断。 ### 实验步骤 1. 配置 T1 的计数模式、时钟源等参数。 ```c T1CTL |= 0x0C; // T1 计数模式为比较器模式 T1CTL &= ~0x03; // T1 时钟源为时钟源选择寄存器 CLKCON 的 CLKSPD 位所选择的时钟源 T1CTL &= ~0x30; // T1 比较器模式为单次比较模式 ``` 2. 配置 T1 的比较器 0。 ```c T1CC0L = 0x00; // T1 的比较器 0 的低 8 位 T1CC0H = 0x80; // T1 的比较器 0 的高 8 位 ``` 3. 使能 T1 的中断。 ```c T1IE = 1; // 使能 T1 的中断 ``` 4. 在主函数中进入循环,等待定时器中断的触发。 ```c while(1); ``` 5. 在定时器中断服务函数中处理中断事件。 ```c #pragma vector = T1_VECTOR __interrupt void T1_ISR(void) { T1IF = 0; // 清除 T1 中断标志 // 中断处理代码 } ``` ### 实验结果 当程序运行后,每隔 1 秒钟会触发一次定时器中断。在中断服务函数中可以添加相应的处理代码,实现定时器中断的功能。 ## 实验二:定时器中断实现 LED 闪烁 ### 实验目的 通过定时器中断实现 LED 的闪烁。 ### 实验原理 在上一个实验中,我们已经学习了如何使用定时器中断。在本实验中,我们将以 T1 定时器为例,通过定时器中断实现 LED 的闪烁。 在本实验中,我们将使用 P0.0 引脚控制 LED 的状态。LED 亮时,P0.0 输出低电平;LED 灭时,P0.0 输出高电平。我们可以通过改变 P0.0 引脚的电平状态,实现 LED 的闪烁。 ### 实验步骤 1. 配置 P0.0 引脚为输出模式。 ```c P0SEL &= ~0x01; // P0.0 引脚配置为 GPIO 模式 P0DIR |= 0x01; // P0.0 引脚配置为输出模式 ``` 2. 配置 T1 的计数模式、时钟源等参数。 ```c T1CTL |= 0x0C; // T1 计数模式为比较器模式 T1CTL &= ~0x03; // T1 时钟源为时钟源选择寄存器 CLKCON 的 CLKSPD 位所选择的时钟源 T1CTL &= ~0x30; // T1 比较器模式为单次比较模式 ``` 3. 配置 T1 的比较器 0。 ```c T1CC0L = 0x00; // T1 的比较器 0 的低 8 位 T1CC0H = 0x80; // T1 的比较器 0 的高 8 位 ``` 4. 使能 T1 的中断。 ```c T1IE = 1; // 使能 T1 的中断 ``` 5. 在定时器中断服务函数中处理中断事件,改变 P0.0 引脚的电平状态。 ```c #pragma vector = T1_VECTOR __interrupt void T1_ISR(void) { T1IF = 0; // 清除 T1 中断标志 P0_0 = ~P0_0; // P0.0 引脚电平状态取反 } ``` 6. 在主函数中进入循环,等待定时器中断的触发。 ```c while(1); ``` ### 实验结果 当程序运行后,LED 会以 1 秒钟的频率闪烁。如果需要改变 LED 闪烁的频率,可以通过修改 T1 的比较器 0 的值来实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值