cancel
Showing results for 
Search instead for 
Did you mean: 

How to correctly configure CubeMx for timer One Pulse Mode?

Xxoyo.1
Associate III

I am trying to output One Pulse Mode, however the output is not back to 0V when the pulse is complete. The One Pulse is started with a button interrupt.

The timing of the One Pulse is correct, but when the pulse is finished, the output was set to high. And this created another problem, the button would not trigger One Pulse again.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
 
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
 
HAL_TIM_Base_Start(&htim2);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
 
HAL_TIM_OnePulse_Start_IT(&htim2, TIM_CHANNEL_1);
 
}
static void MX_TIM2_Init(void)
{
 
  /* USER CODE BEGIN TIM2_Init 0 */
 
  /* USER CODE END TIM2_Init 0 */
 
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
 
  /* USER CODE BEGIN TIM2_Init 1 */
 
  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 4294967295;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OnePulse_Init(&htim2, TIM_OPMODE_SINGLE) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */
 
  __HAL_TIM_SET_PRESCALER(&htim2, Master_Prescale);
  __HAL_TIM_SET_AUTORELOAD(&htim2, Master_Arr);
  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, Master_PulseOff);
 
 
 
	//TIM_CCxChannelCmd(htim2.Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
	//__HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE);
	//__HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE);
 
  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);
 
}

0693W00000BctCeQAJ.png0693W00000BctClQAJ.png 

Purple line (Timer 2)= the One Pulse output. Yellow line (Timer 1) = Mode 2 PWM 1Khz 50% duty cycle, started simultaneously with the One Pulse timer

0693W00000BctCqQAJ.png 

 Update : Im using STM32F429 Discovery board for this project

4 REPLIES 4
TDK
Guru

What chip?

If you feel a post has answered your question, please click "Accept as Solution".
Xxoyo.1
Associate III

Im working on STM32F429 Discovery board

TDK
Guru

After you set it up in CubeMX, you should call HAL_TIM_PWM_Init with your ARR/PSC settings. If you change ARR/PSC after that, you need to generate an update event so they get loaded to the shadow register.

https://github.com/STMicroelectronics/STM32CubeF4/blob/2f3b26f16559f7af495727a98253067a31182cfc/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c#L6624

Then call HAL_TIM_PWM_Start to start the timer inside the button interrupt. Or better yet, set a flag and call it within the main loop to avoid thread issues. Don't call the other things you're calling.

I'm not sure of the link between TIM1 and TIM2 in your example. You say you're triggering off of a button interrupt. Is TIM1 piped into the button interrupt?

Edit: I'm not 100% sure here what HAL is doing with the OPM bit for this case. You can use HAL_TIM_OnePulse_Init / HAL_TIM_OnePulse_Start, but I'm not sure that's what you want here.

If you feel a post has answered your question, please click "Accept as Solution".
Xxoyo.1
Associate III

I have just updated the codes following your suggestion, but the problem still persist i.e. the purple line still remains high after One Pulse.

 /* USER CODE BEGIN TIM2_Init 2 */
 
//  __HAL_TIM_SET_PRESCALER(&htim2, Master_Prescale);
//  __HAL_TIM_SET_AUTORELOAD(&htim2, Master_Arr);
//  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, Master_PulseOff);
 
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, Master_PulseOff);
 htim2.Init.Period = Master_Arr;	// ARR
htim2.Init.Prescaler = Master_Prescale;	// prescale
 HAL_TIM_PWM_Init(&htim2);
 htim2.Instance->EGR = TIM_EGR_UG;

To ensure it's not problem caused by the shadow register, I commented all of my user code in Tim2 init, and set correct numerical values inside CubeMX. However , it still didnt solve the issue.

I apologize for not being clear with the Tim1 and Tim2 relationship, they have no Master/slave configuration. I only Use Tim1 to indicated that my button interrupt was pressed. So ideally, when the button is pressed, Tim2 outputs one pulse and Tim1 PWM should start simultaneously .

I saw forum saying OnePulse_Init/HAL_Tim_OnePulse_Start has some bug with the functions, so i didn't want to use them .

https://www.reddit.com/r/stm32/comments/e2co0y/getting_complete_one_pulse_functionality_working/

https://www.reddit.com/r/stm32/comments/dn3r9i/need_help_getting_onepulse_to_work_with_the_hal/

By any chance, could you provide me a simple working project generated with CubeMx with this oneshot pulse that's triggered in software? any working piece of code would greatly help my progress.