cancel
Showing results for 
Search instead for 
Did you mean: 

TIM2 in STM32F100C8

ezyreach
Associate II
Posted on June 30, 2011 at 10:25

I m trying to use TIM2 as a general purpose timer to generate an interrupt at every 10mS.

void Timer2_Init(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

   

    TIM_TimeBaseStructure.TIM_Period = 10;               

    TIM_TimeBaseStructure.TIM_Prescaler = 36000;

    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);            /* TIM IT disable */

    TIM_Cmd(TIM2, DISABLE);                                /* TIM2 disable counter */

}

void RCC_Configuration(void)

{       

    RCC_DeInit();     

    RCC_HSEConfig(RCC_HSE_ON);                                // Enable HSE

    while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);               

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);       

    FLASH_SetLatency(FLASH_Latency_0);                       

    RCC_HCLKConfig(RCC_SYSCLK_Div1);                        

    RCC_PCLK2Config(RCC_HCLK_Div1);                         // PCLK2 = HCLK

    RCC_PCLK1Config(RCC_HCLK_Div2);                        // PCLK1 = HCLK/2

    RCC_PREDIV1Config(RCC_PREDIV1_Source_HSE, RCC_PREDIV1_Div1);

    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_3); 

     

    RCC_PLLCmd(ENABLE);                                    // Enable PLL

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);       

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);               

    while(RCC_GetSYSCLKSource() != 0x08);                  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |      

             RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1 , ENABLE);   

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2 |

         RCC_APB1Periph_USART3 | RCC_APB1Periph_TIM2, ENABLE);   

}

I have enabled the timer interrupt also.

The above routine doesnt generate an interupt exactly at 10mS.

My external crystal connected is 8MHz. And the SYSCLK is configured as PLLCLK which is operating at 24MHz.

I am not clear how the TIM_PERIOD and TIM_Prescaler are calculated.

As the above example is provided by the STM FAE.

And what is procedure to set a timer as GP Timer?

10 REPLIES 10
Posted on June 30, 2011 at 14:51

Freq = TIMCLKx / (Prescale + 1) / (Period + 1)

   TIM_TimeBaseStructure.TIM_Prescaler = (24000 - 1); // 24 MHz to 1KHz ie 1 ms tick

   TIM_TimeBaseStructure.TIM_Period = (10 - 1); // 10 ms               

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ezyreach
Associate II
Posted on June 30, 2011 at 20:13

Freq = TIMCLKx / (Prescale + 1) / (Period + 1)

The above equivalent to,

Freq = TIMCLKx / ((Prescale + 1) * (Period + 1))

Is that correct?

And also in the code posted earlier that means it is not for 10mS delay.

TIM_TimeBaseStructure.TIM_Prescaler  = 24000

TIM_TimeBaseStructure.TIM_Period = 10

The above two declarations is ok for 10mS delay?

What i observed by executing the code posted earlier, there was accumulation of the time period each time the interrupt is generated.

I am not sure how this accumulation is occuring.

Is the code posted earlier has the correct declarations?

Posted on June 30, 2011 at 22:35

And also in the code posted earlier that means it is not for 10mS delay.

 

The above two declarations is ok for 10mS delay?

 

No the numbers programmed into the registers are ZERO based, you must subtract ONE from the simple numbers.

TIM_TimeBaseStructure.TIM_Prescaler  = 23999; // 24000 - 1

TIM_TimeBaseStructure.TIM_Period = 9; // 10 -1

To compute the frequency :

TIMFreq = (TIMCLK / (TIM_TimeBaseStructure.TIM_Prescaler + 1)) / ( TIM_TimeBaseStructure.TIM_Period + 1);

TIMFreq = TIMCLK / ((TIM_TimeBaseStructure.TIM_Prescaler + 1) * ( TIM_TimeBaseStructure.TIM_Period + 1));

You are dividing TIMCLK by the prescaler, then your dividing THAT by the period, every time it goes through the period, you get an update interrupt.

Should compute to 100 Hz

You could also use the Systick for periodic interruption.

  /* Setup SysTick Timer for 10 msec interrupts  (100 Hz)*/

  if (SysTick_Config(SystemCoreClock / 100))

  {

    /* Capture error */

    while (1);

  }

    TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);            /* TIM IT disable */

 

    TIM_Cmd(TIM2, DISABLE);                                /* TIM2 disable counter */

I'd probably be enabling these, but suspect that code is not shown.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ezyreach
Associate II
Posted on July 01, 2011 at 08:07

@Clive1

Thank you very much for the info.

The explanation was very clear.

Yes i had enabled the timer counter and its interrupt in another function. But that was not reflected in my earlier code posting.

ezyreach
Associate II
Posted on July 01, 2011 at 08:48

As per the earlier postings, now the TIM2 is working to generate an interrupt at every 10mS.

Now i have added TIM3 to generate an interrupt at every 100mS.

I have added the TIM3 enable in RCC, NVIC is enabled and IRQ handler is also added.

What i observed is that the TIM3 interrupt is not generated. I m not sure why this happens.

As per reading from the manual i inferred that both these timers are independent and can be used as GP timer.

My initialisation code for TIM3.

void Timer3_Init(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure3;

    TIM_TimeBaseStructure3.TIM_Period= 99;                    //100mS Delay

    TIM_TimeBaseStructure3.TIM_Prescaler= 23999;

    TIM_TimeBaseStructure3.TIM_ClockDivision=0;

    TIM_TimeBaseStructure3.TIM_CounterMode=TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure3);

    TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);            /* TIM IT disable */

    TIM_Cmd(TIM3, DISABLE);                                /* TIM3 disable counter */

}

The interrupt and the counter enable is done in another function.

Posted on July 01, 2011 at 14:01

I tend to use a lot of the timers for generating external timing signals, and use the Systick to call other periodic functions on software counters, ie it runs at 1ms, but calls other services at 1x, 10x, 100x, 1000x entries into the routine. RTOS's often us a single higher rate timer, and have software timers which decrement expiration counts, or observe a timestamp passing/passed.

I suspect your problem with TIM3 is in code not shown. Either you've missed a 3 digit some where, the clock on the right APB (TIM3/APB1 vs TIM1/APB2) is not enabled, or an interrupt is not cleared, etc. Or you have an issue with initialization order for other peripherals/hardware. Provide a more freestanding example, I'll take a look.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ezyreach
Associate II
Posted on July 01, 2011 at 14:39

void RCC_Configuration(void)

{       

    RCC_DeInit();                         

    RCC_HSEConfig(RCC_HSE_ON);

    while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);       

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);       

    FLASH_SetLatency(FLASH_Latency_0);                       

    RCC_HCLKConfig(RCC_SYSCLK_Div1);                        

    RCC_PCLK2Config(RCC_HCLK_Div1);                         // PCLK2 = HCLK

    RCC_PCLK1Config(RCC_HCLK_Div2);                        // PCLK1 = HCLK/2

    RCC_PREDIV1Config(RCC_PREDIV1_Source_HSE, RCC_PREDIV1_Div1);

    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_3);

     

    RCC_PLLCmd(ENABLE);                                    // Enable PLL

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);       

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);               

    while(RCC_GetSYSCLKSource() != 0x08);                   

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |

                  RCC_APB2Periph_GPIOB | RCC_APB2Periph_USART1 , ENABLE);   

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2 |

              RCC_APB1Periph_USART3 |RCC_APB1Periph_TIM2 |

                                        RCC_APB1Periph_TIM3, ENABLE);     

}

void NVIC_Configuration(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x3000);    

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

   

    /* Enable the USART1 Interrupt */                        //3rd - High Priority

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    /* Enable the USART2 Interrupt */                        //2nd

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    /* Enable the USART3 Interrupt */                        //1st High Priority

    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

    /* Enable the TIM2 gloabal Interrupt */

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    /* Enable the TIM3 gloabal Interrupt */

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

}

void TIM2_IRQHandler(void)

{   

    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);

    Tim2_Counter+=1;     

}

void TIM3_IRQHandler(void)

{

    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);       

    Tim3_Counter+=1;       

}

Both the counter variables are declared globally.

void main(void)

{

    RCC_Configuration();

    NVIC_Configuration();

    Timer2_Init();

    Timer3_Init();

    Timer2_Enable();

    Timer3_Enable();

    while(1)

    {

         if(Tim2_Counter>=200)

        {

            Timer2_Disable();

            Tim2_Counter=0;

            SendLength(++j,USART1);     //print the count every2 secs

            CRLF();           

            Timer2_Enable();

        }

         if(Tim3_Counter==10)

        {

            Timer3_Disable();

            Tim3_Counter=0;

            SendLength(++i,USART1);     //print every 1 secs

            CRLF();

            Timer3_Enable();

        }

    }

}

Seems that the problem arised once i had initialised for the timer 3 interrupt.

Once this has done even the timer 2 interrupt doesnt work.

In short the timers work fine if there is either timer2 or timer 3.

If both used then none works.

ezyreach
Associate II
Posted on July 01, 2011 at 14:41

In my earlier post i forgot add the timer init functions.

void Timer2_Init(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure2;

   

    /* Time base configuration */

    TIM_TimeBaseStructure2.TIM_Period = 9;                //10mS delay

    TIM_TimeBaseStructure2.TIM_Prescaler = 23999;

    TIM_TimeBaseStructure2.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure2.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure2);

    TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);            /* TIM IT disable */

    TIM_Cmd(TIM2, DISABLE);                                /* TIM2 disable counter */

}

void Timer3_Init(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure3;

    TIM_TimeBaseStructure3.TIM_Period= 99;                    //100mS Delay

    TIM_TimeBaseStructure3.TIM_Prescaler= 23999;

    TIM_TimeBaseStructure3.TIM_ClockDivision=0;

    TIM_TimeBaseStructure3.TIM_CounterMode=TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure3);

    TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);            /* TIM IT disable */

    TIM_Cmd(TIM3, DISABLE);                                /* TIM3 disable counter */

}

void Timer2_Enable(void)

{

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);            /* TIM IT enable */

    TIM_Cmd(TIM2, ENABLE);                            /* TIM2 enable counter */

}

void Timer3_Enable(void)

{

    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);            /* TIM IT enable */

    TIM_Cmd(TIM3, ENABLE);                            /* TIM3 enable counter */   

}

void Timer2_Disable(void)

{

    TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);            /* TIM IT disable */

    TIM_Cmd(TIM2, DISABLE);                                /* TIM2 disable counter */

}

void Timer3_Disable(void)

{

    TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);            /* TIM IT disable */

    TIM_Cmd(TIM3, DISABLE);       

}

ezyreach
Associate II
Posted on July 04, 2011 at 09:24

Any error in the above posted code?

As the timer 3 is running but the timer 2 is not running.

Please help me to locate where the error is.