Monday 20 April 2009

pulse timers

As I need a short pulse to fire the triacs I checked upon the possibilities of the other timers. TIM2,3 and 4 act as general purpose timers and are well suited for the job. I experimented with PWM mode but I found it not so good in my case. I decided to toggle the IOs manually on compare match events. The good thing is that you have 4 compare match events per timer. This opens up a lot of possibilities. I will put the principal of working here using TIM2 as an example but in fact I use all 3 of them to fire 6 triacs in total. The first thing to do is setting the period of the timer. In my case this must be set to 10ms as we work with 50HZ/20ms mains frequency. We must fire for the positive as well as for the negative sine wave so that makes a period of 10ms.

/* Time 2 base configuration 10ms */
TIM_TimeBaseStructure.TIM_Period = 9999;
TIM_TimeBaseStructure.TIM_Prescaler = 72;
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

Period calculation:

72MHz / 72 = 1MHz or 1µs period unit.
1µs + 9999 x (1µs) = 10ms

Now we need just a little bit more to set up comparing to TIM1 because we want to use the compare matches. This is done initializing the OC_struct with ride;

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = triacvalue;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);

This one above sets the CC1 to trigger at triacvalue. This trigger will be signalled with an interrupt. The preload must be disabled to able to change the compare value at run time. Be aware to put OCMode to TIM_OCMode_Inactive because otherwise the timer output lines are enabled. In this design I wanted to select my own gpio pins.

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = triacvalue + 50;
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);

The second compare match will be just a bit later than first one to make our short fire pulse. In this case we make a pulse of 50µs. This process of setting up the compare matches repeats over all the timers you want to bind with some interrupt event. The NVIC interrupt controller must be set as follows:

/* Enable the TIM2 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

The only thing you need to do after that is writing your code in the interrupt handler and don't forget to start the timer clock which is different from the TIM1 :

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);


You interrupt handler code might be :

void TIM2_IRQHandler(void)
if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
GPIO_SetBits(GPIOC, GPIO_Pin_9);
else if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
GPIO_ResetBits(GPIOC, GPIO_Pin_9);

Also here as simply as that. So the pulses are made by toggling the gpios on interrupt events. You can also change your interrupt priority here. But there i will cover that later on as there's plenty to say on it.

Complexity is completely avoided in this architecture. The speed of writing code is highly increased if you use the ride firmware library for the arm target. You have to download the rkit for arm to be able to use this and that library in your ride IDE.

1 comment:

  1. if(TIM_GetITStatus(TIM2, TIM_IT_CC1)!=RESET)

    what does this line check for? What does TIM_IT_CC1 stand for? I didn't get this condition...can u plz explain?