2011-10-25 11:02 AM
Hi all,
I have a strange problem using Timer1 in Output Toggle mode. My objective is to generate square waves of different frequencies using the same timer. I've based my code on the 'TIM_OCToggle' example in the Standard Peripheral Library documentation.I'm using an IAR STM32-SK Starter Kit dev board (STM32F103RB). I've also tested my code on the Olimex H-103 dev board.When I use the example from the documentation, which uses Timer 3, the code works perfectly.However, when I attempt to change to Timer 1 - I get absolutely no switching on the Timer 1 outputs (I'm using pins A8 and A9 - channel 1 and 2). When I run the code in Download and Debug mode, I can see that the program sequence works as I expect, and that the program enters the TIM1_CC interrupt handler. However the output does not switch.I've ensured that pins A8 and A9 are initialised, that I'm not running any remap function, that clocks are being directed to Port A and AFIO and Timer1.I'd appreciate any advice on what might be happening. Thanks! (I've attached my code below)void main(void){
SystemInit();
RCC_Configuration();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
NVIC_Configuration();
GPIO_InitTypeDef GPIO_InitStructure7;
GPIO_InitStructure7.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure7.GPIO_Mode = GPIO_Mode_FF_PP;
GPIO_InitStructure7.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOA, &GPIO_InitStructure7);
GPIO_InitStructure7.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOA, &GPIO_InitStructure7);
initialiseTimers();
while(1);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void RCC_Configuration(void)
{
/* RCC system reset(for debug purpose) */
RCC_DeInit();
/* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON);
/* Wait till HSE is ready */
if(RCC_WaitForHSEStartUp() == SUCCESS)
{
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div4);
/* Flash 2 wait state */
FLASH_SetLatency(FLASH_Latency_2);
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
/* PLLCLK = 8MHz * 9 = 72 MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08)
{
}
}
}
void initialiseTimers(void)
{
Int16U PrescalerValue = 0;
TIM_TimeBaseInitTypeDef TIM1_TimeBaseInitStruct;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM1_TimeBaseInitStruct.TIM_Period = 300;
TIM1_TimeBaseInitStruct.TIM_Prescaler = PrescalerValue;
TIM1_TimeBaseInitStruct.TIM_ClockDivision = 0;
TIM1_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseInitStruct);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1000;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable);
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1002;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Disable);
TIM_Cmd(TIM1, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
}
void TIM1_CC_IRQHandler(void)
{
uint16_t capture;
/* TIM1_CH1 toggling with frequency = */
if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC1 );
capture = TIM_GetCapture1(TIM1);
TIM_SetCompare1(TIM1, capture + 1000);
}
/* TIM1_CH2 toggling with frequency = */
if (TIM_GetITStatus(TIM1, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM1, TIM_IT_CC2);
capture = TIM_GetCapture2(TIM1);
TIM_SetCompare2(TIM1, capture + 1002);
}
}
}
2011-10-25 02:08 PM
So if the period is 300 (should be N-1 btw), how precisely will it get to 1000+ ? I'm not familiar with OC mode, but in PWM which is very effective a frequency generation the counter is trapped in 0..300 in your example
TIM1_TimeBaseInitStruct.TIM_Period = 300;
TIM1_TimeBaseInitStruct.TIM_Prescaler = PrescalerValue;
TIM1_TimeBaseInitStruct.TIM_ClockDivision = 0; TIM1_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseInitStruct); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1000; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Disable); TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 1002; TIM_OC2Init(TIM1, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Disable); TIM_Cmd(TIM1, ENABLE); TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);GPIO_InitStructure7.GPIO_Mode = GPIO_Mode_AF_PP;
2011-10-25 04:24 PM
Ah, that should have read 65535. That's the problem with trying lots of different things to fix the issue and not changing everything back.
Unfortunately the problem still exists - even with the timer period at 65535, nothing switches. Any other ideas? Thanks!2012-11-01 03:36 PM
I have discovered the same problem. I wanted to generate clock frequency for a codec. The difference was that no timer interrupt was needed.
It seems that Output Toggle mode of Timer 1 does not work. I had to use the PWM mode.2012-11-02 03:55 AM
The interrupt technique is one of advancing the CCRx values, and permitting multiple frequencies to be generated from the rather crude timer/prescaler/channel implementation in the part. The saturation point of the processor being a limiting factor here, and a failure to meet the timing window.
TIM1/TIM8 require more through initialization, but I'm not wholly convinced that TIM1 can't toggle in output compare mode. I might try to refute this if I get bored.2012-11-05 12:34 AM
Without attempting to understand the problem: isn't the problem in the need to enable the MOE bit for the advanced timers' outputs?
JW