2
\$\begingroup\$

I am using an STM32Cube IDE and HAL library to generate two PWM using two timers.

I want these two PWMs to stop i.e go LOW after one of the PWMs has generated N pulses.

I don't know what to use in what mode. Should I use a third timer with a mode or something else?

EDIT: After reading the answer, I'm getting closer but still some issues PWM does not stop.

Here is my settings(NUCLEO-F302R8):

I set PA0 as PWM output and PB1(myInterrupt_Input) as external trigger input.

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

Here my main.c:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM2_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int global_pulse_flag = 0;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
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 = 640-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1000;
  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();
  }
  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 = 500;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

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

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 38400;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : myInterrupt_Input_Pin */
  GPIO_InitStruct.Pin = myInterrupt_Input_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(myInterrupt_Input_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.Pin = LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI1_IRQn);

}

/* USER CODE BEGIN 4 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    if(htim -> Instance == TIM2)
    {
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
            global_pulse_flag++;
            if(global_pulse_flag>55){
                global_pulse_flag = 0;
                HAL_TIM_PWM_Stop_IT(&htim2,TIM_CHANNEL_1);
            }

        }
    }
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Here is stm32f3xx_it.c:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    stm32f3xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f3xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */

/* USER CODE END TD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/* External variables --------------------------------------------------------*/
extern TIM_HandleTypeDef htim2;
/* USER CODE BEGIN EV */

/* USER CODE END EV */

/******************************************************************************/
/*           Cortex-M4 Processor Interruption and Exception Handlers          */
/******************************************************************************/
/**
  * @brief This function handles Non maskable interrupt.
  */
void NMI_Handler(void)
{
  /* USER CODE BEGIN NonMaskableInt_IRQn 0 */

  /* USER CODE END NonMaskableInt_IRQn 0 */
  /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
  while (1)
  {
  }
  /* USER CODE END NonMaskableInt_IRQn 1 */
}

/**
  * @brief This function handles Hard fault interrupt.
  */
void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Memory management fault.
  */
void MemManage_Handler(void)
{
  /* USER CODE BEGIN MemoryManagement_IRQn 0 */

  /* USER CODE END MemoryManagement_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
    /* USER CODE END W1_MemoryManagement_IRQn 0 */
  }
}

/**
  * @brief This function handles Pre-fetch fault, memory access fault.
  */
void BusFault_Handler(void)
{
  /* USER CODE BEGIN BusFault_IRQn 0 */

  /* USER CODE END BusFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_BusFault_IRQn 0 */
    /* USER CODE END W1_BusFault_IRQn 0 */
  }
}

/**
  * @brief This function handles Undefined instruction or illegal state.
  */
void UsageFault_Handler(void)
{
  /* USER CODE BEGIN UsageFault_IRQn 0 */

  /* USER CODE END UsageFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
    /* USER CODE END W1_UsageFault_IRQn 0 */
  }
}

/**
  * @brief This function handles System service call via SWI instruction.
  */
void SVC_Handler(void)
{
  /* USER CODE BEGIN SVCall_IRQn 0 */

  /* USER CODE END SVCall_IRQn 0 */
  /* USER CODE BEGIN SVCall_IRQn 1 */

  /* USER CODE END SVCall_IRQn 1 */
}

/**
  * @brief This function handles Debug monitor.
  */
void DebugMon_Handler(void)
{
  /* USER CODE BEGIN DebugMonitor_IRQn 0 */

  /* USER CODE END DebugMonitor_IRQn 0 */
  /* USER CODE BEGIN DebugMonitor_IRQn 1 */

  /* USER CODE END DebugMonitor_IRQn 1 */
}

/**
  * @brief This function handles Pendable request for system service.
  */
void PendSV_Handler(void)
{
  /* USER CODE BEGIN PendSV_IRQn 0 */

  /* USER CODE END PendSV_IRQn 0 */
  /* USER CODE BEGIN PendSV_IRQn 1 */

  /* USER CODE END PendSV_IRQn 1 */
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

/******************************************************************************/
/* STM32F3xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f3xx.s).                    */
/******************************************************************************/

/**
  * @brief This function handles EXTI line1 interrupt.
  */
void EXTI1_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI1_IRQn 0 */
     if(HAL_TIM_PWM_Start_IT(&htim2, TIM_CHANNEL_1) != HAL_OK)
     {
         Error_Handler();
     }
  /* USER CODE END EXTI1_IRQn 0 */
  HAL_GPIO_EXTI_IRQHandler(myInterrupt_Input_Pin);
  /* USER CODE BEGIN EXTI1_IRQn 1 */

  /* USER CODE END EXTI1_IRQn 1 */
}

/**
  * @brief This function handles TIM2 global interrupt.
  */
void TIM2_IRQHandler(void)
{
  /* USER CODE BEGIN TIM2_IRQn 0 */

  /* USER CODE END TIM2_IRQn 0 */
  HAL_TIM_IRQHandler(&htim2);
  /* USER CODE BEGIN TIM2_IRQn 1 */

  /* USER CODE END TIM2_IRQn 1 */
}

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */
\$\endgroup\$
12
  • \$\begingroup\$ Can you route one of them to a count down counter? Preload the countdown with the number of pulses you want, and when the counter reaches zero it triggers an interrupt and the ISR stops the PWM output? Something like that. \$\endgroup\$
    – mkeith
    Jan 28 at 8:12
  • \$\begingroup\$ That preloaded counter means a third timer to be used correct? \$\endgroup\$
    – cm64
    Jan 28 at 8:42
  • 1
    \$\begingroup\$ This may be related: electronics.stackexchange.com/questions/541521/… \$\endgroup\$
    – Tagli
    Jan 28 at 8:57
  • 1
    \$\begingroup\$ Can you not just fire an interrupt every time the PWM completes a cycle and use a variable counting down in the interrupt service handler? I don't know these chips so I'm just thinking MCU generic. \$\endgroup\$
    – Ian Bland
    Jan 28 at 13:25
  • 1
    \$\begingroup\$ @IanBland That is exactly what I've suggested, I've just explained how to do it in STM32 HAL \$\endgroup\$
    – ChrisD91
    Jan 28 at 14:47

2 Answers 2

6
\$\begingroup\$

There's an easy solution to this using HAL as there are drivers that call a function every time a timer (in this case PWM) is called. You can just count the number of times the function is called and then stop your second PWM.

  1. Enable PWM as interrupt-based in the .ioc / cubemx page in stm32cubeide and generate code
  2. go to Drivers/xxx_HAL_Driver/Src/xx_hal_tim.c in project explorer window
  3. Look for the driver called HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel) and copy and paste it into your main. Obviously you will need to provide the correct timer handle and channel
  4. In the timer driver file also look for a function called __weak void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim). Copy and paste this function in your main.c
  5. Remove the __weak and define the pulse finished callback function yourself. HAL will call this function every time a PWM pulse is finished. You need to have a flag that increments every time the function is called. Once it is called N times you can set your second to LOW.

Example code: before the main while loop ,start the PWM using timer 3 and channel 1:

 if(HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1) != HAL_OK) 
 {
     Error_Handler();
 }

And defining what to do with the pulse interrupt call. In this case if the timer that called the function is timer 3, make sure that it was also channel 1 (in case you have multiple timers and channels). If it is as expected increment a global falg.

/* USER CODE BEGIN 4 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    if(htim -> Instance == TIM3)
    {
        if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
            global_pulse_flag++;
            
        }
    }
}
/* USER CODE END 4 */

CubeMX screenshot to enable PWM interrupt:

enter image description here

\$\endgroup\$
20
  • \$\begingroup\$ Interesting and I want to try this. But how do you set PWM as interrupt base in Cube MX? \$\endgroup\$
    – cm64
    Jan 28 at 10:42
  • 1
    \$\begingroup\$ Added a screenshot to the answer. In cubemx you need to configure your parameter settings (I assume you've already done this) and then in the NVIC settings tab you have the option to enable global interrupts for that timer \$\endgroup\$
    – ChrisD91
    Jan 28 at 10:49
  • \$\begingroup\$ Ok I will try. Will this: "if(HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1) != HAL_OK)" be inside the while loop or before? \$\endgroup\$
    – cm64
    Jan 28 at 11:09
  • 1
    \$\begingroup\$ If you declare it inside the while loop, it will keep restarting the PWM initialisation every loop. Do it before the while loop, I'd recommend it in the /* USER CODE BEGIN 2 */ part the cubemx generates for you \$\endgroup\$
    – ChrisD91
    Jan 28 at 11:11
  • \$\begingroup\$ I generate the PWM now. But after global_pulse_flag++; I have now if(global_pulse_flag == 1000){ HAL_TIM_Base_Stop(&htim2); HAL_TIM_Base_Stop_IT(&htim2); } to stop PWM after 1000 counts. But PWM still runs I use timer2 in my case \$\endgroup\$
    – cm64
    Jan 28 at 11:18
2
\$\begingroup\$

I see several possibilities :

  1. compute the time neededto complete the N pulses, and stop the PWM after that time : you have 2 sub options :
  • just get current time when you start the PWM, and check from your main loop if the time has elapsed : depending PWM frequency and what else you do in your main loop, you might stop it a few pulses too late if your main loop is busy doing something else when the moment comes to stop it

  • use another timer, and generate an interup when time is come to stop it

  1. There might be a way to chain timers, in order for a second timer to count the number of pulses (or resets) from your PWM.

  2. If your PWM is rather low frequency, you don't need extreme accuracy, and can spare some CPU : you could just generate some "soft PWM" using an interupt based on a timer : in this interupt, instead of just switching your pin, you also check if you reached N pulses : if so, you no longer switch

EDIT : adding pseudo code for option 1.2 :

void interupt_routine_timer_2()
{
    stop_pwm_on_timer_1();
}


void main()
{
    int nbr_of_pulses_timer_2= ...;  //compute the number of pulses needed on timer 2 to get the duration of N pulses (depends on clock frequency, prescaler, PWM frequency and N)
    set_timer_2_counting_down(initial_value=nbr_of_pulses_timer_2, interrupt_on_zero=interupt_routine_timer_2);
    start_pwm_on_timer_1();
    
}

So when the time of N pulses is elapsed, you call an interupt, which turns off PWM.

Basically, all you need to know is :

  • how to start a PWM on timer 1

  • how to stop a PWM on timer 1

  • how to generate an interuption after a fixed delay (using a timer).

For all those 3 things, you should be able to find examples on internet. Then you just have to merge them.

\$\endgroup\$
9
  • \$\begingroup\$ "use another timer, and generate an interrupt when time is come to stop it" I cannot find any examples on this method. How to set what to set ect. \$\endgroup\$
    – cm64
    Jan 28 at 9:57
  • \$\begingroup\$ I added some pseudo code : is it clearer now? \$\endgroup\$
    – Sandro
    Jan 28 at 10:11
  • \$\begingroup\$ I would like to try this in STM32 Cube IDE. But don't you need to set timer_2 as slave of timer_1 ect? Can you try to implement this as well and see the result? \$\endgroup\$
    – cm64
    Jan 28 at 10:17
  • \$\begingroup\$ And timer_2 should count pulses(rising edges) of timer_1; it seems in your code timer_2 is counting itself. Isnt it? \$\endgroup\$
    – cm64
    Jan 28 at 10:21
  • \$\begingroup\$ No. That's the nice thing of method 1.2 : you just measure absolute time, instead of counting pulses, which makes the code more "simple" (ie avoids complex things like chaining timers). Let's say you want to generate 10 pulses at 100Hz : you know that each pulse takes 10ms, so 10 pulses take 100ms. So you can simply say "I stop the PWM after 100ms" instead of ssaying "I stop the PWM after 10 pulses". NB : I would recommend centered PWM, as to avoid starting pulse N+1 at exactly time N*period. Otherwise, you might need to reduce the duration by a small fraction of period \$\endgroup\$
    – Sandro
    Jan 28 at 10:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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