Skip to main content
joesoftware
Associate III
March 14, 2013
Question

TIMER with discovery

  • March 14, 2013
  • 6 replies
  • 1371 views
Posted on March 14, 2013 at 20:07

I modify TIM Time Base example for learn more about timer, i blink led with timer, my code works well but i didn't understand instructions

This is my code:

/** 
****************************************************************************** 
* @file TIM/TimeBase/main.c 
* @author MCD Application Team 
* @version V3.5.0 
* @date 08-April-2011 
* @brief Main program body 
****************************************************************************** 
* @attention 
* 
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 
* 
* <
h2
><
center
>© COPYRIGHT 2011 STMicroelectronics</
center
></
h2
> 
****************************************************************************** 
*/ 
/* Includes ------------------------------------------------------------------*/ 
#include ''stm32f10x.h'' 
#include ''stm32vldiscovery.h'' 
/** @addtogroup STM32F10x_StdPeriph_Examples 
* @{ 
*/ 
/** @addtogroup TIM_TimeBase 
* @{ 
*/ 
/* Private typedef -----------------------------------------------------------*/ 
/* Private define ------------------------------------------------------------*/ 
/* Private macro -------------------------------------------------------------*/ 
/* Private variables ---------------------------------------------------------*/ 
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
TIM_OCInitTypeDef TIM_OCInitStructure; 
__IO uint16_t CCR1_Val = 40961; 
uint16_t PrescalerValue = 0; 
/* Private function prototypes -----------------------------------------------*/ 
void RCC_Configuration(void); 
void GPIO_Configuration(void); 
void NVIC_Configuration(void); 
/* Private functions ---------------------------------------------------------*/ 
/** 
* @brief Main program 
* @param None 
* @retval None 
*/ 
int main(void) 
{ 
/*!< At this stage the microcontroller clock setting is already configured, 
this is done through SystemInit() function which is called from startup 
file (startup_stm32f10x_xx.s) before to branch to application main. 
To reconfigure the default setting of SystemInit() function, refer to 
system_stm32f10x.c file 
*/ 
/* System Clocks Configuration */ 
RCC_Configuration(); 
/* NVIC Configuration */ 
NVIC_Configuration(); 
/* GPIO Configuration */ 
GPIO_Configuration(); 
STM32vldiscovery_LEDOn(LED3); 
STM32vldiscovery_LEDOff(LED4); 
/* Compute the prescaler value */ 
PrescalerValue = (uint16_t) (SystemCoreClock / 12000000) - 1; 
/* 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(TIM2, &TIM_TimeBaseStructure); 
/* Prescaler configuration */ 
TIM_PrescalerConfig(TIM2, 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(TIM2, &TIM_OCInitStructure); 
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable); 
/* TIM IT enable */ 
TIM_ITConfig(TIM2, TIM_IT_CC1 , ENABLE); 
/* TIM2 enable counter */ 
TIM_Cmd(TIM2, ENABLE); 
while (1); 
} 
/** 
* @brief Configures the different system clocks. 
* @param None 
* @retval None 
*/ 
void RCC_Configuration(void) 
{ 
/* PCLK1 = HCLK/4 */ 
RCC_PCLK1Config(RCC_HCLK_Div16); 
/* TIM2 clock enable */ 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 
/* GPIOC clock enable */ 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); 
} 
/** 
* @brief Configure the GPIO Pins. 
* @param None 
* @retval None 
*/ 
void GPIO_Configuration(void) 
{ 
GPIO_InitTypeDef GPIO_InitStructure; 
/* GPIOC Configuration:Pin 8 and 9 as alternate function push-pull */ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOC, &GPIO_InitStructure); 
} 
/** 
* @brief Configure the nested vectored interrupt controller. 
* @param None 
* @retval None 
*/ 
void NVIC_Configuration(void) 
{ 
NVIC_InitTypeDef NVIC_InitStructure; 
/* Enable the TIM2 global Interrupt */ 
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 
} 
#ifdef USE_FULL_ASSERT 
/** 
* @brief Reports the name of the source file and the source line number 
* where the assert_param error has occurred. 
* @param file: pointer to the source file name 
* @param line: assert_param error line source number 
* @retval None 
*/ 
void assert_failed(uint8_t* file, uint32_t line) 
{ 
/* User can add his own implementation to report the file name and line number, 
ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */ 
while (1) 
{} 
} 
#endif 
/** 
* @} 
*/ 
/** 
* @} 
*/ 
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 

My problems are: if TIM2 counter clock at 24/16 and CC1 update rate = TIM2 counter clock / CCR1_Val How can i chose TIM_TimeBaseStructure.TIM_Period = 65535; what will i change if i use another value? And why more instruction about prescale? PrescalerValue = (uint16_t) (SystemCoreClock / 1200000) - 1; TIM_TimeBaseStructure.TIM_Prescaler = 0 ; whats the different use of that? If i want 500ms timer how can i configure this value? Thanks
    This topic has been closed for replies.

    6 replies

    Tesla DeLorean
    Guru
    March 14, 2013
    Posted on March 15, 2013 at 00:49

    So where is the interrupt handler? Are you advancing the TIM2->CCR1 to generate the frequency?

    Your TIM2 clock is probably 3 MHz, if the CPU is running at 24 MHz, look at the clock tree in the manual to understand this relationship.

    Generating 2 Hz from 3 MHz, you'd need to divide the source by 1500000 which won't fit in 16 bit.

    I personally would use the Update interrupt, Set the Period to 50000-1 and Prescale to 30-1, this is achieved with some rudimentary factoring, there are dozens of other combinations that would work.

    2 x 50000 x 30 = 3 MHz
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    joesoftware
    Associate III
    March 15, 2013
    Posted on March 15, 2013 at 09:39

    Thanks clive1

    This is my interrupt handler

    void TIM2_IRQHandler(void) 
    { 
    if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) 
    { 
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); 
    STM32vldiscovery_LEDToggle(LED3); 
    STM32vldiscovery_LEDToggle(LED4); 
    } 
    }

    I understand what u wrote. I can't understand why 3MHZ i think /* PCLK1 = HCLK/16 */ RCC_PCLK1Config(RCC_HCLK_Div16); generates 1.5MHz? If i want to set prescalevalue to 30 what instruction need to change? i can't understand why i have 2 instruction different: /* Compute the prescaler value */ PrescalerValue = (uint16_t) (SystemCoreClock / 1200000) - 1; and TIM_TimeBaseStructure.TIM_Prescaler = 0 ; Last One thing where i use

    CCR1_Val = 40961;

    if all my clock was configured to 2 x 50000 x 30 = 3 MHz i read in help of this code that he use CC1 update rate = TIM2 counter clock / CCR1_Val Thanks
    Tesla DeLorean
    Guru
    March 15, 2013
    Posted on March 15, 2013 at 10:05

    The code changes the prescaler later, but I think you need to re-read the chapter on timers in the manual. It is the period/prescale value that alter the periodicity of the counter, the output compare could be used for phase, but will not generate a frequency unless you keep advancing the trigger point.

    For a simple 2 Hz interrupt, from a 24 MHz * 2 / 16 clock the following should suffice.

    #include ''stm32f10x.h''
    #include ''stm32vldiscovery.h''
    void RCC_Configuration(void);
    void GPIO_Configuration(void);
    void NVIC_Configuration(void);
    int main(void)
    {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    /* System Clocks Configuration */
    RCC_Configuration();
    /* NVIC Configuration */
    NVIC_Configuration();
    /* GPIO Configuration */
    GPIO_Configuration();
    STM32vldiscovery_LEDOn(LED3);
    STM32vldiscovery_LEDOff(LED4);
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = 50000-1;
    TIM_TimeBaseStructure.TIM_Prescaler = 30-1 ;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    /* TIM IT enable */
    TIM_ITConfig(TIM2, TIM_IT_Update , ENABLE);
    /* TIM2 enable counter */
    TIM_Cmd(TIM2, ENABLE);
    while (1);
    }
    void RCC_Configuration(void)
    {
    /* PCLK1 = HCLK/4 */
    RCC_PCLK1Config(RCC_HCLK_Div16);
    /* TIM2 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    /* GPIOC clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    }
    void GPIO_Configuration(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    /* GPIOC Configuration:Pin 8 and 9 as push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    }
    void NVIC_Configuration(void)
    {
    NVIC_InitTypeDef NVIC_InitStructure;
    /* Enable the TIM2 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    }
    void TIM2_IRQHandler(void)
    {
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    STM32vldiscovery_LEDToggle(LED3);
    STM32vldiscovery_LEDToggle(LED4);
    }
    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    March 15, 2013
    Posted on March 15, 2013 at 10:12

    I can't understand why 3MHZ i think  

     

    /* PCLK1 = HCLK/16 */

     

      RCC_PCLK1Config(RCC_HCLK_Div16);

     

    generates 1.5MHz?

     

     

    From the Clock Tree in the Reference Manual

    0690X00000605GsQAI.png
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    joesoftware
    Associate III
    March 15, 2013
    Posted on March 15, 2013 at 10:34

    Thanks

    for your patience.

    I forgot that

    apb1

    doubles the

    clock

    timers

    .

    I will read again timer chapter, i think now it will be more easy.

    Thanks

    Tesla DeLorean
    Guru
    March 15, 2013
    Posted on March 15, 2013 at 11:06

    The description is a bit deceptive, it doesn't really double it, rather it takes a clock from further up the divider chain. So the operation isn't /16 then x2 but rather just /8

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..