cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 PWM to stop after n pluses

Wleon.1
Associate II

Is there a way to stop STM32 PWM after 10 pluses ?

I know one solution is using the system time and issue a stop via the code, however my issue is the stm CPU might be very busy to handle the stop signal.

19 REPLIES 19

Which STM32?

Use a timer which has the repetition counter (TIM_RTR), see TIM1/TIM8.

If there's no timer with TIM_RTR available, you can use another timer as master, in master-slave configuration, this timer in gated mode. Another option is to use DMA to load 0 into ARR or into CR1. Both these options are more complex than using the repetition counter.

JW

Thanks for your reply, but how do you load 0 into ARR using DMA ? Is there any example ?

In the same way as you'd write to any other TIM register using DMA. Read the TIM, DMA chapters in the Reference Manual, and the Timer Cookbook application note AN4776.

JW

Which STM32?

What frequency, and how busy?

The STM32 could get an update interrupt at each pulse. Or at multiples with the repetition count. At 8-bit provides for 1 thru 256 as I recall.

Posted examples to forum before doing N pulse PWM using One-Shot Mode + Repetition Count

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Thanks for the reply, I tried the TIM DMA, and got the DMA and TIM register to the following settings, however it seems that no interrupt is happening, I don't see the ARR change. Can you help me check if my settings are correct ?0693W000001rMPsQAM.png

Okay, from the screenshots we can guess it's 'F723. You should've told us.

DMA1 Stream 0 (set to Channel 2) is triggered by TIM4_CH1, you should've set TIM4_DIER.CC1DE for that.

Then that should work, but IMO it's better to leave the trigger from update (DIER.UDE=1 as it is now), and use the respective DMA1 Stream 6 (at channel 2).

JW

Hi thanks for the reply ! I have got the interrupt now and the DMA is running, however I encounter something very strange.

so I have set an data array

#define n 9
#define transfer 6
uint32_t buffer[n] = {500, 251, 252, 253, 504, 255, 506, 257, 258}; 
uint32_t DCR = 0x20B;

and I call the following function to kick start:

HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA_MODIFIED(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
{
  uint32_t tmpsmcr;
 
  /* Check the parameters */
  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
 
  if (htim->State == HAL_TIM_STATE_BUSY)
  {
    return HAL_BUSY;
  }
  else if (htim->State == HAL_TIM_STATE_READY)
  {
    if ((pData == NULL) && (Length > 0U))
    {
      return HAL_ERROR;
    }
    else
    {
      htim->State = HAL_TIM_STATE_BUSY;
    }
  }
  else
  {
    /* nothing to do */
  }
 
  switch (Channel)
  {
    case TIM_CHANNEL_1:
    {
      /* Set the DMA compare callbacks */
      htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseCplt;
      htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
 
      /* Set the DMA error callback */
      htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
 
      /* Enable the DMA stream */
      if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->DMAR, Length) != HAL_OK)  <----- i Change this from CCR1 to DMAR
      {
        return HAL_ERROR;
      }
 
      /* Enable the TIM Capture/Compare 1 DMA request */
      __HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
      break;
    }
 
    default:
      break;
  }
 
int main(void)
{
...
 
 htim4.Instance->ARR = 1000;
  htim4.Instance->CCR1 = 100;
  HAL_TIM_PWM_Start_DMA_MODIFIED(&htim4, TIM_CHANNEL_1, buffer, transfer);
...
}
 

I wired a interrupt pin to the TIM output, and each interrupt i will save ARR and CCR1 to an array:

int arr[100] = {0};
int ccr1[100] = {0};
 
...
 
/**
  * @brief This function handles EXTI line[9:5] interrupts.
  */
void EXTI9_5_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI9_5_IRQn 0 */
 
    if(i<100)
   {
      arr[i] =  htim4.Instance->ARR;
      ccr1[i] = htim4.Instance->CCR1;
   }else{
     //i++;
   }
   i++;
 
  /* USER CODE END EXTI9_5_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
  /* USER CODE BEGIN EXTI9_5_IRQn 1 */
  
  /* USER CODE END EXTI9_5_IRQn 1 */
}

I was expecting:

arr[] = 1000, 500, 253 ...

ccr1[]=100, 251, 253 ...

what I actually got is:

arr[] = 1000, 1000, 252 ...

ccr1[]=100, 251, 504 ...

why is this so strange ? It says in the document if I set DCR to 0x20B, it should DMA 3 element in the array each time the DMA is triggered, why the pattern seems so "random".

here is my register set:0693W000001rRn0QAE.png

I don't understand what are you trying to do, but don't use both the CC1DE and UDE - use only UDE and change the DMA stream as I wrote above.

JW

I am trying to change ARR and CCR1 for each and every pulses.