cancel
Showing results for 
Search instead for 
Did you mean: 

Synchronized two pwm signals with different frequencies

Iulia
Associate II

Hello,

I am new to ST and I need some advice. I need to create two pwm signals that are synchronized. PWM A should go to a physical channel and PWM B which runs at half the frequency is supposed to trigger ADC conversion at falling edge. 

PWMAB.png

The signals are synchronized in such a way that the timer counters start counting from zero again at the same time every 100 us. I need to be able to change the duty cycle for both of them in HAL_ADC_ConvCpltCallback(). The reason for the needed synchronization here is that the ADC should not get triggered at the same time as the rising or falling edge of the physical pwm signal.

1. What is the easiest way to achieve this? I am using a stm32G0B1RE and I have to use the HAL interface functions.

2. If I understand the docs correctly I can only scan 8 ADC channels at a time on this MCU. My use case is that I need to scan CH0-CH7 every 100 us but sometimes I also need to scan CH9-CH10 in between. Is it possible to do that or does it get too messy?

3. To get familiar with this I tested for now just  letting the signals have the same frequency and configured PWMA and PWMB on channel 4 and 1 of timer 2. But it seems like the ADC gets triggered by either channel, that is even if I only start the channel 4 of the timer the ADC will still get triggered. How can I configure which timer channel will trigger the ADC?

In my test I am using and modifying the example project from ST called ADC_MultiChannelSingleConversion which sets up the ADC with DMA.

 

hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
 
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 15999;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 10000;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }

  sConfigOC.Pulse = 1000;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

  /*if (HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1))
  {
    Error_Handler();
  }*/

  if (HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_4))
  {
    Error_Handler();
  }

 

 

2 REPLIES 2

Read out and check the ADC and TIM registers, if they are set as you intended.

Maybe what you want is Discontinuous mode, read description of this mode (and DISCEN bit) in ADC chapter in RM.

Synchronizing timers is a different task, you can try it separately. Set up slave timer's Slave-Mode controller in TIMx_SMCR to Trigger mode and select proper TRGI, set up its period in TIMx_ARR, PWM for selected channel in TIMx_CCMRx/TIMx_CCER and TIMx_CCRx, but don't enable its counter in TIMx_CR1.CEN yet. Now set up master timer to output TRGO upon Update or CCx as you wish, and set it up completely to output PWM, and enable it. TRGO-TRGI will then in hardware enable the slave timer.

If what you want is not something easily clickable in CubeMX, you may be better off using normal registers programming rather than sticking to Cube/HAL.

JW

Joe WILLIAMS
ST Employee

Hello Iulia

Your inquiry has been routed to our Online Support Center.
Thank you for your patience.

Kind Regards

Joe WILLIAMS