This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Timer accuracy

Hello,
I configured a timer to generate a signal every 1 ms.

See below my code about the timer:

TIM_DeInit(TIMx);  // TIM1 Deinitialization *
TIM_InitStructure.TIM_Mode                       = TIM_OCM_CHANNEL_1;
TIM_InitStructure.TIM_OC1_Modes          = TIM_TIMING;
TIM_InitStructure.TIM_Clock_Source       = TIM_CLK_APB;
TIM_InitStructure.TIM_Clock_Edge         = TIM_CLK_EDGE_FALLING;
TIM_InitStructure.TIM_Prescaler          = 0xEF; // period = 5us
TIM_InitStructure.TIM_Pulse_Length_1 = 0xC8; // cycle of 200 period => cycle = 1ms
TIM_Init (TIMx, &TIM_InitStructure);

And the statements inside timer's interrupt:

void TIM1_IRQHandler(void)
{
        // port 3 pin 7 activated
        P37_1;
        // ACK interrupt
        TIM_ClearFlag(TIM1, TIM_FLAG_OC1);      // clear Output Compare 1 flag
        TIM_CounterCmd(TIM1, TIM_CLEAR);        // Reset TIM1 Counter
    VIC0->VAR = 0xFF;                                        // write any value to VIC0 VAR
}

BUT my oscilloscope measured a period of 1.03 ms instead of the 1ms expected.
Normally to generate a pulse every 1.03 ms the TIM_Pulse_Length_1 should be set to 0xCE.
As you can see, the difference between 0xCE and 0xC8 is big.

What can be the cause of this timer's inaccuracy ?
> Problem in PLL configuration ?
> Problem of crystal ?
> Problem in timer configuration ?

Has someone the same problem ?
In advance, thank you

Parents Reply Children
  • We use:
    > STR912FAW44

    for the PLL configuration :
    > In the main application loaded by the bootloader, the PLL is configured as followed inside main.c (there is no file with the extension .s):

    // Initialisation
            SCU_MCLKSourceConfig(SCU_MCLK_OSC);     /* Default configuration */
    
        /*wait state insertion :This function should be executed from SRAM when*/
        /*booting from bank1 to avoid  Read-While-Write from the Same Bank.*/
        FMI_Config(FMI_READ_WAIT_STATE_2, FMI_WRITE_WAIT_STATE_0, FMI_PWD_ENABLE,\ 
                   FMI_LVD_ENABLE, FMI_FREQ_HIGH);/*Insert 2 Wait States for read*/
    
        SCU_PLLFactorsConfig(192, 25, 2); /* PLL factors Configuration based on*/
        /* a OSC/Crystal value = 25Mhz*/
        SCU_PLLCmd(ENABLE);  /* PLL Enable and wait for Locking*/
        SCU_RCLKDivisorConfig(SCU_RCLK_Div1); /* RCLK @96Mhz */
        SCU_HCLKDivisorConfig(SCU_HCLK_Div1); /* AHB @96Mhz */
        SCU_FMICLKDivisorConfig(SCU_FMICLK_Div1);/* FMI @96Mhz */
        SCU_PCLKDivisorConfig(SCU_PCLK_Div2); /* APB @48Mhz */
        SCU_MCLKSourceConfig(SCU_MCLK_PLL);  /* MCLK @96Mhz */
    

    I give you also how I calculated my counter and prescaler:
    > APB = 48Mhz
    > prescaler = 0xEF because we choosed to count 5us per 5us <= 1/(48/240) = 5 us
    > counter = 0xC8 because 0xC8 = 200 and 200 * 5us = 1 ms

  • Are you running an RC oscillator?
    >> I used the MCBSTR9 eval board. They used a 25MHz oscillator

  • SCU_MCLKSourceConfig(SCU_MCLK_PLL);  /* MCLK @96Mhz */
    

    Whats the exact value? Is it really 96000000Hz?
    For me its 99328000 instead of 99MHz.

  •    SCU_PLLFactorsConfig(192, 25, 2); /* PLL factors Configuration based on*/
        /* a OSC/Crystal value = 25Mhz*/
    
    

    If this were my project, I'd be seriously worried wether an output frequency of 192 MHz for the PLL might be impossible to achieve with an input of 25 MHz. PLLs like this usually only allow to scale up the input frequency by an integer factor. 192/25 isn't integer.

    In the case at hand, I'd expect a result of 8*25 MHz, i.e. 200 MHz. That would throw off all other frequencies and timings by a factor of 200/192, which just so happens to be 1.04. Sound familiar? ;-)