0
\$\begingroup\$

I am generating PWM using TIM1 channel 1 and channel 2 along with their complementary channels. I am providing the CCR values from an array via DMA. I have written a DMA complete callback function. When the DMA completes the full array, the PWM channel polarity should toggle.

I am using DMA in circular mode on an STM32F411RE controller.

HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)sin_table, 20);//low
HAL_TIMEx_PWMN_Start_IT(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_2, (uint32_t *)sin_table, 20); //high
HAL_TIMEx_PWMN_Start_IT(&htim1, TIM_CHANNEL_2);  

The call back function is as follows:

void PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{    if (htim->hdma[TIM_DMA_ID_CC1] != NULL && htim->hdma[TIM_DMA_ID_CC1] == &hdma_tim1_ch1)
       {
          HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);

          if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
              {
 HAL_TIM_PWM_Stop_DMA(&htim1, TIM_CHANNEL_1);
                 HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
                  // Stop PWM on CH2 and CH2N before toggling polarity
                 HAL_TIM_PWM_Stop_DMA(&htim1, TIM_CHANNEL_2);
                HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
                 // Toggle the polarity bits for CH1 and CH1N
                htim1.Instance->CCER ^= (TIM_CCER_CC1P | TIM_CCER_CC1NP);
                // Toggle the polarity bits for CH2 and CH2N
               htim1.Instance->CCER ^= (TIM_CCER_CC2P | TIM_CCER_CC2NP);
HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)sin_table, 200);
                    HAL_TIMEx_PWMN_Start_IT(&htim1, TIM_CHANNEL_1);
                    HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_2, (uint32_t *)sin_table, 200);
                    HAL_TIMEx_PWMN_Start_IT(&htim1, TIM_CHANNEL_2);  

After the callback function is executed, the PWM signal stops, and the signal is not being generated. How can I achieve toggled or changed polarity of the PWM signal at each DMA cycle completion?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Yes I found the answer.

Forget to use HAL for continuous operations. Maybe with right usage half and full complete callbacks and rewrite arrays for DMA. For continuous PWM never break TIM setup only change CCR values.

The following code works:

void PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->hdma[TIM_DMA_ID_CC1] != NULL 
         && htim->hdma[TIM_DMA_ID_CC1] == &hdma_tim1_ch1)
    {
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        { 
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);

            // Toggle the polarity bits for CH1 and CH1N
            htim1.Instance->CCER ^= (TIM_CCER_CC1P | TIM_CCER_CC1NP);
            
            // Toggle the polarity bits for CH2 and CH2N
            htim1.Instance->CCER ^= (TIM_CCER_CC2P | TIM_CCER_CC2NP);
            
            if (i==2)
                i=0;
        }
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.