嵌入式成长轨迹44 【Zigbee项目】【CC2430基础实验】【定时器中断】
中断介绍
CPU 有18 个中断,每个中断源都有它自己的位于一系列特殊功能寄存器中的中断请求标志,中断分别组合为不同的,可以选择的优先级别。
中断屏蔽
每个中断请求可以通过设置特殊功能寄存器中特定位 IEN0,IEN1 或者IEN2,使能或禁止。某些外部设备会因为若干事件产生中断请求,这些中断请求可以作用在P0、P1、P2、DMA计数器1 、计数器 3 、计数器 4 或者RF上,对于每个内部中断源对应的特殊功能寄存器,这些外部设备都有中断屏蔽位。
为了使用CC2430中的中断功能,应当执行下列步骤;
1 、设置IEN0 中的EAL 位1 ;
2 、设置寄存器 IEN0、IEN1 合IEN2 中对应的中断使能位为1;
3 、如果有,则设置特殊功能寄存器中对应的各中断使能位为 1 ;
4 、在该中断对应的向量地址上,运行该中断的服务程序。
中断处理
当中断发生时,CPU 就指向中断向量。一旦中断服务开始,就只能够被更高优先级的中断打断;中断服务程序由中断指令 RETI终止,当RETI执行时,CPU 将返回到中断发生时的下一条指令。
当中断发生时,不管该中断使能或禁止,CPU 。都会在中断标志寄存器中设置中断标志位。当中断使能时,首先设置中断标志,然后在下一个指令周期,由硬件强行产生一个LCALL 到对应的向量地址,运行中断服务程序。
新中断的响应,取决于该中断发生时 CPU 的状态。当 CPU 正在运行的中断服务程序,其优先级大于或等于新的中断时,新的中断暂不运行,直至新的中断的优先级高于正在运行的中断服务程序。中断响应的时间取决于当前的指令,最快的为7 个机器指令周期,其中 1 个机器指令周期用于检测中断,其余6 个用来执行 LCALL。
中断优先级
中断组合成为6 个中断优先组,每组的优先级通过设置寄存器 IPO 和IP1 实现。为了给中断(也就是它所在的中断优先组)赋值优先级,需要设置 IP0) 和IP1 的对应位。
中断优先级及其赋值的中断源每组赋值为 4 个中断优先级之一。
当进行中断服务请求时,不允许被同级或较低级别的中断打断。当同时收到几个相同优先级的中断请求时,采取轮流检测顺序来判定哪个中断优先响应。
void Init_T4_AND_LED(void) ;
函数原型:
void Init_T4_AND_LED(void)
{
P1DIR = 0X03;
led1 = 1;
led2 = 1;
TIMER34_INIT(4); // 初始化T4
TIMER34_ENABLE_OVERFLOW_INT(4,1); // 开T4中断
TIMER34_SET_CLOCK_DIVIDE(4,128);
TIMER34_SET_MODE(4,0); //自动重装 00->0xff
TIMER34_START(4,1); //启动
};
函数功能:将 I/0 P10,P11 设置为输出去控制 LED ,将 T4设置为自动重装模式,定时器时钟 16分频,并启动T4。
void T4_ISR(void) ;
函数原型:
#pragma vector = T4_VECTOR
__interrupt void T4_ISR(void)
{
IRCON = 0x00; // 可不清中断标志, 硬件自动完成
if(counter<1000)counter++; //10 次中断LED 闪烁一轮
else
{
counter = 0; // 计数清零
GlintFlag = !GlintFlag; //GlintFalg = 1 ,LED 闪烁
}
}
函数功能:这是一个中断服务程序,每1000 次中断改变一次红色 LED 的状态。
开启溢出中断
#define TIMER34_ENABLE_OVERFLOW_INT(timer,val) \
do{T##timer##CTL = (val) ? T##timer##CTL | 0x08 : T##timer##CTL & ~0x08; \
EA = 1; \
T4IE = 1; \
}while(0)
功能:打开T4的溢出中断。
复位T4相关寄存器
#define TIMER34_INIT(timer) \
do { \
T##timer##CTL = 0x06; \
T##timer##CCTL0 = 0x00; \
T##timer##CC0 = 0x00; \
T##timer##CCTL1 = 0x00; \
T##timer##CC1 = 0x00; \
} while (0)
功能:将T4相关的寄存器复位到0
控制T4起停
#define TIMER#define TIMER34_START(timer,val) \
(T##timer##CTL = (val) ? T##tim er##CTL | 0X10 : T##timer##CTL&~0X10)
功能:timer 为定时器序号,只能取3 或4 。val 为1 ,定时器正常运行,val 为0 ,定时器停止计数
设置T4工作方式
#define TIMER3_SET_MODE(val) \
do{ \
T4CTL &= ~0X03; \
(val==1)?(T4CTL|=0X01): /*DOWN */ \
(val==2)?(T4CTL|=0X02): /*Modulo */ \
(val==3)?(T4CTL|=0X03): /*UP / DOWN */ \
(T4CTL|=0X00); /*free runing */ \
}while(0)
#define T4_MODE_FREE 0X00
#define T4_MODE_DOWN 0X01
#define T4_MODE_MODULO 0X02
#define T4_MODE _UP_DOWN 0X03
功能:根据val的值将T4设置为不同模式,一共4 种模式。
1 //main.c 2 #include <ioCC2430.h> 3 4 #define led1 P1_0 5 #define led2 P1_1 6 7 #define uchar unsigned char 8 #define uint unsigned int 9 10 /***************************************** 11 //定义全局变量 12 *****************************************/ 13 uint counter = 0; 14 uchar GlintFlag = 0; 15 16 /***************************************** 17 //函数声明 18 *****************************************/ 19 void Delay(uint n); 20 void Init_T4_AND_LED(void); 21 22 /***************************************** 23 //T3配置定义 24 *****************************************/ 25 // Where _timer_ must be either 3 or 4 26 // Macro for initialising timer 3 or 4 27 #define TIMER34_INIT(timer) \ 28 do { \ 29 T##timer##CTL = 0x06; \ 30 T##timer##CCTL0 = 0x00; \ 31 T##timer##CC0 = 0x00; \ 32 T##timer##CCTL1 = 0x00; \ 33 T##timer##CC1 = 0x00; \ 34 } while (0) 35 36 //Macro for enabling overflow interrupt 37 #define TIMER34_ENABLE_OVERFLOW_INT(timer,val) \ 38 (T##timer##CTL = (val) ? T##timer##CTL | 0x08 : T##timer##CTL & ~0x08) 39 40 41 42 // Macro for configuring channel 1 of timer 3 or 4 for PWM mode. 43 #define TIMER34_PWM_CONFIG(timer) \ 44 do{ \ 45 T##timer##CCTL1 = 0x24; \ 46 if(timer == 3){ \ 47 if(PERCFG & 0x20) { \ 48 IO_FUNC_PORT_PIN(1,7,IO_FUNC_PERIPH); \ 49 } \ 50 else { \ 51 IO_FUNC_PORT_PIN(1,4,IO_FUNC_PERIPH); \ 52 } \ 53 } \ 54 else { \ 55 if(PERCFG & 0x10) { \ 56 IO_FUNC_PORT_PIN(2,3,IO_FUNC_PERIPH);\ 57 } \ 58 else { \ 59 IO_FUNC_PORT_PIN(1,1,IO_FUNC_PERIPH); \ 60 } \ 61 } \ 62 } while(0) 63 64 // Macro for setting pulse length of the timer in PWM mode 65 #define TIMER34_SET_PWM_PULSE_LENGTH(timer, value) \ 66 do { \ 67 T##timer##CC1 = (BYTE)value; \ 68 } while (0) 69 70 71 // Macro for setting timer 3 or 4 as a capture timer 72 #define TIMER34_CAPTURE_TIMER(timer,edge) \ 73 do{ \ 74 T##timer##CCTL1 = edge; \ 75 if(timer == 3){ \ 76 if(PERCFG & 0x20) { \ 77 IO_FUNC_PORT_PIN(1,7,IO_FUNC_PERIPH); \ 78 } \ 79 else { \ 80 IO_FUNC_PORT_PIN(1,4,IO_FUNC_PERIPH); \ 81 } \ 82 } \ 83 else { \ 84 if(PERCFG & 0x10) { \ 85 IO_FUNC_PORT_PIN(2,3,IO_FUNC_PERIPH); \ 86 } \ 87 else { \ 88 IO_FUNC_PORT_PIN(1,1,IO_FUNC_PERIPH); \ 89 } \ 90 } \ 91 }while(0) 92 93 //Macro for setting the clock tick for timer3 or 4 94 #define TIMER34_START(timer,val) \ 95 (T##timer##CTL = (val) ? T##timer##CTL | 0X10 : T##timer##CTL&~0X10) 96 97 #define TIMER34_SET_CLOCK_DIVIDE(timer,val) \ 98 do{ \ 99 T##timer##CTL &= ~0XE0; \ 100 (val==2) ? (T##timer##CTL|=0X20): \ 101 (val==4) ? (T##timer##CTL|=0x40): \ 102 (val==8) ? (T##timer##CTL|=0X60): \ 103 (val==16)? (T##timer##CTL|=0x80): \ 104 (val==32)? (T##timer##CTL|=0xa0): \ 105 (val==64) ? (T##timer##CTL|=0xc0): \ 106 (val==128) ? (T##timer##CTL|=0XE0): \ 107 (T##timer##CTL|=0X00); /* 1 */ \ 108 }while(0) 109 110 //Macro for setting the mode of timer3 or 4 111 #define TIMER34_SET_MODE(timer,val) \ 112 do{ \ 113 T##timer##CTL &= ~0X03; \ 114 (val==1)?(T##timer##CTL|=0X01): /*DOWN */ \ 115 (val==2)?(T##timer##CTL|=0X02): /*Modulo */ \ 116 (val==3)?(T##timer##CTL|=0X03): /*UP / DOWN */ \ 117 (T##timer##CTL|=0X00); /*free runing */ \ 118 }while(0) 119 120 121 /***************************************** 122 //T3及LED初始化 123 *****************************************/ 124 void Init_T4_AND_LED(void) 125 { 126 P1DIR = 0X03; 127 led1 = 1; 128 led2 = 1; 129 130 TIMER34_INIT(4); //初始化T4 131 TIMER34_ENABLE_OVERFLOW_INT(4,1); //开T4中断 132 EA = 1; 133 T4IE = 1; 134 135 //T4CTL |= 0XA0; //时钟128分频101 136 TIMER34_SET_CLOCK_DIVIDE(4,128); 137 TIMER34_SET_MODE(4,0); //自动重装00->0xff 138 T4CC0 = 0Xf0; 139 TIMER34_START(4,1); //启动 140 }; 141 142 /***************************************** 143 //主函数 144 *****************************************/ 145 void main(void) 146 { 147 Init_T4_AND_LED(); 148 while(1) 149 { 150 if(GlintFlag == 1)led1 = !led1; //改变小灯的状态 151 Delay(4000); 152 }; 153 } 154 155 /***************************************** 156 //延时 157 *****************************************/ 158 void Delay(uint n) 159 { 160 uint ii; 161 for(ii=0;ii<n;ii++); 162 for(ii=0;ii<n;ii++); 163 for(ii=0;ii<n;ii++); 164 for(ii=0;ii<n;ii++); 165 for(ii=0;ii<n;ii++); 166 } 167 168 #pragma vector = T4_VECTOR 169 __interrupt void T4_ISR(void) 170 { 171 IRCON = 0x00; //可不清中断标志,硬件自动完成 172 //led2 = 0; //for test 173 if(counter<1000)counter++; //10次中断LED闪烁一轮 174 else 175 { 176 counter = 0; //计数清零 177 GlintFlag = !GlintFlag; 178 } 179 }