问题描述:
1. MSP430F5509+CC1101在实现定时发送无线数据包的功能时,偶尔会产生XT1 fault。
2. 取100个设备进行测试,在运行一段时间后,大约会有7个设备产生了XT1 fault。
3. 使用数字电源,串联30欧姆电阻,为设备供电,每一个设备都会产生XT1 fault。
4. XT1 fault产生的时间,是在CC1101发送数据包完成后的瞬间,接收端可以收到此数据包。
5. 将程序中的所有的__bis_SR_register(LPM3_bits + GIE);更改为__bis_SR_register(LPM0_bits + GIE);,仍然会出现XT1 fault。
6. 去除程序中所有的__bis_SR_register(LPM3_bits + GIE);,稍作修改,使得程序可以实现预定功能,未出现XT1 fault。
注:
1. MCLK = DCODIV = 12MHz, SMCLK = DCODIV = 12MHz, ACLK = XT1 = 32.768KHz, FLL reference = XT1CLK
2. CC1101发送数据包时,设备的总电流大约40mA,耗时10ms。
3. XT1 = 32.768KHz外部晶振, -20 < PPM < 20, LF mode
求助:
1. 什么情况下可以产生XT1 fault ?
2. 产生XT1 fault后,需要进行哪些操作,使得系统可以尽快回到正常工作状态?
UCS的设置函数:
/*******************************************************************************
* @fn: InitSysClk_12MHz
* @brief: MCLK = SMCLK = DCOCLKDIV = 12MHz, ACLK = XT1CLK = 32.768KHz
* @para: none
* @return:
* 0 = ok
* -1 = XT1 error
* -2 = DCO error
* -3 = XT1 error && DCO error
* -4 = XT2 error
* -5 = XT1 error && XT2 error
* -6 = DCO error && XT2 error
* -7 = XT1 error && DCO error && XT2 error
******************************************************************************/
signed char InitSysClk_12MHz(void) {
signed char rc = 0;
*Address = 0x9628;
*(Address + 4) = 0x0800;
*Address = 0x9600;
P1SEL |= BIT0;
P1DIR |= BIT0;
P5SEL |= BIT4 | BIT5; // Select XT1
UCSCTL6 &= ~(XT1OFF); // XT1 On
UCSCTL6 |= XCAP_3; // Internal load cap
UCSCTL3 = 0; // FLL Reference Clock = XT1
// Loop until XT1,XT2 & DCO stabilizes - In this case loop until XT1 and DCo
// settle unsigned int delay = 60000;
do {
UCSCTL7 &= ~(XT2OFFG | XT1LFOFFG | DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
if (--delay == 0) {
if (UCSCTL7 & XT1LFOFFG) { // XT1 error
rc += -1;
}
if (UCSCTL7 & DCOFFG) { // DCO error
rc += -2;
}
if (UCSCTL7 & XT2OFFG) { // XT2 error
rc += -4;
}
return rc;
}
} while (SFRIFG1 & OFIFG); // Test oscillator fault flag
UCSCTL6 &= ~(XT1DRIVE_3); // Xtal is now stable, reduce drive strength
UCSCTL4 |= SELA_0; // ACLK = LFTX1 (by default)
UCSCTL3 = SELREF_0; // Set DCO FLL reference = REFO
UCSCTL0 = DCO0 | 0x0000; // Set lowest possible DCOx, MODx
__bis_SR_register(SCG0);
// Disable the FLL control loop
UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation
UCSCTL2 = FLLD_0 + 365; // Set DCO Multiplier for 8MHz
// (N + 1) * FLLRef = Fdco
// (365 + 1) * 32768 = 12MHz
__bic_SR_register(SCG0);
// Enable the FLL control loop
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
// UG for optimization.
// 32 x 32 x 12 MHz / 32,768 Hz = 375000 = MCLK cycles for DCO to settle
__delay_cycles(375000);
// Loop until XT1,XT2 & DCO fault flag is cleared
delay = 60000;
do {
UCSCTL7 &= ~(XT2OFFG | XT1LFOFFG | DCOFFG);
// Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
if (--delay == 0) {
if (UCSCTL7 & XT1LFOFFG) { // XT1 error
rc += -1;
}
if (UCSCTL7 & DCOFFG) { // DCO error
rc += -2;
}
if (UCSCTL7 & XT2OFFG) { // XT2 error
rc += -4;
}
return rc;
}
} while (SFRIFG1 & OFIFG); // Test oscillator fault flag
PMMCTL0_H = PMMPW_H; // PMM Password
SVSMHCTL &= ~(SVMHE | SVSHE); // Disable High side SVS
SVSMLCTL &= ~(SVMLE | SVSLE); // Disable Low side SVS
return 0;
}