cancel
Showing results for 
Search instead for 
Did you mean: 

ARR update causing output glitch

_EFrie
Associate III

Using STM32F765, I'm using tim1 with OC toggle.

The issue is glitches when I update the ARR value within the Repetition UP ISR.  ARR Preload is enabled, not sure what to look at here.

D2 toggles when the TIM1_UP_TIM10_IRQHandler fires, and D3 is TIM1 CH1 output, and the glitch seems obviously caused by the SetAutoReload when it fires.

Screenshot 2025-02-26 14.23.59.png

Init code

void init_stepper(void) {
  ena_stepper();
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  LL_TIM_InitTypeDef TIM_InitStruct = {0};
  /* USER CODE END TIM1_Init 2 */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
  /**TIM1 GPIO Configuration
  PA8   ------> TIM1_CH1
  */
  GPIO_InitStruct.Pin = TMC_STEP_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
  LL_GPIO_Init(TMC_STEP_GPIO_Port, &GPIO_InitStruct);

  TIM_InitStruct.Prescaler = 0;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 65535;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  TIM_InitStruct.RepetitionCounter = 0;
  LL_TIM_Init(TIM1, &TIM_InitStruct);

  LL_TIM_EnableARRPreload(TIM1);
  LL_TIM_SetClockSource(TIM1, LL_TIM_CLOCKSOURCE_INTERNAL);
  LL_TIM_DisableMasterSlaveMode(TIM1);
  LL_TIM_SetPrescaler(TIM1, 63);

  LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_TOGGLE);
  LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1);
  LL_TIM_OC_SetCompareCH1(TIM1, 0x0000);
  LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCPOLARITY_LOW);
  LL_TIM_EnableAllOutputs(TIM1);
  //
  NVIC_SetPriority(TIM1_UP_TIM10_IRQn, PRIORITY_TIMER1_PWM);
  NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
  LL_TIM_SetRepetitionCounter(TIM1, 31);
  LL_TIM_EnableIT_UPDATE(TIM1);
}

 

ISR

void TIM1_UP_TIM10_IRQHandler(void) {
  
  if (LL_TIM_IsActiveFlag_UPDATE(TIM1) == 1) {
          LL_GPIO_TogglePin(OUT_ALIVE_GPIO_Port, OUT_ALIVE_Pin);
    LL_TIM_ClearFlag_UPDATE(TIM1);
    stepTickCount += 16;
    // Stop here
    if (stepTickCount >= targetPosition) {
      LL_TIM_DisableCounter(TIM1);
      LL_TIM_SetCounter(TIM1, 0);
      LL_TIM_SetAutoReload(TIM1, SystemCoreClock / 128 / 500 /* HZ */);
    }
    uint32_t arr = LL_TIM_GetAutoReload(TIM1);
    if (!arr) {
      arr = 1;
    }
    uint32_t currHz = 1687500 / LL_TIM_GetAutoReload(TIM1);
    currHz = (currHz > 0 ? currHz : 1);
    if ((targetPosition - stepTickCount) < 200) {
      // Decel here
      if (currHz > 750) {
        currHz -= 750;
        if (currHz < 750) {
          currHz = 750;
        }
        LL_TIM_SetAutoReload(TIM1, SystemCoreClock / 128 / currHz /* HZ */);
      }
    } else {
      // Acceleration here
      if (currHz < targetSpeed) {
        currHz += 750;
        if (currHz > targetSpeed) {
          currHz = targetSpeed;
        }
        LL_TIM_SetAutoReload(TIM1, SystemCoreClock / 128 / currHz /* HZ */);
      }
    }
  }
}

 

 

 

 

2 REPLIES 2

>> .. the glitch seems obviously caused by the SetAutoReload when it fires.

Or you manually clearing the COUNTER

The general idea is that you set up the shadow registers ahead of time so they cleanly and consistently engage when the UPDATE event occurs, ie rolling into zero

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

The counter isn't being cleared.  yeah, its in the code there, but it turns off the timer completely, it only fires at the end.