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.

FR5 crystal load calculation



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

  • Argail said:
    where should I found the formula?

    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.

  • 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?

  • Argail said:
    Thank you for the update, I thought this was more related to the pierce oscillator.

    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:
    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.

    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.

  • 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