现在在做的温控部分算法,需要每隔0.25s采集一次温度数据,然后计算出相应的控制量,并以PWM的形式输出。为了实现这个功能,时钟系统是不可或缺的,现就MSP430F5438A的时钟系统进行研究。
MSP430F5438A 里面有三个计时器,如下图所示
这三个计时器为TA0,TA1,TB0。TA0有5个capture/compare 寄存器, TA1有3个, TB0 有7个。
TA0 is a 16-bit timer/counter (Timer_A type) with five capture/compare registers. It can support multiple capture/compares, PWM outputs, and interval timing. It also has extensive interrupt capabilities. Interrupts may be generated from the counter on overflow conditions and from each of the capture/compare registers.
也就是说TA0计时器可以实现计时功能,也可以产生大量的中断,这些中断可以来自于计数器的溢出和每一个capture/compare寄存器。
好了,现在可以来深入了解这些东西了。
Timer_A features include:
• Asynchronous 16-bit timer/counter with four operating modes
• Selectable and configurable clock source
• Up to seven configurable capture/compare registers
• Configurable outputs with pulse width modulation (PWM) capability
• Asynchronous input and output latching
• Interrupt vector register for fast decoding of all Timer_A interrupts
就像其他的模块一样,Timer_A模块同样需要选择时钟,也需要选择模式。这些都需要寄存器的控制,现将一些主要的寄存器列在下面:
(1) TAxCTL : 定时器控制寄存器。主要包括定时器时钟的选择,模式控制,定时器清零和定时器终端使能和标志位的功能。
(2)TAxR :这个寄存器用来存储Timer_A的计数量。
(3)TAxCCTLn: Timer_A capture/compare 寄存器控制寄存器。这个寄存器用以控制Timer_A寄存器(TAxCCRn),主要包括capture mode , output mode ,interrupt enable 等一系列内容。
(4)TAxCCRn: 比较模式:Timer_A 计时器的值
捕捉模式:is copied into the TAxCCRn register when a capture is performed.
(5) TAxIV: Timer_Ax中断向量寄存器
好了,大体就需要了解这么多,先写一段程序验证一下这些功能。
一:使用定时器控制LED的闪烁(在P11.0上连着一个红色led等,当P11.0=0时,灯亮)
#include "msp430x54x.h"
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P11DIR |= 0x01; // P11.0 output
TA1CCTL0 = CCIE; // CCR0 interrupt enabled
TA1CCR0 = 50000;
TA1CTL = TASSEL_2 + MC_1 + TACLR; // SMCLK, upmode, clear TAR
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts
__no_operation(); // For debugger
}
// Timer A0 interrupt service routine
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
P11OUT ^= 0x01; // Toggle触发 P1.0
}
每次TARx计数到50000闪烁一次。事实证明,红色led灯闪烁。
二:使用定时器产生PWM的波形
比如我想要的到一个周期约为10ms,占空比为1/5的方波波形。
#include "io430x54xA.h"
//这个函数用来产生5MHz的时钟信号
void InitClock()
{
P1DIR |= BIT0;
P1SEL |= BIT0; //ACLK output,这时候可以使用示波器观察时钟信号
UCSCTL3 |= SELREF_2; // FLLref = REFO
UCSCTL4 = SELM__DCOCLKDIV + SELS__DCOCLKDIV + SELA__DCOCLKDIV;// 时钟来源:主系统时钟来源DCOCLKDIV;子系统时钟来源DCOCLKDIV;辅助系统时钟来源DCOCLKDIV
UCSCTL5 |= DIVM__1 + DIVS__1 + DIVA__1; // 分频:主系统时钟1分频;子系统时钟1分频;辅助系统时钟1分频
__bis_SR_register(SCG0); // Disable FLL
UCSCTL1 = DCORSEL_6; // 10.7MHz<Fdco<39MHz
UCSCTL2 |= FLLD__2 +151 ; // 5MHz DCOCLKDIV Fdco/4
__bic_SR_register(SCG0); // Enable FLL
// 等待错误标志清除,振动器稳定
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
}
//初始化Timer_A
void Init_Timer_A()
{
P2DIR |= 0x04; // P2.2 output
P2SEL |= 0x04; // P2.2 options select
TA1CCR0 = 50000; // PWM Period 约为10ms
TA1CCTL1 = OUTMOD_3; // CCR1 set/reset
TA1CCR1 = 40000; // CCR1 PWM duty cycle 1/5
//TA1CCTL2 = OUTMOD_7; // CCR2 reset/set
//TA1CCR2 = 128; // CCR2 PWM duty cycle
TA1CTL = TASSEL_2 + MC_1 + TACLR; // SMCLK, up mode, clear TAR
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
InitClock();
Init_Timer_A();
__bis_SR_register(LPM0_bits); // Enter LPM0
__no_operation(); // For debugger
}
示波器检测结果为:
由此可以看出,输出的波形周期约为10ms,占空比约为1/5 。
其他的问题就具体考虑就ok。