Getting Started with STM32G0 and STM32CubeIDE: Update Duty Cycle using DMA

In this guide, we shall see how to configure the DMA with timer to update the duty cycle of the PWM using DMA to generate certain waveform.

In this guide, we shall cover the following:

  • STM32CubeMX Configuration.
  • Code.
  • Results.

1. STM32CubeMX Configuration:

We start off by creating new project with name of PWM_DMA.

For how to create project, please refer to this guide here.

One CubeMX is opened, from timers, select TIM1.

From TIM1:

  • Set clock source to internal cock.
  • Channel1 and Channel2 PWM Generation CH1 and CH2 respectively.
  • Set counter period to 1600.

From DMA tab:

  • Add TIM1_CH1 and TIM1_CH2.
  • Set direction to Memory to Peripheral for both.
  • Enable Circular mode for both.

Save the project and this will generate the code.

2. Code:

In main.c source file:

In User code begin PV (Private Variable):

#define sample_size		200


uint16_t lookUp1[sample_size] = {0,50 ,100 ,151 ,201 ,250 ,300 ,349 ,398 ,446 ,494 ,542 ,589 ,635 ,681
	,726 ,771 ,814 ,857 ,899 ,940 ,981 ,1020 ,1058 ,1095 ,1131 ,1166 ,1200 ,1233 ,1264
	,1294 ,1323 ,1351 ,1377 ,1402 ,1426 ,1448 ,1468 ,1488 ,1505 ,1522 ,1536 ,1550 ,1561
	,1572 ,1580 ,1587 ,1593 ,1597 ,1599 ,1600 ,1599 ,1597 ,1593 ,1587 ,1580 ,1572 ,1561
	,1550 ,1536 ,1522 ,1505 ,1488 ,1468 ,1448 ,1426 ,1402 ,1377 ,1351 ,1323 ,1294 ,1264
	,1233 ,1200 ,1166 ,1131 ,1095 ,1058 ,1020 ,981 ,940 ,899 ,857 ,814 ,771 ,726 ,681 ,635
	,589 ,542 ,494 ,446 ,398 ,349 ,300 ,250 ,201 ,151 ,100 ,50,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
	,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
	,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
	,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };

uint16_t lookUp2[sample_size] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
	,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
	,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0
	,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,50 ,100 ,151 ,201 ,250 ,300 ,349 ,398 ,446 ,494
	,542 ,589 ,635 ,681 ,726 ,771 ,814 ,857 ,899 ,940 ,981 ,1020 ,1058 ,1095 ,1131 ,1166 ,1200 ,1233
	,1264 ,1294 ,1323 ,1351 ,1377 ,1402 ,1426 ,1448 ,1468 ,1488 ,1505 ,1522 ,1536 ,1550 ,1561 ,1572 ,1580
	,1587 ,1593 ,1597 ,1599 ,1600 ,1599 ,1597 ,1593 ,1587 ,1580 ,1572 ,1561 ,1550 ,1536 ,1522 ,1505 ,1488
	,1468 ,1448 ,1426 ,1402 ,1377 ,1351 ,1323 ,1294 ,1264 ,1233 ,1200 ,1166 ,1131 ,1095 ,1058 ,1020 ,981
	,940 ,899 ,857 ,814 ,771 ,726 ,681 ,635 ,589 ,542 ,494 ,446 ,398 ,349 ,300 ,250 ,201 ,151 ,100 ,50 ,0};

Here, we have 200 sample for duty cycle for sinewave.

In user code begin 2:

  HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, lookUp1, 200);
  HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_2, lookUp2, 200);

The HAL_TIM_PWM_Start_DMA takes the following parameters:

  • Pointer to timer handler, htim1 in this case.
  • Timer channel, which is channel 1 and channel 2.
  • Data array that hold the duty cycles values.
  • Size of the data.

Thats it for the code.

Save the project, build it and run it on your STM32G070.

3. Results:

By using logic analyzer and probing PA8 and PA9, you should get the following:

We have successfully updated the duty cycle with DMA without using CPU resources at all.

Happy coding 😉

Add Comment

Your email address will not be published. Required fields are marked *