【IoT】如何使用 MSP430 内部频率 VLO 以及如何校正频率
1、需求定义
有时候为了节省成本,会尽量减少外部器件的花费,MSP430有一个内部 12KHz 的 VLO 频率,虽然有较大温飘和压飘,通过校正也是可以满足需求的。
2、什么是 VLO
Very-Low-Power Low-FrequencyOscillator (VLO),也就是超低功耗低频振荡器;
输出频率:标称 12KHz,3V 下最小 4KHz,最大 20KHz;
功耗: 2.2V 下最大只有 0.7uA,比32K768的手表晶振 1.5uA 还低很多,这已经是 LPM3 模式下功耗最低的时钟源了;
用途:可以用作 MSP430 的 ACLK,MCLK,SMCLK 时钟源;
3、如何使用 VLO
//******************************************************************************
// Description; Pulse P1.0 with a 1/100 active duty cycle using software.
// Ultra-low frequency ~ 1.5kHz, ultra-low power active mode demonstrated.
// ACLK = VL0, MCLK = VLO/8 ~1.5kHz, SMCLK = n/a
//
// MSP430G2xx1
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | P1.0|-->LED
//
//******************************************************************************
#include <msp430.h>
int main(void)
{
volatile unsigned int i;
WDTCTL = WDTPW + WDTHOLD;
BCSCTL3 |= LFXT1S_2; // 选择时钟源:LFXT1 = VLO
IFG1 &= ~OFIFG; // Clear OSCFault flag
__bis_SR_register(SCG1 + SCG0);
BCSCTL2 |= SELM_3 + DIVM_3; // 8分频:MCLK = LFXT1/8
P1DIR = 0xFF;
P1OUT = 0;
P2DIR = 0xFF;
P2OUT = 0;
for (;;)
{
P1OUT |= 0x01;
for (i = 10; i > 0; i--);
P1OUT &= ~0x01;
for (i = 1000; i > 0; i--);
}
}
4、如何校正 VLO 频率
VLO 非常适合做低功耗下的待机时钟,但是不同环境频率偏差太大,在TI的应用支持中就有一种方法来校准 VLO。
VLO 本身的输出频率并不能被改变,称作校准不是很确切。我们大部分情况下使用 VLO 低频时钟只是为了将单片机从低功耗模式下唤醒,也就是需要实用它产生一个从0到几十赫兹的唤醒信号。既然不能动时钟源,那我们就想办法改变定时器的计数来获得我们想要的唤醒信号。
在 msp430G2XXX 中还有一个时钟叫 DCO,主要用于时钟倍频。TI 为 msp430G2XXX 单片机提供了至少一个用于校准 DCO 的数据存放在 FLASH 中。
这个经过校准的最小 DCO 频率为 1MHz,我们可以通过书橱在一个或 X 个 VLO 周期内的 DCO 振荡次数 Y,这样 f(VLO)=f(DCO)*X/Y。知道 VLO 的频率之后,设置好定时器便可以获得我们需要的唤醒中断信号。并且这个唤醒信号的精度不依赖于VLO(当然温度和电压不能变化)。
实际应用可以隔一段时间重新校准一次 VLO,确保在温度变化时,唤醒信号的精度不随 VLO偏移。
TI 官网提供了较为完整的实例:
头文件 #include "VLO_Library.h":
#ifndef VLO_Library
#define VLO_Library
extern int TI_measureVLO( void );
extern unsigned int TI_8MHz_Counts_Per_VLO_Clock;
#endif
校正源码:
;*******************************************************************************
; L. Westlund
; Texas Instruments Inc.
; March 2006
; Built with IAR Embedded Workbench Version: 3.40A
;*******************************************************************************
#include <msp430x20x2.h>
MODULE VLO_Library
;Variables
PUBLIC TI_8MHz_Counts_Per_VLO_Clock
;Functions
PUBLIC TI_measureVLO
RSEG DATA16_I
TI_8MHz_Counts_Per_VLO_Clock DS 2
#ifdef TACCTL2_ ; For non-Timer_A2 devices
#define TACCTLX TACCTL2
#define TACCRX TACCR2
#else
#define TACCTLX TACCTL0
#define TACCRX TACCR0
#endif
RSEG CODE ; Code is relocatable
;-------------------------------------------------------------------------------
TI_measureVLO
; returns: r12
; -An int representing the number of 8MHz clock pulses in one VLO cycle
; -This value is identical to the number put into TI_8MHz_Counts_Per_VLO_Clock
;-------------------------------------------------------------------------------
mov.b &BCSCTL1, r15 ; preserve previous settings
mov.b &DCOCTL, r14
push.b &BCSCTL2
push.b &BCSCTL3
push.b &P2SEL
bic.b #0xC0, &P2SEL ; clear P2SEL bits to avoid XTAL interference.
mov.b &CALBC1_1MHZ, &BCSCTL1 ; Set range
mov.b &CALDCO_1MHZ, &DCOCTL ; Set DCO step + modulation
mov.w #CM_1+CCIS_1+CAP,&TACCTLX ; CAP, ACLK
mov.w #TASSEL_2+MC_2+TACLR, &TACTL; SMCLK, cont-mode, clear
mov.b #LFXT1S_2, &BCSCTL3 ; ACLK = VLO
clr.b &BCSCTL2
bis.b #DIVA_3, &BCSCTL1 ; ACLK=VLO/8
bic.w #CCIFG, &TACCTLX ; Clear capture flag
edge_one bit.w #CCIFG, &TACCTLX ; Test capture flag to skip first signal
jz edge_one
bic.w #CCIFG, &TACCTLX ; Clear capture flag
edge_two bit.w #CCIFG, &TACCTLX ; Test capture flag to skip second signal
jz edge_two ;
mov.w &TACCRX, r13 ; save hardware captured value
bic.w #CCIFG, &TACCTLX ; Clear capture flag
edge_three bit.w #CCIFG, &TACCTLX ; Test capture flag to capture a good clock
jz edge_three ;
bic.w #MC_3, &TACTL ; stop timer
mov.w &TACCRX, r12
sub.w r13, r12
mov.w r12, &TI_8MHz_Counts_Per_VLO_Clock
mov.b r15, &BCSCTL1
mov.b r14, &DCOCTL
pop.b &P2SEL
pop.b &BCSCTL3
pop.b &BCSCTL2
ret
END
应用实例:
//******************************************************************************
// Description: This example toggles P1.0 on approximately a 1 second interval
// The DCO is set to 8MHz to demonstrate that clock settings are preserved
// across the function call.
// ACLK = VLO, MCLK = SMCLK = 8MHz
//
// MSP430F2012
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | P1.4/SMCLK|-->SMCLK = 8MHz
// | P1.0/ACLK|-->LED 1 second interrupt
//
//******************************************************************************
#include <msp430x20x2.h>
#include "VLO_Library.h"
int dco_delta;
int result;
void main(void)
{
volatile unsigned int i;
WDTCTL = WDTPW +WDTHOLD; // Stop Watchdog Timer
P1DIR |= 0x11; // P1.0,1,4 outputs
P1SEL |= 0x10; // P1.4 = SMCLK
BCSCTL3 |= LFXT1S_2; // ACLK = VLO
BCSCTL1 = CALBC1_8MHZ; // 8MHz cal value
DCOCTL = CALDCO_8MHZ; // 8MHz cal value
dco_delta = TI_measureVLO(); // dco delta = number of
// 1MHz cycles in 8 ACLK cycles
TACCTL0 = CCIE; // CCR0 interrupt enabled
TACCR0 = (8000000 / dco_delta); //
TACTL = TASSEL_1 + MC_1; // ACLK, upmode
P1OUT = 0x01;
_BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupt
}
// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
P1OUT ^= 0x01; // Toggle P1.0
}
文章来源: blog.csdn.net,作者:简一商业,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/liwei16611/article/details/80469386
- 点赞
- 收藏
- 关注作者
评论(0)