嵌入式成长轨迹43 【Zigbee项目】【CC2430基础实验】【T4的使用】
CC2430/CC2431 包括四个定时器:一个一般的 16 位(Timer 1) 和两个8 位(Timer3,4)定时器,支持典型的定时/ 计数功能,例如测量时间间隔,对外部事件计数,产生周期性中断请求,输入捕捉、比较输出和PWM 功能。一个 16 位MAC定时器(Timer 2),用以为IEEE802.15.4 的CSMA-CA 算法提供定时以及为IEEE802.15.4 的MAC层提供定时。
本实验使用T4,输入捕捉、比较输出和PWM 功能。
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
P2SEL (0xF5) – Port 2 Function Select
P2SEL |= 0x02;
7 - 0 R0 Not used
6 PRI3P1
Port 1 peripheral priority control. These bits shall determine the order of priority in the case when PERCFG assigns USART0 and USART1 to the same pins.
0 USART0 has priority
1 USART1 has priority
5 PRI2P1
Port 1 peripheral priority control. These bits shall determine the order of priority in the case when PERCFG assigns USART1 and timer 3 to the same pins.
0 USART1 has priority
1 Timer 3 has priority
4 PRI1P1
Port 1 peripheral priority control. These bits shall determine the order of priority in the case when PERCFG assigns timer 1 and timer 4 to the same pins.
0 Timer 1 has priority
1 Timer 4 has priority
3 PRI0P1 0 R/W
Port 1 peripheral priority control. These bits shall determine the order of priority in the case when PERCFG assigns USART0 and timer 1 to the same pins.
0 USART0 has priority
1 Timer 1 has priority
2 SELP2_4 P2_4 function select
0 General purpose I/O
1 Peripheral function
1 SELP2_3 P2_3 function select
0 General purpose I/O
1 Peripheral function
0 SELP2_0 P2_0 function select
0 General purpose I/O
1 Peripheral function
PERCFG (0xF1) – Peripheral Control
0x20
7 - 0 R0 Not used
6 T1CFG Timer 1 I/O location
0 Alternative 1 location
1 Alternative 2 location
5 T3CFG Timer 3 I/O location
0 Alternative 1 location
1 Alternative 2 location
4 T4CFG Timer 4 I/O location
0 Alternative 1 location
1 Alternative 2 location
3:2 -Not used
1 U1CFG USART1 I/O location
0 Alternative 1 location
1 Alternative 2 location
0 U0CFG USART0 I/O location
0 Alternative 1 location
1 Alternative 2 location
while(!XOSC_STABLE); \
asm("NOP");
NOP指令即“空指令”,在x86的CPU中机器码为0x90(144)。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令,所以NOP指令自然也会占用执行一个指令的CPU时间片。 常用于程序延时或精确计时,不过在较快的CPU上不明显。 主要作用:
1、字节填充对齐
2、精确延时和计时
3、破解程序的call验证
4、等待其他设备执行完毕
5、清除由上一个算术逻辑指令设置的flag位
6、辅助jmp、call等指令
使用PWM应调用:
TIMER34_PWM_CONFIG(timer)// Macro for configuring channel 1 of timer 3 or 4 for PWM mode.
TIMER34_SET_PWM_PULSE_LENGTH(timer, value) // Macro for setting pulse length of the timer in PWM mode
想试着用一次PWM的……可是灯一直不亮……
先放一个T4的计数触发,以后再来收拾——
1 //emot.h 2 3 #ifndef EMOT_H 4 #define EMOT_H 5 6 #include <iocc2430.h> 7 8 typedef unsigned int WORD; 9 typedef unsigned char BYTE; 10 typedef WORD UINT16; 11 12 /***************************************** 13 //IO功能定义 14 *****************************************/ 15 #define IO_FUNC_PORT_PIN(port, pin, func) \ 16 do { \ 17 if((port == 2) && (pin == 3)){ \ 18 if (func) { \ 19 P2SEL |= 0x02; \ 20 } else { \ 21 P2SEL &= ~0x02; \ 22 } \ 23 } \ 24 else if((port == 2) && (pin == 4)){ \ 25 if (func) { \ 26 P2SEL |= 0x04; \ 27 } else { \ 28 P2SEL &= ~0x04; \ 29 } \ 30 } \ 31 else{ \ 32 if (func) { \ 33 P##port##SEL |= (0x01<<(pin)); \ 34 } else { \ 35 P##port##SEL &= ~(0x01<<(pin));\ 36 } \ 37 } \ 38 } while (0) 39 40 // where func is one of: 41 #define IO_FUNC_GIO 0 // General purpose I/O 42 #define IO_FUNC_PERIPH 1 // Peripheral function 43 44 45 46 47 /***************************************** 48 //时钟定义 49 *****************************************/ 50 // Macro for getting the clock division factor 51 #define CLKSPD (CLKCON & 0x07) 52 53 // Macro for getting the timer tick division factor. 54 #define TICKSPD ((CLKCON & 0x38) >> 3) 55 56 // Macro for checking status of the crystal oscillator 57 #define XOSC_STABLE (SLEEP & 0x40) 58 59 // Macro for checking status of the high frequency RC oscillator. 60 #define HIGH_FREQUENCY_RC_OSC_STABLE (SLEEP & 0x20) 61 62 //macro for setting CLKCON.TICKSPD 63 #define SET_TICKSPD_DIVIDE(val) do{CLKCON &= ~0X38 ; CLKCON |= (unsigned char)(val);}while(0) 64 /* 65 // Where _val_ is one of 66 #define 32M_TICK 0x00 67 #define 16M_TICK 0x08 68 #define 8M_TICK 0x10 69 #define 4M_TICK 0x18 70 #define 2M_TICK 0x20 71 #define 1M_TICK 0x28 72 #define 0_5M_TICK 0x30 73 #define 0_2_5M_TICK 0x38 74 */ 75 76 77 // Macro for setting the 32 KHz clock source 78 #define SET_32KHZ_CLOCK_SOURCE(source) \ 79 do { \ 80 if( source ) { \ 81 CLKCON |= 0x80; \ 82 } else { \ 83 CLKCON &= ~0x80; \ 84 } \ 85 } while (0) 86 87 // Where _source_ is one of 88 #define CRYSTAL 0x00 89 #define RC 0x01 90 91 // Macro for setting the main clock oscillator source, 92 //turns off the clock source not used 93 //changing to XOSC will take approx 150 us 94 #define SET_MAIN_CLOCK_SOURCE(source) \ 95 do { \ 96 if(source) { \ 97 CLKCON |= 0x40; \ 98 while(!HIGH_FREQUENCY_RC_OSC_STABLE); \ 99 if(TICKSPD == 0){ \ 100 CLKCON |= 0x08; \ 101 } \ 102 SLEEP |= 0x04; \ 103 } \ 104 else { \ 105 SLEEP &= ~0x04; \ 106 while(!XOSC_STABLE); \ 107 asm("NOP"); \ 108 CLKCON &= ~0x47; \ 109 SLEEP |= 0x04; \ 110 } \ 111 }while (0) 112 113 114 /***************************************** 115 //T4配置定义 116 *****************************************/ 117 // Where _timer_ must be either 3 or 4 118 // Macro for initialising timer 3 or 4 119 #define TIMER34_INIT(timer) \ 120 do { \ 121 T##timer##CTL = 0x06; \ 122 T##timer##CCTL0 = 0x00; \ 123 T##timer##CC0 = 0x00; \ 124 T##timer##CCTL1 = 0x00; \ 125 T##timer##CC1 = 0x00; \ 126 } while (0) 127 128 //Macro for enabling overflow interrupt 129 #define TIMER34_ENABLE_OVERFLOW_INT(timer,val) \ 130 do{ (T##timer##CTL = (val) ? T##timer##CTL | 0x08 : T##timer##CTL & ~0x08); \ 131 EA = 1; \ 132 T##timer##IE = 1; \ 133 }while(0) 134 135 // Macros for configuring IO peripheral location: 136 #define IO_PER_LOC_TIMER4_AT_PORT1_PIN01() do { PERCFG = (PERCFG&~0x10)|0x00; } while (0) 137 #define IO_PER_LOC_TIMER4_AT_PORT2_PIN03() do { PERCFG = (PERCFG&~0x10)|0x10; } while (0) 138 139 // Actual MCU pin configuration: 140 // 141 // Peripheral I/O signal Alt1 Alt2 142 // ------------------------------------------- 143 // Timer4 channel0 P1.0 P2.0 144 // Timer4 channel1 P1.1 P2.3 145 146 147 // Macro for enabling/ disabling interrupts from the channels of timer 1, 3 or 4. 148 #define TIMER_CHANNEL_INTERRUPT_ENABLE(timer, channel, value) \ 149 do{ \ 150 if(value){ \ 151 T##timer##CCTL##channel## |= 0x40; \ 152 } else { \ 153 T##timer##CCTL##channel## &= ~0x40; \ 154 } \ 155 } while(0) 156 157 158 159 160 // Macro for configuring channel 1 of timer 3 or 4 for PWM mode. 161 #define TIMER34_PWM_CONFIG(timer) \ 162 do{ \ 163 T##timer##CCTL1 = 0x24; \ 164 if(timer == 3){ \ 165 if(PERCFG & 0x20) { \ 166 IO_FUNC_PORT_PIN(1,7,IO_FUNC_PERIPH); \ 167 } \ 168 else { \ 169 IO_FUNC_PORT_PIN(1,4,IO_FUNC_PERIPH); \ 170 } \ 171 } \ 172 else { \ 173 if(PERCFG & 0x10) { \ 174 IO_FUNC_PORT_PIN(2,3,IO_FUNC_PERIPH);\ 175 } \ 176 else { \ 177 IO_FUNC_PORT_PIN(1,1,IO_FUNC_PERIPH); \ 178 } \ 179 } \ 180 } while(0) 181 182 183 184 185 // Macro for setting pulse length of the timer in PWM mode 186 #define TIMER34_SET_PWM_PULSE_LENGTH(timer, value) \ 187 do { \ 188 T##timer##CC1 = (BYTE)value; \ 189 } while (0) 190 191 192 // Macro for setting timer 3 or 4 as a capture timer 193 #define TIMER34_CAPTURE_TIMER(timer,edge) \ 194 do{ \ 195 T##timer##CCTL1 = edge; \ 196 if(timer == 3){ \ 197 if(PERCFG & 0x20) { \ 198 IO_FUNC_PORT_PIN(1,7,IO_FUNC_PERIPH); \ 199 } \ 200 else { \ 201 IO_FUNC_PORT_PIN(1,4,IO_FUNC_PERIPH); \ 202 } \ 203 } \ 204 else { \ 205 if(PERCFG & 0x10) { \ 206 IO_FUNC_PORT_PIN(2,3,IO_FUNC_PERIPH); \ 207 } \ 208 else { \ 209 IO_FUNC_PORT_PIN(1,1,IO_FUNC_PERIPH); \ 210 } \ 211 } \ 212 }while(0) 213 214 //Macro for setting the clock tick for timer3 or 4 215 #define TIMER34_START(timer,val) \ 216 (T##timer##CTL = (val) ? T##timer##CTL | 0X10 : T##timer##CTL&~0X10) 217 218 #define TIMER34_SET_CLOCK_DIVIDE(timer,val) \ 219 do{ \ 220 T##timer##CTL &= ~0XE0; \ 221 (val==2) ? (T##timer##CTL|=0X20): \ 222 (val==4) ? (T##timer##CTL|=0x40): \ 223 (val==8) ? (T##timer##CTL|=0X60): \ 224 (val==16)? (T##timer##CTL|=0x80): \ 225 (val==32)? (T##timer##CTL|=0xa0): \ 226 (val==64) ? (T##timer##CTL|=0xc0): \ 227 (val==128) ? (T##timer##CTL|=0XE0): \ 228 (T##timer##CTL|=0X00); /* 1 */ \ 229 }while(0) 230 231 //Macro for setting the mode of timer3 or 4 232 #define TIMER34_SET_MODE(timer,val) \ 233 do{ \ 234 T##timer##CTL &= ~0X03; \ 235 (val==1)?(T##timer##CTL|=0X01): /*DOWN */ \ 236 (val==2)?(T##timer##CTL|=0X02): /*Modulo */ \ 237 (val==3)?(T##timer##CTL|=0X03): /*UP / DOWN */ \ 238 (T##timer##CTL|=0X00); /*free runing */ \ 239 }while(0) 240 #define T4_MODE_FREE 0X00 241 #define T4_MODE_DOWN 0X01 242 #define T4_MODE_MODULO 0X02 243 #define T4_MODE_UP_DOWN 0X03 244 245 //macro for setting the compare value of timer3 or 4 246 #define TIMER34_SET_CPM_VALUE(timer,channel,val) \ 247 do{ T##timer##CC##channel## = (unsigned int)(val); }while(0) 248 // Where _timer_ must be either 3 or 4 249 // Where _channel_ must be either 1 or 2 250 251 252 /********************************************************************* 253 //键盘定义 254 *********************************************************************/ 255 #define KEY1 P1_2 256 #define KEY2 P1_3 257 258 #define ENABLE_KEY_ON_BOARD() \ 259 do{ \ 260 P1SEL &= ~0X0C; \ 261 P1DIR &= ~0X0C; \ 262 P1INP |= 0x0c; \ 263 }while(0) 264 265 266 #endif //emot.h
1 //main.c 2 #include "emot.h" 3 4 #define led1 P1_0 5 #define led2 P1_1 6 7 #define uchar unsigned char 8 9 /***************************************** 10 //定义全局变量 11 *****************************************/ 12 uchar counter = 0; 13 14 /***************************************** 15 //T4及LED初始化 16 *****************************************/ 17 void Init_T4_AND_LED(void) 18 { 19 P1DIR = 0X03; 20 led1 = 1; 21 led2 = 1; 22 23 TIMER34_INIT(4); //初始化T4 24 TIMER34_ENABLE_OVERFLOW_INT(4,1); //开T4中断 25 26 TIMER34_SET_CLOCK_DIVIDE(4,128); 27 TIMER34_SET_MODE(4,0); //自动重装00->0xff 28 29 TIMER34_START(4,1); //启动 30 }; 31 32 void main(void) 33 { 34 Init_T4_AND_LED(); //初始化LED和T4 35 while(1); //等待中断 36 } 37 38 39 #pragma vector = T4_VECTOR 40 __interrupt void T4_ISR(void) 41 { 42 IRCON = 0x00; //可不清中断标志,硬件自动完成 43 //led2 = 0; //for test 44 if(counter<200)counter++; //200次中断LED闪烁一轮 45 else 46 { 47 counter = 0; //计数清零 48 led2 = led1; 49 led1 = !led1; //改变小灯的状态 50 } 51 }