S.D.Lu的MSP430入门学习笔记(9):定时器TimerA(4)捕获功能

S.D.Lu的MSP430入门学习笔记(9):

定时器TimerA(4)捕获功能

本篇笔记介绍如何使用TimerA的捕获模式校准DCO、测量方波信号的频率/周期、脉宽和占空比。

对DCO时钟进行校准 对信号脉宽、占空比等参数的测量要求高频时钟。但是MSP430G2452的不支持外部高频时钟,所以不能使用外部高频晶振作为时钟源。内部数控时钟DCO就成了唯一选择。虽然TI在出厂时对MSP430的DCO进行了校准,保存了1MHz、8MHz、12MHz、16MHz这几个频率的校准值,但是由于工作环境的不同,会因为温度等因素的影响而产生较大的偏差。所以,在对时钟要求较高的设计中,最好对其进行再次校准。 对DCO进行校准的基本原理是用TimerA定时器的捕获/比较功能,进行两个频率的比较,然后根据比较结果调整DCO的输出,直到得到指定频率。具体方法是,使用外部的32768Hz晶振作为基准时钟源,使用TimerA的捕获功能对DCO的频率进行测量,然后通过DCOx、MODx和RSELx位来调节DCO的频率,直到其输出等于想要的频率。请看例程:

本例中,P1.4用于输出SMCLK,即DCOCLK,程序运行时,可以用示波器观察P1.4口的信号,以确认当前的DCOCLK频率。同时,在不同DCO频率下,可以观察到P1.0上的LED闪烁频率不同。在21~24行选择任意一行,屏蔽其它3行,可以得到16MHz、12MHz、8MHz、1MHz不同的DCOCLK频率。

函数void Set_DCO(unsigned int Delta);的作用就是设定DCO输出指定频率。应该注意的是,参数Delta的单位是4069Hz。

下面对该函数的代码进行分析。

37行,对LFXT1CLK进行8分频作为ACLK,因为本例中LFXT1使用外部32768Hz晶振,所以ACLK=32768Hz/8=4096Hz,这就是Delta的单位。

38行,将CCR0单元设置为捕获上升沿模式,信号输入为CCI0B,即ACLK=4096Hz。为什么CCI0B是ACLK呢?请查看MSP430G2452对应的数据手册。

39行,TimerA的时钟源选择SMCLK,即DCOCLK,这就是我们要测量的频率。选择连续计数模式,并清零计数器。

43行,等待,直到捕获发生。在此是通过查询TACCTL0的标志位CCIFG的方法确认捕获是否发生的。

44行,捕获发生之后,TACCTL0的CCIFG位置1。在此清零该位,以便下次捕获的识别。

45行,将本次捕获的值存入变量Compare。

46行,对本次捕获值和上次捕获值进行求差,并存入Compare。 47行,将本次捕获的值存入变量Oldcapture,作为下次求差的数据。

49-50行,如果相邻两次捕获的差值=要设定的值,则完成校准,退出41行的while(1)。 51-57行,如果相邻两次捕获的差值>要设定的值,说明DCO频率太高,通过DCOx、MODx和RSELx位来降低DCO的频率。

58-64行,如果相邻两次捕获的差值<要设定的值,说明DCO频率太低,通过DCOx、MODx和RSELx位来提高DCO的频率。

66-68行,在跳出41行的while(1)之后,对TACCTL0、TACTL、BCSCTL1这几个寄存器进行恢复初始值。

如果要将DCOCLK校准为4MHz该怎么操作呢?可参考例程中的做法,首先,定义一个数字常量宏DELTA_4MHZ,其值对应4MHz的参数,即4000000/4096≈977。然后在主函数中将Set_DCO(DELTA_1MHZ);换成Set_DCO(DELTA_4MHZ);即可,校准后DCO输出为977×4096≈4000.8kHz。

需要特别注意的是,由于DCO是以外部32786Hz晶振频率为基准的,所以DCO的精度不可能大于晶振频率的精度。不同的校准频率,输出的频率精度不同,输出频率越高,其精度越高。假设外部32768Hz晶振的频率精度可以忽略不计,则Set_DCO(Delta);函数校准后,DCO频率的精度为1/ Delta。频率误差是一样的,都是±4096Hz,即±一个Delta单位。

>>>用IO模拟发送串口数据

测量方波信号的频率/周期、脉宽和占空比时,需要有输出终端,通过串口发送数据到PC上显示是比较好的选择。所以在此插入一个用IO模拟发送串口数据的例子。使用USB转TTL串口线连接MCU和PC使硬件变得简洁。

因为MSP430G2452的片上外设并没有UART,所以需要通过其他的方法来实现UART的功能。本笔记只涉及到数据发送,所以用IO模拟UART时序发送数据是最简单的方法。

UART的基本数据格式如下图。

起始位是一个位宽的低电平;然后是8位数据,低位在前,高位在后;之后是一位校验位,该位也可以没有;最后是停止位,它是一个位宽的高电平,停止位的宽度也可以是1.5个或2个位宽。空闲时,数据线为高电平。

选定UART的通讯波特率之后,就可以知道其位宽。比如波特率为9600,那么其位宽约为104微秒。

我们在“DCO校准”的例子基础上修改,增加一个串口发送函数。如下图,主函数前面增加了两个宏定义和一个函数声明,主函数中增加一个变量,在while(1)增加串口发送数据的函数调用。void Set_DCO(unsigned int Delta)函数在主函数之后进行定义。

联系客服:779662525#qq.com(#替换为@) 苏ICP备20003344号-4