cancel
Showing results for 
Search instead for 
Did you mean: 

Using all channels of Timer 3

daniel2
Associate II
Posted on June 23, 2014 at 16:22

I'd like to use all channels of Timer 3 to generate different clocks and timers.

Channel 1- 10ms timer interrupt Channel 2- 250us timer interrupt Channel 3- 50kHz clock (50%) on PB0 Channel 4- 256kHz clock (50%) on PB1 The problems I'm having are:
  1. I believe I need to use the CCR for this and I don't know how to configure that without getting it to do the output compare and toggle the I/O
  2. I can't get a clock over 5kHz on any of the I/Os (75kHz update

    rate)

void Timer3_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOB clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
/* GPIOB Configuration: TIM3 CH3 (PB0) and TIM3 CH4 (PB1) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Connect TIM Channels to AF1 */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_1);
/* Enable the TIM3 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* ---------------------------------------------------------------------------
TIM3 Configuration: Output Compare Toggle Mode:
In this example TIM3 input clock (TIM3CLK) is set to APB1 clock (PCLK1).
=> TIM3CLK = PCLK1 = 48 MHz
CC3 update rate = TIM3 counter clock / CCR3_Val = 75000 Hz
==> So the TIM3 Channel 3 generates a periodic signal with a 
frequency equal to 37500 Hz.
CC4 update rate = TIM3 counter clock / CCR4_Val = 9375 Hz
==> So the TIM3 Channel 4 generates a periodic signal with a 
frequency equal to 465 Hz. 
--------------------------------------------------------------------------- */ 
/* 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);
/* Output Compare Toggle Mode configuration: Generic */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
/* Output Compare Toggle Mode configuration: Channel 3 */
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 Toggle Mode configuration: Channel 4 */
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 enable counter */
TIM_Cmd(TIM3, ENABLE);
/* TIM IT enable */
TIM_ITConfig(TIM3, TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
}

#assert.h
5 REPLIES 5
Posted on June 23, 2014 at 16:29

Understand that each timer only has a SINGLE counting element.

To generate different periodicity from different channels, you'd need to keep advancing the CCRx comparator setting at EACH interrupt.

So you'd want to use the prescaler to set the time base of the counter, say 1 us (1 MHz), and set the period maximal, ie 0xFFFF for 16-bit and 0xFFFFFFFF for 32-bit timers.

For a 250us interrupt you'd need to do TIMx->CCRx += 250; at each interrupt to advance the comparator.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
daniel2
Associate II
Posted on June 23, 2014 at 17:11

The problem is that when I push the update rate too high the clock starts to break down. For example I have CCR3_Val = 8 and CCR4_Val = On channel 4 I get a 5kHz clock as expected for a 125kHz update rate but on channel 3 I have a 28Hz clock. It seems that when I push the GPIO toggle rate above around 80kHz it starts to break down. Is there something else I need to configure to avoid this or is this beyond the capability of the micro?

/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF;
TIM_TimeBaseStructure.TIM_Prescaler = 12; //4MHz
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
void TIM3_IRQHandler(void)
{
/* TIM3_CH3 toggling with frequency = 37500 Hz */
if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
capture = TIM_GetCapture3(TIM3);
TIM_SetCompare3(TIM3, capture + CCR3_Val);
}
/* TIM3_CH4 toggling with frequency = 37500 Hz */
if (TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
capture = TIM_GetCapture4(TIM3);
TIM_SetCompare4(TIM3, capture + CCR4_Val);
}
}

Posted on June 23, 2014 at 17:24

Yes, because at some point you saturate the processor with interrupts. You don't specify a processor or the speed it's running at, but 100 KHz interrupts would have 720 machine cycles on a 72 MHz STM32F1, and flash accesses (execution) would eat 3 cycles.

The way you solve this is to use different timers to generate different frequencies, and let the hardware toggle the pins. For servo type applications where all the channels are the same frequency (50 Hz, 20 ms), you can use all four channels, and alter the duty with the CCRx registers.

The STM32 timers, integer dividers and clocking scheme are pretty weak. For specific frequencies you might have to run the processor at sub optimal speeds, or use magic crystal values. If you have exotic requirements consider an PLD/FPGA solution.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
daniel2
Associate II
Posted on June 23, 2014 at 18:26

Sorry, part number is STM32F030 running at 48MHz off HSI.

os_kopernika
Associate II
Posted on June 24, 2014 at 00:23

''The problem is that when I push the update rate too high the clock starts to break down.''

That is what happens when the code is based on false assumptions. You can use such line in an IRQ to verify if assumptions hold:

assert(TIM3->CNT <= IRQ_ACCEPTABLE_DELAY);