cancel
Showing results for 
Search instead for 
Did you mean: 

Timer Compare Output - How to rearm timer

Rob Peck
Associate
Posted on May 16, 2018 at 10:08

Board/Processor : STM32L476RG-Nucleo

Example code from: STM32Cube_FW_L4_V1.10.0

ARM IAR compiler V8.

I can successfully build and run the TIM_OCActive / TIM_OCInactive examples on the above board, they produce the required output pulses as described in the readme file.

I also successfully built a new project from scratch using the cube, to generate a 250mS pulse on the LED PA.5.

Unfortunately what I cant do is to generate another pulse ie user presses a button to generate another timed pulse.  I know I could use a basic timer set the pin high, then set the pin low when the timer interrupt fires, however I need a hardware controlled solution such that if the firmware was to fail in some way the output would still be turned off.  Which I understand I can do using the timer compare output once I can figure out how to rearm it.

The documentation for the timers and project examples don't describe how to rearm the timer to generate a new timed output pulse.  I have tried re-initialising the timer, I tried stopping and then starting the timer using the HAL functions all have no effect.

Has anyone managed to rearm the timer to generate a second or multiple pulses?

4 REPLIES 4
T J
Lead
Posted on May 16, 2018 at 14:45

I use a timer and rearm it to wait_mS();

void init_mS_Wait_Timer(void) {
 HAL_TIMEx_OCN_Start(&htim2, TIM_CHANNEL_1); // no interrupt call back is initialised on TOC channel
}

void wait_ms(int _mS) {
 resetTim2ChannelCounter(&htim2, 1);
 do {
 waitTim2ChannelComplete(&htim2, 1);
 } while (--_mS > 0);
}

void resetTim2ChannelCounter(TIM_HandleTypeDef *htim, uint32_t channel) {
 uint32_t tmp;
 tmp = htim->Instance->CNT;
 switch (channel) {
 // used to have &=
 case 1 : {
 htim->Instance->CCR1 = tmp;
 htim->Instance->SR = !TIM_SR_CC1IF; // clear the flag 
 break;
 }
}

void waitTim2ChannelComplete(TIM_HandleTypeDef *htim, uint32_t channel) {
 uint32_t tmp;
 tmp = 0;
 while (!tmp) {
 checkBackgroundServices(); // checking state machines while waiting.
 switch (channel) {
 case 1:
 tmp = htim->Instance->SR & TIM_SR_CC1IF;
 break;
 case 2:
 tmp = htim->Instance->SR & TIM_SR_CC2IF;
 break;
 case 3:
 tmp = htim->Instance->SR & TIM_SR_CC3IF;
 break;
 case 4:
 tmp = htim->Instance->SR & TIM_SR_CC4IF;
 break; 
 }
 }
 switch (channel) {
case 1 : {
 htim->Instance->SR = !TIM_SR_CC1IF; // clear the flag 
 break;
 }
 case 2: {
 htim->Instance->SR = !TIM_SR_CC2IF; // clear the flag
 break;
 }
 case 3: {
 htim->Instance->SR = !TIM_SR_CC3IF; // clear the flag
 break;
 }
 case 4: {
 htim->Instance->SR = !TIM_SR_CC4IF; // clear the flag
 break;
 }
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

henry.dick
Senior II
Posted on May 16, 2018 at 14:58

Read the datasheet about single pulse mode.

Posted on May 16, 2018 at 22:37

There are many ways to skin a cat.

One of them may be: start from the Set Active On Match example; upon keypress detected, stop the timer by clearing TIMx_CR1.CEN, write 0 into TIMx_CNT, set output compare mode in TIMx_CCMRy.OCzM momentarily to Force Inactive to clear the output, set it back to Set Active On Match, and then enable the timer (TIMx_CR1.CEN = 1).

Another may utilize the One-Pulse mode mentioned by dhenry above (see TIMx_CR1.OPM), using one of the PWM modes; this may be triggered also purely in hardware from another channel of the same timer (I have a barebones example on efton.sk for something similar under 'selfdisable', but it's somewhat more involved and... well... self-disables which is what you don't want).

Reading the TIM chapter in RM is always a good starting point.

JW

Rob Peck
Associate
Posted on May 17, 2018 at 13:16

Thank you for all your assistance.

JW your first suggestion got me going.

To get the timer to rearm and thus generate a new positive pulse in Active mode on the output OCx Pin I changed the mode OCxM to 'Forced Inactive' (drives the output high on OCx) then immediately set the mode OCxM to Active which enables the timer to countdown when the counter reaches the Compare value CCRx the output OCx returns low.  Performing this routine again while a pulse is still in progress restarts the counting period again.