大家好,
我已经能够设置我的控制器以使用计时器运行,运行中断等。 这方面的一切都很好。 我正在使用带有DCO/FLL的REFO作为时间基准。 没有晶体,因此不需要XT1。
我了解可以启用CSCTL7/FLLWARNEN,以便在FLL检测到DCO因温度而超出范围时生成中断。 不幸的是,DCO故障和XT1 OSC故障共享相同的NMI (参见SLAU445G中的图3-5)作为DCO故障。 两个CSCTL7/FLLUNLOCKHIS位根据需要保持0b00, 但 XT1 OSC故障始终生成(持续)。 因此,如果我启用SFRIE1/OFIE,则会不断生成XT1 OSC故障。 这就是为什么我一直在尝试禁用XT1和/或任何可能生成XT1 OSC故障的设备。 我已经厌倦了通过SR/OSCOFF关闭XT1 (这是一次很长的射击),CSCTL7/ENSTFCT1 (也不是真正正确的事情)以及其他一些我现在无法回忆的事情。
如果我想重新校准DCO/FLL,如果它漂移(比如由于温度),FLLWARNEN是不是该去的?
如果是,我在忽略什么?
如果不是,正确的机制是什么?
谢谢大家。
下面是一个代码;
#include <MSP430-h>
#define init_rate 0x3C // Timer0 A0速率(基于8 MHz MCLK)
静态持续无符号int blink_rate =
{ //较大的数字=较慢的闪烁速率
0x6000, // blink_cnt必须出现此信息才能缓慢闪烁
0x1000 // blink_cnt必须达到此值才能快速闪烁
};
unsigned int blink_rate = 0; // blink_rate索引[]
volatile unsigned int blink_cnt; //计数计时器中断到blink_rate_table[]时间,易失性以防止优化
无符号int测试=0;
////
MCLK振荡器=8 MHz
//如果需要大于8 MHz的值,则必须
//为FRAM添加等待//初始化
OSC_Init(void){
//__bis_sr_register (OSCOFF); //禁用LFXT1,可以尝试停止XT1.....,但它会再次出现。
__bis_sr_register (SCG0); //禁用FLL (在下面再次启用)
CSCTL3 |= SELREF_REFCLK; //将REFO设置为FLL参考源
CSCTL0 = 0; //清除DCO和MOD寄存器
CSCTL1 &=~(DCORSEL_7); //首先清除DCO频率选择位
CSCTL1 |= DCORSEL_3; //为8MHz设置DCORSEL = 0x02
CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz
__DELAY周期(3); //执行3xNOP以使设置生效
__BIC_SR_REGISTER (SCG0); //启用FLL
While (CSCTL7和(FLLUNLOCK0 | FLLUNLOCK1));//等待FLL锁定
CSCTL7 |=~(ENSTFCNT1 | FLLULUCFO| FLLULUNLOCK0 | FLLUNLOCK1); //禁用XT1计数器(它是后部疼痛)
CSCTL7 &=~(FLLUNLOCKHIS0 | FLLUNLOCKHIS1);//清除FLLUNLOCKHIS故障标记。
//当我们等待FLL锁定时,它们已经被设置。
CSCTL7 |= FLLWARNEN; //如果由于温度原因导致频率锁定松动,则启用中断
//SFRIE1 |= OFIE; //在SYS中启用FLL中断
//****** 取消注释上述行会导致不断生成XT1 NMI。 *****
}
////
Time_Base FLL丢失锁定中断服务例程
//
#pragma vector = UNMI_vector
__interrupt void UNMI_ISR(void)
{
__bis_sr_register (SCG0); //禁用FLL (在下面再次启用)
CSCTL3 |= SELREF_REFCLK; //将REFO设置为FLL参考源
CSCTL0 = 0; //清除DCO和MOD寄存器
CSCTL1 &=~(DCORSEL_7); //首先清除DCO频率选择位
CSCTL1 |= DCORSEL_3; //为8MHz设置DCORSEL = 0x02
CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz
__DELAY周期(3); //执行3xNOP以使设置生效
__BIC_SR_REGISTER (SCG0); //启用FLL
While (CSCTL7和(FLLUNLOCK0 | FLLUNLOCK1));//等待FLL锁定
CSCTL7 &=~(FLLUNLOCKHIS0 | FLLUNLOCKHIS1);//清除FLLUNLOCKHIS故障标记。
//在等待FLL锁定时,它们已被设置
。}
//
//初始化I/O引脚
//
void gPIO_Init(void)
{
//使未使用的引脚输出保持低功耗
P1REN = 0x00; //端口1电阻器关闭
P2REN = 0x00; //端口2电阻器关闭
P1SEL0 = 0x00; //使端口1成为简单的I/O端口
P1SEL1 = 0x00; //使端口1成为简单的I/O端口
P2SEL0 = 0x00; //使端口2成为简单的I/O端口
P2SEL1 = 0x00; //使端口2成为简单的I/O端口
P1DIR = 0x00; //现在将P1设置为输入方向
P2DIR || BIT7; //将WFP 2.7 设置为输出方向。 LED位于该针脚上
。}
//
使用捕获/比较控件0初始化TimerA0
//
void TimerA0_C0_Init(void){
TA0CCTL0 = CCIE; //设置定时器A捕获-比较0
TA0CCR0 = INIT_RATE; //设置周期时间
TA0CTL = tassel__SMCLK | MC__UP; //配置计时器A0 clk源和操作模式
}////
Timer0 A0中断服务例程
//
#pragma矢量= TIMER0_A0_vector
__interrupt void Timer0_A0_ISR (void)
{
IF(Blink_cnt >= Blink_RATE_Blink_RATE[Blink_RATE]) //如果是时间,请更改LED
的状态{
P2OUT ^= 0x80; //使用专用或切换WFP 2.7 (LED)
blink_cnt = 0; //并在达到阈值时重置计数器
测试++;
如果(测试>= 20)
{
测试= 0;
如果(blink_rate == 1)
blink_rate = 0;
否则
blink_rate = 1;
}
}
否则
blink_cnt+; //否则,增加计数
器}////
main.c
//
void main(void){
WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
//PM5CTL0 &=~LOCKLPM2; //禁用GPIO开机默认高阻抗模式
//以激活先前配置的端口设置
OSC初始化(); //将振荡器设置为MCLK =8 MHz
GPIO初始化(); //初始化GPIO引脚
TimerA0_C0_Init(); //初始化TimerA0和CCR0
__bis_sr_register (GIE); //启用中断
同时(1); //这只是临时的例子__bis_sr_register(LPM0_bits | GIE);对我正在俯瞰的SG0/1/OSCOFF/CPUOFF做了一些有趣的事情。
//__bis_sr_register (LPM0_bits | GIE); //在此处停车并进入低功率状态,相当于BIS #8,SR
//__no_operation(); //用于调试
}