cancel
Showing results for 
Search instead for 
Did you mean: 

1Hz interrupt from TIM3 ?

antonius
Senior

Dear Members,

How can I get exactly 1Hz interrupt from TIM3 ?

I use STM32F4 Discovery and looking at TIM_TimeBase Example, but I can not get exactly 1Hz yet...

Thanks

Code :

TIM_OCInitTypeDef  TIM_OCInitStructure;
__IO uint16_t CCR1_Val = 54618;
__IO uint16_t CCR2_Val = 27309;
__IO uint16_t CCR3_Val = 13654;
__IO uint16_t CCR4_Val = 6826;
 
 
/* -----------------------------------------------------------------------
    TIM3 Configuration: Output Compare Timing Mode:
    
    In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1), 
    since APB1 prescaler is different from 1.   
      TIM3CLK = 2 * PCLK1  
      PCLK1 = HCLK / 4 
      => TIM3CLK = HCLK / 2 = SystemCoreClock /2
          
    To get TIM3 counter clock at 50 MHz, the prescaler is computed as follows:
       Prescaler = (TIM3CLK / TIM3 counter clock) - 1
       Prescaler = ((SystemCoreClock /2) /50 MHz) - 1
                                              
    CC1 update rate = TIM3 counter clock / CCR1_Val = 9.154 Hz
    ==> Toggling frequency = 4.57 Hz
    
    C2 update rate = TIM3 counter clock / CCR2_Val = 18.31 Hz
    ==> Toggling frequency = 9.15 Hz
    
    CC3 update rate = TIM3 counter clock / CCR3_Val = 36.62 Hz
    ==> Toggling frequency = 18.31 Hz
    
    CC4 update rate = TIM3 counter clock / CCR4_Val = 73.25 Hz
    ==> Toggling frequency = 36.62 Hz
 
/* Compute the prescaler value */
  //PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 500000) - 1;
	PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 6826) - 1;  //TIM3 counter clock at 6826Hz
 
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
 
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
 
  /* Prescaler configuration */
  TIM_PrescalerConfig(TIM3, PrescalerValue, TIM_PSCReloadMode_Immediate);
 
  /* Output Compare Timing Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
 
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
 
  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
 
  /* Output Compare Timing Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
 
  TIM_OC2Init(TIM3, &TIM_OCInitStructure);
 
  TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
 
  /* Output Compare Timing Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
 
  TIM_OC3Init(TIM3, &TIM_OCInitStructure);
 
  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Disable);
 
  /* Output Compare Timing Mode configuration: Channel4 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
 
  TIM_OC4Init(TIM3, &TIM_OCInitStructure);
 
  TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Disable);
   
  /* TIM Interrupts enable */
  TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
This example shows how to configure the TIM peripheral in Output Compare Timing 
mode with the corresponding Interrupt requests for each channel in order to generate
4 different time bases.
 
The TIM3CLK frequency is set to SystemCoreClock / 2 (Hz), to get TIM3 counter 
clock at 500 KHz so the Prescaler is computed as following:
   - Prescaler = (TIM3CLK / TIM3 counter clock) - 1
 
SystemCoreClock is set to 168 MHz for STM32F4xx Devices Revision A.
 
The TIM3 CC1 register value is equal to 54618, 
CC1 update rate = TIM3 counter clock / CCR1_Val = 9.154 Hz,
so the TIM3 Channel 1 generates an interrupt each 109.2ms
 
The TIM3 CC2 register is equal to 27309, 
CC2 update rate = TIM3 counter clock / CCR2_Val = 18.31 Hz
so the TIM3 Channel 2 generates an interrupt each 54.6ms
 
The TIM3 CC3 register is equal to 13654, 
CC3 update rate = TIM3 counter clock / CCR3_Val = 36.62 Hz
so the TIM3 Channel 3 generates an interrupt each 27.3ms
 
The TIM3 CC4 register is equal to 6826, 
CC4 update rate = TIM3 counter clock / CCR4_Val =  73.25 Hz
so the TIM3 Channel 4 generates an interrupt each 13.65ms.
 
When the counter value reaches the Output compare registers values, the Output 
Compare interrupts are generated and, in the handler routine, 4 pins(PD.12, PD.13,
PD.14 and PD.15) are toggled with the following frequencies: 
 
- PD.12:  4.57 Hz (CC1)
- PD.13:  9.15 Hz (CC2)
- PD.14: 18.31 Hz (CC3) 
- PD.15: 36.62 Hz (CC4)

24 REPLIES 24

prevent it from overflow, reset the counter ? or reduce the timer clock ?

Or you know a better idea ? it's puzzling me...

Thanks

TDK
Guru

I looked at the example a bit more closely. The reason they're getting different interrupt frequencies is that the interrupt itself changes the CCRx value an increments it by the corresponding CCRx_Val defined value. Because of this, it also sneakily requires TIM_Period = 65535 so that it can rely on 16-bit overflow to calculate the correct next CCRx value.

To get 1Hz and 0.5Hz interrupts, use your original example but change:

// to get 1 Hz interrupt
__IO uint16_t CCR1_Val = 2000;
 
// to get 0.5 Hz interrupt
__IO uint16_t CCR2_Val = 4000;
 
...
 
// to get 2kHz timer clock
// (if SystemCoreClock = 168MHz, this evaluates to 41999)
PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 2000) - 1;

Did not test, but it probably works.

Original project:

https://github.com/USTPGW/Workspace/blob/583e96715a9fd9dda5bd5c1dbb662284a81d102f/Workspace/STM32F4-Discovery_FW_V1.1.0/Project/Peripheral_Examples/TIM_TimeBase/main.c

If you feel a post has answered your question, please click "Accept as Solution".

thanks for the reply,

Here's my experiment :

__IO uint16_t CCR1_Val = 1000;

__IO uint16_t CCR2_Val = 2000;

__IO uint16_t CCR3_Val = 4000;

__IO uint16_t CCR4_Val = 8000;

PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 1000) - 1; //TIM3 counter clock at 1000Hz

suppose to be 1Hz, 0.5Hz, 0.25Hz and 0.125Hz

the interrupt service,

/**
 
 * @brief This function handles TIM3 global interrupt request.
 
 * @param None
 
 * @retval None
 
 */
 
void TIM3_IRQHandler(void)
 
{
 
 if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
 
 {
 
   TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
 
 
   /* LED4 toggling with frequency = 4.57 Hz */
 
   STM_EVAL_LEDToggle(LED4);
 
   capture = TIM_GetCapture1(TIM3);
 
   TIM_SetCompare1(TIM3, capture + CCR1_Val);
 
 }
 
 else if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
 
 {
 
   TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
 
 
   /* LED3 toggling with frequency = 9.15 Hz */
 
   STM_EVAL_LEDToggle(LED3);
 
   capture = TIM_GetCapture2(TIM3);
 
   TIM_SetCompare2(TIM3, capture + CCR2_Val);
 
 }
 
 else if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
 
 {
 
   TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
 
 
   /* LED5 toggling with frequency = 18.31 Hz */
 
   STM_EVAL_LEDToggle(LED5);
 
   capture = TIM_GetCapture3(TIM3);
 
   TIM_SetCompare3(TIM3, capture + CCR3_Val);
 
 }
 
 else
 
 {
 
   TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
 
 
   /* LED6 toggling with frequency = 36.62 Hz */
 
   STM_EVAL_LEDToggle(LED6);
 
   capture = TIM_GetCapture4(TIM3);
 
   TIM_SetCompare4(TIM3, capture + CCR4_Val);
 
 }
 
}
 
 

I'll give a try and posted,

Cheers

antonius
Senior

What's the minimum frequency for TIM3 counter ?

Is it possible that I change

 uint32_t SystemCoreClock = 168000000;

to lower frequency ? for example 50000000 for preventing my TIM3 overflow ?

Min_frequency = TIMER_CLK / 65536

antonius
Senior

it means that if I have timer_CLK = 1000Hz

PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 1000) - 1; //TIM3 counter clock at 1000Hz

minimum TIM3 counter = 65.536Hz ?

I had a typo,

TIM3_CLK is SystemCoreClock / 2 (usually APB clock)

for a "GIVEN" TIM3_CLK the minimum is:

Min_frequency = TIM3_CLK / 65536

S.Ma
Principal

you also could extend the timer using overflow calkback and increment a global 32 bit variable.... that starts to look like a sw RTC....

Piranha
Chief II

> How​ to avoid overflow ? I want to get 1Hz, 0.5Hz, 0.1Hz and 0.05Hz

The longest period is 20 s (for 0,05 Hz) and it must not overflow 65'536. For that a period of 60'000 would be a nice number and for that to work, you need a timer frequency of 60000 / 20 s = 3 kHz. Set a prescaler to 84 MHz / 3 kHz = 28'000. Adjust a period for the faster frequencies and you are done.

But you cannot get multiple simultaneous frequencies from a single timer without readjustment in a software interrupt on every cycle!

Anyway this sounds like a possibly wrong solution for the job. If it is for some software retry/polling cycles, then it really is a job for software timers...