两年前,使用MSP430写过不少程序,当然用的最多的就是MSP430G2553这款单片机了,但是昨天写一个简单的测量脉冲方波占空比的代码,不想却被这个小小代码狠狠的虐了一次。Timer定时器写的一塌糊涂,折腾了一个晚上,今天就重新回顾一下一些容易混淆的误区:
一、被测信号
被测信号可以直接连接到单片机引脚。但要注意几个问题
1、被测信号的电压,如果略高于单片机VCC可以通过引脚串联电阻分压方式解决,如果电压和VCC差别大需要有个电平转换电路(放大或缩小)
2、做捕获时,一般在单片机引脚上加上拉或者下拉电阻(根据捕获跳变沿,功耗等方面考虑进行选择)
3、利用施密特触发器将边缘缓慢变化的周期性信号变换为同频率的矩形脉冲,输入单片机时注意不要超过电源电压。
二、CM_0/ CM_1 / CM_2 / CM_3
写法注意:中间有一个下划线
通过CM_0/ CM_1 / CM_2 / CM_3 可以分别选择 不捕获 / 上升沿 / 下降沿 / 都捕获。举例来说如果捕获按键的时间间隔用上升沿或者下降沿就可以了,如果要记录红外遥控的数据则必须用CM_3才行。
三、TIMER0_A1_VECTOR ,TIMER0_A0_VECTOR等
msp430g2553有两个定时器,一个是Timer0,一个是Timer1。TIMER0_A1_VECTOR ,TIMER0_A0_VECTOR 是Timer0的中断向量,
在430中,CCR0中断与CCR1,CCR2,溢出中断没有在一个中断向量表中,两个是分开的。CCR0中断具有最高优先级,而其余三个在一个中断向量表中。Timer1也相同,所以就有4个中断向量。
MSP430中,不同的型号拥有不同的硬件配置,因此中断源也有所差别,TIMER1_A0_VECTOR表示定时器1 A0的中断源,1代表硬件上的定时器,有定时器0 定时器1等;A0代表定时器n内的A0寄存器,通常会有A0 A1等,他们都计数源都来自同一个定时器,但对计数源的数据可以进行不同的处理,从而产生不同的中断。
在M430G2553头文件中有如下定义
#define TIMER0_A1_VECTOR (8 * 2u) /* 0xFFF0 Timer0)A CC1, TA0 */ #define TIMER0_A0_VECTOR (9 * 2u) /* 0xFFF2 Timer0_A CC0 */ #define TIMER1_A1_VECTOR (12 * 2u) /* 0xFFF8 Timer1_A CC1-4, TA1 */ #define TIMER1_A0_VECTOR (13 * 2u) /* 0xFFFA Timer1_A CC0 */
可见,每个TimerA模块有两个中断向量
http://blog.lehu.shu.edu.cn/879836630/A450185.html
如果timerA值用作定时器,可以有三个定时器(TA、TACCR0和TACCR1),每个定时器有三种定时方式,有些定时器共用一个中断向量,TIMER0_A0_VECTOR专门为TACCR0配置,TA和TACCR1(对于timer1,还有TACCR2)共用TIMER0_A1_VECTOR,当多个中断同时发生,按优先级的先后顺序执行。
TIMER0_A0_VECTOR是计时器0的CCR0的中断寄存器,TIMER0_A1_VECTOR是计时器0的CCR1-CCR4、TA的寄存器
同理定时器TA1也是分为两个TIMER1_A0_VECTOR和TIMER1_A1_VECTOR
#pragma vector=TIMER0_A1_VECTOR __interrupt void TimerA(void) { switch(__even_in_range(TA0IV,14)) /* 这句话的意思是:只有在TA0IV的值是在0--14内的偶数时才会执行switch函数内的语句 其作用是提高switch语句的效率*/ { case 2:P1OUT=BIT1;break; //TACCR1 CCIFG置位,表明计数值和设定的13107相等了,也就是说计了0.4S了 case 4:P1OUT=BIT2;break; //TACCR2 CCIFG置位,表明计了0.8S了 case 6:P1OUT=BIT3;break; //TACCR3 CCIFG置位,表明计了1.2S了 case 8:P1OUT=BIT4;break; //TACCR4 CCIFG置位,表明计了1.6S了 case 14:P1OUT=BIT5;break; //TAIFG置位,表明计了2S了 default:break; } }
四、CCIS、CCIS_X设置
MSP430头文件内容如下:
#define CCIS1 (0x2000) /* Capture input select 1 */ #define CCIS0 (0x1000) /* Capture input select 0 */ #define CCIS_0 (0*0x1000u) /* Capture input select: 0 - CCIxA */ #define CCIS_1 (1*0x1000u) /* Capture input select: 1 - CCIxB */ #define CCIS_2 (2*0x1000u) /* Capture input select: 2 - GND */ #define CCIS_3 (3*0x1000u) /* Capture input select: 3 - Vcc */
注意:
1、CCIS1与CCIS_0有区别
2、CCIS_X是TACCTLX中的寄存机,关系到选择定时器“绑定”到某的IO口。
查看MSP430单片机用户中文手册就会发现
在用户手册端子功能描述中,已经比较详细的注明了某一个IO口对应哪一个CCIXA或CCIXB
如:P1.2 Timer0_A, 捕捉:CCI0A 输入
所以在自己设置捕获模式的寄存器的时候,通过设置CCIXA或B,就可以指定此定时器触发源从哪一个IO口作为信号输入。
五、捕获模式定时器IO口选择
1、选择定时器
以MSP430G2553为例,通过用户中文手册可知,此单片机有两个定时器TIMER0 和TIMER1
TIMER0对应的信号输入IO为上图TA0.X,TIMER0对应的信号输入IO为上图TA1.X.
明确这些信息之后,你就可以根据自己的需求选择你需要的定时器了。
2、IO口选择
请参考此文:CCIS、CCIS_X设置
通过查上表确定具体信号输入IO口,选择CCTLX中的CCIS_X寄存器,根据自己需求选择CCIXA或CCIXB即可。
六、CCR0、CCR1、CCR2设置
CCRx是捕获/比较寄存器
用做捕获时:捕获的同时TAR的值会传给CCRx,用来测算周期是很好的方法,一般捕获用法时无须设置参数。
用作比较时:CCR0一般用来设置输出电平的转换时机,就是TAR计数到CCR0时输出电平发生相应的变化(输出方式可以设置);也可以将CCR0设置为最大值,此时CCRx(x:1或2)用来设置输出电平转换的时机,即TAR计数到CCRx时输出电平转换,计数到CCR0时重新开始计数。