Search code examples
stm32freertosrtospwmcmsis

STM32 change PWM Duty Cycle dynamically in RTOS


I'm using this code below trying to achieve a intensity transition effect upon turning on a light:

void output2ControlTask(void *argument)
{
  /* USER CODE BEGIN output2ControlTask */
  uint32_t DutyCycle = 0;
  /* Infinite loop */
  for(;;)
  {
    if(flag_EN_OUTPUT2 == ON){
      SteadyBurn_PWM_RTOS(&htim2, TIM_CHANNEL_3, DutyCycle);
      if(DutyCycle < 100){
        DutyCycle++;
      }
    }
    if(flag_EN_OUTPUT2 == OFF){
      SteadyBurn_PWM_RTOS(&htim2, TIM_CHANNEL_3, DutyCycle);
      if(DutyCycle > 0){
        DutyCycle--;
      }
    }
    osDelay(100);
  }
  /* USER CODE END output2ControlTask */
}
void SteadyBurn_PWM_RTOS(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t intensity_percentage){
    __HAL_TIM_SET_COMPARE(htim, Channel, (uint32_t)(COUNTER_PERIOD * (float)(intensity_percentage/100)));
}

Somehow when observed with an oscilloscope the output delayed for like 10 seconds (make sense with osDelay(100)) and then outputted a 100% Duty Cycle PWM, with no transition effect.

I remember using this code without in RTOS environment works fine. I thought about priority issues but when I changed DutyCycle to any int and left out the DutyCycle it outputs the corresponding PWM instantly.

I also debugged the DutyCycle and it was in the correct increment in runtime as well. Is it a HAL problem?


Solution

  • Right, it was a casting problem afterall.

    removed a pair of parentheses on the math function and it works.

    __HAL_TIM_SET_COMPARE(htim, Channel, (uint32_t)(COUNTER_PERIOD * (float)intensity_percentage/100));