cancel
Showing results for 
Search instead for 
Did you mean: 

How to stop PWM after 22 clocks

StevenG
Associate III

I want to stop generating a PWM signal after 22 clock edges.  It seems like the TIMx_RCR register (repetition counter register) should work for this.

 

My code started from the CubeMX generated code but I have had to remove a lot of it for performance reasons.  I am running an STM32H523 with a SYSCLK of 250MHz.  The PWM is about 650 KHz so I need to disable the output about 33 us after I start it.  That timing is a little tight to do with an interrupt counting down from 22 to zero; however, that seems to be exactly what the TIMx_RCR register does in hardware.

 

My current code uses the HAL_TIM_PWM_PulseFinishedCallback() function but it seems that it is being called for every pulse, not every 22 pulses.

 

Does anyone have some pointers or code examples for how to setup TIM1 on an STM32H523?  I am using STM32CubeIDE v 1.19.0 (because 2.0.0 broke my build).

1 ACCEPTED SOLUTION

Accepted Solutions
StevenG
Associate III

I'm not sure if it is considered bad form to reply to your own question but here is how I solved this problem.

 

1) Changed TIM1_UP_IRQHandler() in stm32h5xx_it.c to be __weak

/**
  * @brief This function handles TIM1 Update interrupt.
  */
__weak void TIM1_UP_IRQHandler(void)
{
  /* USER CODE BEGIN TIM1_UP_IRQn 0 */

  /* USER CODE END TIM1_UP_IRQn 0 */
  HAL_TIM_IRQHandler(&htim1);
  /* USER CODE BEGIN TIM1_UP_IRQn 1 */

  /* USER CODE END TIM1_UP_IRQn 1 */
}

 

2) Added my own interrupt handler in my own file:

 

void TIM1_UP_IRQHandler( void )
{

   SONAR_state = SONAR_PING_LISTEN;

   __HAL_TIM_CLEAR_FLAG( &htim1, TIM_FLAG_UPDATE);

   HAL_TIM_PWM_Stop( &htim1, TIM_CHANNEL_1 );
   HAL_TIMEx_PWMN_Stop( &htim1, TIM_CHANNEL_1 );

  return;
} // end of TIM1_UP_IRQHandler()

 

3) Enabled the Update interrupt without using HAL_TIM....IT() function:

   // Setup TIM1_CH1 (PA8) TXPULSE_B and TIM1_CH1N (PA7) TXPULSE_A for Sonar output pulse transformer
   HAL_TIM_PWM_Start( &htim1, TIM_CHANNEL_1 );
   HAL_TIMEx_PWMN_Start( &htim1, TIM_CHANNEL_1 );

   // Enable TIM1 Update interrupt
   __HAL_TIM_ENABLE_IT( &htim1, TIM_IT_UPDATE);


   while( SONAR_state == SONAR_PING_ACTIVE )
   {
      asm( "nop" );	// NOP
   }

   // Finished sending ping
   TIM1->CR1 &= ~TIM_CR1_CEN;	// The __HAL_TIM_DISABLE disable call is kind of large
   __HAL_TIM_DISABLE_IT( &htim1, TIM_IT_UPDATE);

4)  Stopped TIM1 when the flag was set in the interrupt handler (line 15 above)

 

One downside of this solution is that I had to change a generated file within the auto-generated section so it will break if I regenerate the code from the .ioc file.  The resulting waveform (from the transducer side of the transformer) is below.

 

Sonar_TX_Pulse_Dec10.png

View solution in original post

3 REPLIES 3
StevenG
Associate III

I'm not sure if it is considered bad form to reply to your own question but here is how I solved this problem.

 

1) Changed TIM1_UP_IRQHandler() in stm32h5xx_it.c to be __weak

/**
  * @brief This function handles TIM1 Update interrupt.
  */
__weak void TIM1_UP_IRQHandler(void)
{
  /* USER CODE BEGIN TIM1_UP_IRQn 0 */

  /* USER CODE END TIM1_UP_IRQn 0 */
  HAL_TIM_IRQHandler(&htim1);
  /* USER CODE BEGIN TIM1_UP_IRQn 1 */

  /* USER CODE END TIM1_UP_IRQn 1 */
}

 

2) Added my own interrupt handler in my own file:

 

void TIM1_UP_IRQHandler( void )
{

   SONAR_state = SONAR_PING_LISTEN;

   __HAL_TIM_CLEAR_FLAG( &htim1, TIM_FLAG_UPDATE);

   HAL_TIM_PWM_Stop( &htim1, TIM_CHANNEL_1 );
   HAL_TIMEx_PWMN_Stop( &htim1, TIM_CHANNEL_1 );

  return;
} // end of TIM1_UP_IRQHandler()

 

3) Enabled the Update interrupt without using HAL_TIM....IT() function:

   // Setup TIM1_CH1 (PA8) TXPULSE_B and TIM1_CH1N (PA7) TXPULSE_A for Sonar output pulse transformer
   HAL_TIM_PWM_Start( &htim1, TIM_CHANNEL_1 );
   HAL_TIMEx_PWMN_Start( &htim1, TIM_CHANNEL_1 );

   // Enable TIM1 Update interrupt
   __HAL_TIM_ENABLE_IT( &htim1, TIM_IT_UPDATE);


   while( SONAR_state == SONAR_PING_ACTIVE )
   {
      asm( "nop" );	// NOP
   }

   // Finished sending ping
   TIM1->CR1 &= ~TIM_CR1_CEN;	// The __HAL_TIM_DISABLE disable call is kind of large
   __HAL_TIM_DISABLE_IT( &htim1, TIM_IT_UPDATE);

4)  Stopped TIM1 when the flag was set in the interrupt handler (line 15 above)

 

One downside of this solution is that I had to change a generated file within the auto-generated section so it will break if I regenerate the code from the .ioc file.  The resulting waveform (from the transducer side of the transformer) is below.

 

Sonar_TX_Pulse_Dec10.png

RobK1
Senior

I personally consider it excellent form to post the solution to a problem, because you never know how it might help others. So kudos to you!

Hello,


@StevenG wrote:

I'm not sure if it is considered bad form to reply to your own question but here is how I solved this problem.



That's the first role of the community: to share the solutions and the answers to the questions so others can serve themselves. That's a good practice to provide the answers to your questions and mark them as solutions.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.