cancel
Showing results for 
Search instead for 
Did you mean: 

Software triggered One Pulse Mode – more than once

EThom.3
Senior II

Hi,

I'm trying to generate a pulse of a fixed length when my application triggers it, on one of two timer outputs, depending on a boolean value. My problem is that it works only once. The first time I start the timer, I get a nice pulse, but the subsequent times I get nothing. The outputs stay low. My guess is that I need to "re-arm" the pulse generation, but I can't figure out how to do so – or if that is even the issue.

My "triggering code" is here. Several code lines are probably unnecessary, but have been added out of pure deperation.

void SetShutterState(bool State)
{
  TIM15->CR1 &=~ TIM_CR1_CEN; // Stopping timer. I don't think this is necessary.
  TIM15->SR = 0; // Clearing status bits. Probably not necessary either.
  TIM15->CNT = 0; // Setting counter value to 0. Just in case - shouldn't be nevessary.

  TIM15->CR1 |= TIM_CR1_OPM; // Setting One Pulse Mode. I doubt that this is necessary every time.
  TIM15->CCER = TIM_CCER_CC2E | TIM_CCER_CC1E; // Enabling timer outputs

  // Set one output to OC, the other forced low.
  if (State) TIM15->CCMR1 = (4 << TIM_CCMR1_OC2M_Pos) | TIM_CCMR1_OC2PE | (2 << TIM_CCMR1_OC1M_Pos) | TIM_CCMR1_OC1PE;
  else TIM15->CCMR1 = (2 << TIM_CCMR1_OC2M_Pos) | TIM_CCMR1_OC2PE | (4 << TIM_CCMR1_OC1M_Pos) | TIM_CCMR1_OC1PE;

  TIM15->BDTR = TIM_BDTR_MOE; // Master output enable
  TIM15->CR1 |= TIM_CR1_CEN; // Start timer
}

Elsewhere I've set prescaler, ARR and CCR1 and 2:

PSC = 0xA9

ARR = 0xFFFF

CCR1 = 0x3A98

CCR2 = 0x3A98

This generates the correct pulse width. But as mentioned, it only happens the first time I run the function.

Also, SMCR = 0

 

For the output that is to be pulsed, I use mode 2: "Set channel 1 to inactive level on match. tim_oc1ref signal is forced low when the counter TIM15_CNT matches the capture/compare register 1 (TIM15_CCR1)." This pretty much describes what I wish to do, except it doesn't say explicitly that the channel output is forced high in the beginning. But it does so the first time after MCU reset.

According to this post https://community.st.com/t5/stm32-mcus-products/starting-timers-in-one-pulse-mode/m-p/285441#M66101 setting CR_CEN high should be enough to activate the timer, and it shouldn't need a hardware trigger.

Does anyone know if I need to reactivate something after each pulse? Or am I going in the completely wrong direction?

 

Edit: In the code exerpt, preload is enabled (OC1PE and OC2PE), which it shouldn't be. Disabling them made no difference, though.

1 ACCEPTED SOLUTION

Accepted Solutions
EThom.3
Senior II

Problem solved. I have changed

  if (State) TIM15->CCMR1 = (4 << TIM_CCMR1_OC2M_Pos) | (2 << TIM_CCMR1_OC1M_Pos);
  else TIM15->CCMR1 = (2 << TIM_CCMR1_OC2M_Pos) (4 << TIM_CCMR1_OC1M_Pos);

to

  if (State)
  {
    TIM15->CCMR1 = (4 << TIM_CCMR1_OC2M_Pos) | (5 << TIM_CCMR1_OC1M_Pos);
    TIM15->CCMR1 = (4 << TIM_CCMR1_OC2M_Pos) | (2 << TIM_CCMR1_OC1M_Pos);
  }
  else
  {
    TIM15->CCMR1 = (5 << TIM_CCMR1_OC2M_Pos) | (4 << TIM_CCMR1_OC1M_Pos);
    TIM15->CCMR1 = (2 << TIM_CCMR1_OC2M_Pos) | (4 << TIM_CCMR1_OC1M_Pos);
  }

and it works. Apparently, setting CCMR1_OCxM to 5 sets the initial state for the subsequent OC operation.

I am still not sure why it worked with the first pulse, though. But, in any case, it works now, And I am happy.

View solution in original post

1 REPLY 1
EThom.3
Senior II

Problem solved. I have changed

  if (State) TIM15->CCMR1 = (4 << TIM_CCMR1_OC2M_Pos) | (2 << TIM_CCMR1_OC1M_Pos);
  else TIM15->CCMR1 = (2 << TIM_CCMR1_OC2M_Pos) (4 << TIM_CCMR1_OC1M_Pos);

to

  if (State)
  {
    TIM15->CCMR1 = (4 << TIM_CCMR1_OC2M_Pos) | (5 << TIM_CCMR1_OC1M_Pos);
    TIM15->CCMR1 = (4 << TIM_CCMR1_OC2M_Pos) | (2 << TIM_CCMR1_OC1M_Pos);
  }
  else
  {
    TIM15->CCMR1 = (5 << TIM_CCMR1_OC2M_Pos) | (4 << TIM_CCMR1_OC1M_Pos);
    TIM15->CCMR1 = (2 << TIM_CCMR1_OC2M_Pos) | (4 << TIM_CCMR1_OC1M_Pos);
  }

and it works. Apparently, setting CCMR1_OCxM to 5 sets the initial state for the subsequent OC operation.

I am still not sure why it worked with the first pulse, though. But, in any case, it works now, And I am happy.