I want to drift the LFXT1 frequency from +/-20ppm to 0/+40ppm. It is normally possible to do that with a correct capacitive load calculation, where should I found the formula?
Regards
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
In the crystal datasheet, as this is a very crystal specific thing. Or you calibrate manually with an adjustable capacitor, comparing the result with a reference. THis is how I calibrate my RTCs.Argail said:where should I found the formula?
Thank you for the update, I thought this was more related to the pierce oscillator.
Without looking for drifting the frequency I soldered two capacitor on the RGZ48C board for crystal load because they are no more integrated. This board is delivered with a 12.5pF crystal, so according the formula from SLAA322B: CL1 = (2 × CLoad) – CParasitic, I have to put two times 24pF crystal load.
I've soldered 22pF actually (08051A220JAT2A), but this generates OFIFG from RTC module even with the frequency seems good, and OFIFG is not set in the NMI register.
Without any capacitor, the frequency is near 38KHz (roughly measured with my oscillocsope) but there is no fault flag.
Is there any explanation?
No, the oscillator just pushes and pulls one side of the crystal. At this, the charge flows from one cypycitor through the crystal to the other sides capacitor. So the caps need to match the crystals mechanical 'capacity' or it will detune and oscillation will be attenuated. And obviously, teh crystals data are crystal specific :)Argail said:Thank you for the update, I thought this was more related to the pierce oscillator.
If OFIFG is clear, and teh crystal oscillator is enabled, then things should work. Maybe there's a problem in your init code.You shoudl post it. I don't have any experience with the FR family RTC (or any FR family stuff). I only used the RTC_A of the F5x family so far.Argail said:I've soldered 22pF actually (08051A220JAT2A), but this generates OFIFG from RTC module even with the frequency seems good, and OFIFG is not set in the NMI register.
Here some parts the initialization concerning RTC and CS, the system directly goes in LPM4 after that (wait for external system wake up). The wdt is off, GIE off during the whole init and on before entering LPM4. I use the driver library.
void systemInit(void)
{
[...]
//Configure MCLK=8Mhz and SMCLK=4Mhz, used by SPI
CS_setDCOFreq(CS_BASE,
CS_DCORSEL_0,
CS_DCOFSEL_6); //Set DCO frequency to 8Mhz
CS_clockSignalInit(CS_BASE,
CS_MCLK,
CS_DCOCLK_SELECT,
CS_CLOCK_DIVIDER_1); //MCLK sourced with DCOCLK
CS_clockSignalInit(CS_BASE,
CS_SMCLK,
CS_DCOCLK_SELECT,
CS_CLOCK_DIVIDER_2); //SMCLK sourced with DCOCLK/2
CS_enableClockRequest(CS_BASE,
CS_SMCLK); //Request SMCLK during LPMx modes
[...]
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ,
GPIO_PIN4+
GPIO_PIN5,
GPIO_PRIMARY_MODULE_FUNCTION); //Configure LFXT1 function pin
//Configure RTC
RTC_B_setCalendarEvent(RTC_B_BASE,
RTC_B_CALENDAREVENT_MINUTECHANGE); //Specify an interrupt to assert every minute
RTCCTL0 &= ~(RTCBCD);
RTCCTL0 |= RTC_B_FORMAT_BINARY; //Set calendar format
[...]
}
The system wakeup which launch the clock.
void systemWakeup(void)
{
volatile signed char returnValue=0;
//Start up LFXT1
returnValue=CS_LFXTStartWithTimeout(CS_BASE,
CS_LFXT_DRIVE0,
C_LFXT1Timeout);
if(returnValue==STATUS_FAIL)
{
CS_LFXTOff(CS_BASE);
gV_Flag_error.ACLK=1;
}
else
{
//LFXT1 started
CS_clockSignalInit(CS_BASE,
CS_ACLK,
CS_LFXTCLK_SELECT,
CS_CLOCK_DIVIDER_1); //Select XT1 as the clock source for ACLK
//Load calibration
if(gC_Calibration<0 && gC_Calibration>minCalibration)
RTC_B_setCalibrationData(RTC_B_BASE,
RTC_B_CALIBRATION_DOWN2PPM,
~gC_Calibration+1);
else if(gC_Calibration>=0 && gC_Calibration<maxCalibration)
RTC_B_setCalibrationData(RTC_B_BASE,
RTC_B_CALIBRATION_UP4PPM,
gC_Calibration);
else
gV_Flag_error.Calibration=1; //Calibration not valid
setSystemTime(gV_EpochTime); //Configure RTC counters
#ifdef DebugRTC
RTC_B_definePrescaleEvent(RTC_B_BASE,
RTC_B_PRESCALE_1,
RTC_B_PSEVENTDIVIDER_128); //RTC_5 hardware bug workaround
RTC_B_clearInterrupt(RTC_B_BASE,
RTC_B_OSCILLATOR_FAULT_INTERRUPT+
RTC_B_TIME_EVENT_INTERRUPT+
RTC_B_PRESCALE_TIMER1_INTERRUPT); //Clear interrupt flag
RTC_B_enableInterrupt(RTC_B_BASE,
RTC_B_OSCILLATOR_FAULT_INTERRUPT+
RTC_B_TIME_EVENT_INTERRUPT+ //Assert IRQ each minute
RTC_B_PRESCALE_TIMER1_INTERRUPT); //Assert IRQ each seconds
#else
RTC_B_clearInterrupt(RTC_B_BASE,
RTC_B_OSCILLATOR_FAULT_INTERRUPT+
RTC_B_TIME_EVENT_INTERRUPT+
RTC_B_CLOCK_READ_READY_INTERRUPT); //Clear interrupt flags
RTC_B_enableInterrupt(RTC_B_BASE,
RTC_B_OSCILLATOR_FAULT_INTERRUPT+
RTC_B_TIME_EVENT_INTERRUPT+ //Assert IRQ each minute
RTC_B_CLOCK_READ_READY_INTERRUPT); //Assert IRQ each seconds
#endif
RTC_B_startClock(RTC_B_BASE); //Start clock
enableSwitch(); //Enable switch
//Initialization done, system started
gV_Flag_event.SystemStart=1;
}
}
Without external capacitor the system is running, I measured the frequency with my Saleae logic (shouldbe sufficient), which is very close 32768 but with a duty cycle of 30%.
With external capactitor OFIFG is not set but RTCOFIFG stay set, have to re-solder the capacitors for measuring the frequency, but I broke a pad when I previously desoldered C1/C2 from the RGZ48C.
And the IRQ
/****************************************************************************/
/* RTC */
/****************************************************************************/
#pragma vector=RTC_VECTOR
__interrupt void RTC_B_ISR (void)
{
#ifdef DebugRTC
if(RT1PSIFG&RTCPS1CTL) //Prescaler 1
{
while(!RTCRDYIFG&RTCCTL0);
gV_SystemTime.Seconds=RTCSEC;
gV_SystemTime.Minutes=RTCMIN;
gV_SystemTime.Hours=RTCHOUR;
gV_SystemTime.DayOfWeek=RTCDOW;
gV_SystemTime.DayOfMonth=RTCDAY;
gV_SystemTime.Month=RTCMON;
gV_SystemTime.Year=RTCYEAR;
gV_EpochTime++;
}
if(RTCTEVIFG&RTCCTL0)
{
gV_ElapsedMinutes++;
if(gV_ElapsedMinutes==128)
gV_ElapsedMinutes=0;
}
if(RTCOFIFG&RTCCTL0)
{
gV_Flag_error.ACLK=1;
__low_power_mode_off_on_exit(); //Quit low power mode
}
unsigned int dummyRead=RTCIV;
}
#else
switch (__even_in_range(RTCIV,RTCIV_RTCOFIFG))
{
case RTCIV_NONE: break; //No Interrupt pending
case RTCIV_RTCRDYIFG: //RTC ready: RTCRDYIFG
gV_SystemTime.Seconds=RTCSEC;
gV_SystemTime.Minutes=RTCMIN;
gV_SystemTime.Hours=RTCHOUR;
gV_SystemTime.DayOfWeek=RTCDOW;
gV_SystemTime.DayOfMonth=RTCDAY;
gV_SystemTime.Month=RTCMON;
gV_SystemTime.Year=RTCYEAR;
gV_EpochTime++;
break;
case RTCIV_RTCTEVIFG: //RTC interval timer: RTCTEVIFG, set to one minute
gV_ElapsedMinutes++;
if(gV_ElapsedMinutes==128)
gV_ElapsedMinutes=0;
break;
case RTCIV_RTCAIFG: break; //RTC user alarm: RTCAIFG
case RTCIV_RT0PSIFG: break; //RTC prescaler 0: RT0PSIFG
case RTCIV_RT1PSIFG: break; //RTC prescaler 1: RT1PSIFG
case RTCIV_RTCOFIFG: //RTC Oscillator fault
gV_Flag_error.ACLK=1;
__low_power_mode_off_on_exit();
break;
default: break;
}
}
#endif
gV_XXX are in FRAM
**Attention** This is a public forum