2013-03-14 12:07 PM
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
2013-03-14 04:49 PM
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 MHz2013-03-15 01:39 AM
Thanks clive1
This is my interrupt handlervoid 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 Thanks2013-03-15 02:05 AM
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);
}
}
2013-03-15 02:12 AM
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
2013-03-15 02:34 AM
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. Thanks2013-03-15 03:06 AM
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