cancel
Showing results for 
Search instead for 
Did you mean: 

how to generate PWM with delay

MNapi
Senior III

I can generate PWM using channels 1-4 but they would start at the same time.

I want to generate one PWN and the other one would start with 500 us delay.

Can somebody help with sample code. It is so easy with Arduino, there are so many sample codes, you can program the next day. With STM32 it look me a few weeks just to figure out the blinking LED. They designed the STM32 for computer scientists not for hobbyist .

8 REPLIES 8

> I want to generate one PWN and the other one would start with 500 us delay.

You can't do this on one timer (you can do this in certain timers in some newer STM32s - you did not tell us the STM32 you are using).

Use different timers, and start them the required delay apart. For cycle-precise delay you can use the master-slave feature between timers, but for simpler purposes a simple well-tuned loopdelay would suffice, especially if you can avoid interrupts to get into way.

> They designed the STM32 for computer scientists not for hobbyist .

Hobbyists market does not justify the M$+ of investments into a new chip. Arduino build on the existing AVRs paid for by companies employing programmers.

This said, blinking shouldn't have taken up weeks. Please tell us how did you approach the problem.

JW

Hi

I have STM32F446RE and STM32L412KBU6. I already know that I could use one as internal interrupt like ITR0 and /or master/slave.

But I cannot just figure out the code. I am using Cube MX and Keil, it took really long time to figure out a few simple things. The problem is with STM32 if they gave some sample codes to learn the life would be easier.

Well, you've said you already know how to start a PWM. So the code should go like;

set up timer 1

set up timer2

start timer 1

delay 500us

start timer2

I believe this is how you'd do it in Arduino, too, isn't it?

JW

I wish it would be so simple I already did.

 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

HAL_Delay(1);

 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);

They will start at the same time

The only way I see is to setup another timer as a trigger for TIM3 but I cannot figure it out.

I see that you can enable in Cube MX trigger ***** for time something as ITR0 but I cannot figure it out.

Show more code.

JW

MNapi
Senior III

Here is the main.c, most generated in Cube Mx, it just does not work. We need something like enabling one clock as master another clock and use it as interrupt. I do not know how to write to code

#include "main.h"

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_TIM3_Init(void);

static void MX_TIM2_Init(void);

int main(void)

{

 HAL_Init();

 MX_GPIO_Init();

 MX_TIM3_Init();

 MX_TIM2_Init();

 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);

 while (1)

 {

 }

}

void SystemClock_Config(void)

{

 RCC_OscInitTypeDef RCC_OscInitStruct = {0};

 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 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.PLLM = 16;

 RCC_OscInitStruct.PLL.PLLN = 336;

 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;

 RCC_OscInitStruct.PLL.PLLQ = 2;

 RCC_OscInitStruct.PLL.PLLR = 2;

 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

 {

   Error_Handler();

 }

 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();

 }

}

static void MX_TIM2_Init(void)

{

 TIM_ClockConfigTypeDef sClockSourceConfig = {0};

 TIM_MasterConfigTypeDef sMasterConfig = {0};

 htim2.Instance = TIM2;

 htim2.Init.Prescaler = 180;

 htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

 htim2.Init.Period = 10;

 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

 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();

 }

 sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;

 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

 if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)

 {

   Error_Handler();

 }

}

static void MX_TIM3_Init(void)

{

 TIM_ClockConfigTypeDef sClockSourceConfig = {0};

 TIM_MasterConfigTypeDef sMasterConfig = {0};

 TIM_OC_InitTypeDef sConfigOC = {0};

 htim3.Instance = TIM3;

 htim3.Init.Prescaler = 18;

 htim3.Init.CounterMode = TIM_COUNTERMODE_UP;

 htim3.Init.Period = 100;

 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

 if (HAL_TIM_Base_Init(&htim3) != HAL_OK)

 {

   Error_Handler();

 }

 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

 if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)

 {

   Error_Handler();

 }

 if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)

 {

   Error_Handler();

 }

 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

 if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)

 {

   Error_Handler();

 }

 sConfigOC.OCMode = TIM_OCMODE_PWM1;

 sConfigOC.Pulse = 10;

 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

 if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)

 {

   Error_Handler();

 }

 sConfigOC.Pulse = 75;

 sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;

 if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)

 {

   Error_Handler();

 }

 HAL_TIM_MspPostInit(&htim3);

}

static void MX_GPIO_Init(void)

{

 GPIO_InitTypeDef GPIO_InitStruct = {0};

 __HAL_RCC_GPIOA_CLK_ENABLE();

 __HAL_RCC_GPIOC_CLK_ENABLE();

 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

 GPIO_InitStruct.Pin = GPIO_PIN_5;

 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

 GPIO_InitStruct.Pull = GPIO_NOPULL;

 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

void Error_Handler(void)

{

}

#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)

{

}

#endif

 HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);

So you start TIM3.CH1 and TIM2.CH3, but you haven't configured TIM2.CH3.

JW

do you know the code how to use one timer as interrupt ?

so one timer will generate 500 us pulse and at the end it will trigger another timer to start generating pulse.

I am trying to find how to initialiaze the timers in Cube Mx and any code I need in keil