banner



How To Update Stm32 Pwm Dynamically

Check the attached STM32 IDE examination project for the STM32F030K.

Some resource:

STM32F030K reference transmission:
https://www.st.com/resource/en/reference_manual/dm00091010-stm32f030x4x6x8xc-and-stm32f070x6xb-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

General timer cookbook:
https://www.st.com/resources/en/application_note/dm00236305-generalpurpose-timer-cookbook-for-stm32-microcontrollers-stmicroelectronics.pdf

Online grooming resources. Non for the STM32F030K, merely the F7 peripheral beliefs is similar, volition help a bit.
https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-online-training.html

STM32F0 HAL documentation:
https://www.st.com/resource/en/user_manual/dm00122015-clarification-of-stm32f0-hal-and-lowlayer-drivers-stmicroelectronics.pdf

My arroyo to this would be:

STM32 to 48MHz for all-time performance (36MHz if the frequency needs to be exact)
Select a timer that allows DMA and repetition counter (non all have them). Ex. TIM1.
Slave  & trigger source = disabled
The PWM resolution will be pretty low, about 8bit, as the period needs to be 265 ( 48MHz/(265+1) = 180451Hz). The PWM values will be 0-265.
If you lot tin can reduce the PWM frequency, yous volition gain a lot of precision. 100KHz=479, 50KHz = 959.

If the frequency needs to be exact:  Menstruum=199 ( 36MHz/(199+1) = 180KHz). PWM values = 0-199. 100KHz=359, 50KHz=719.

Enable the PWM channels. Ex. CH1 PWM generation, CH2 PWM generation.
Since you want to update the PWM values slower than the PWM frequency, you tin can use the repetition counter.
Repetition counter = viii, update frequency = 180451/(8+1) = 20050Hz. (exact 20KHz at 36MHz)

Go to DMA tab, add DMA channels for the enabled channels.
Since the PWM register is 16 fleck, the DMA data size is half word. Select half give-and-take for both peripheral and retention.
Enable circular mode so the DMA resets the arrow when reaches the cease.
Peripheral address increase = disabled, retention=enabled.
Management = retentiveness to peripheral.

HAL isn't clear about the timer interrupts. I tested in my STM342F411 and worked nice without them.
Save and let cubeMX build the initial lawmaking.

Check the STM32 HAL source files, as they ordinarily take comments that will help further.

/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_tim.c
/Drivers/STM32F0xx_HAL_Driver/Inc/stm32f0xx_hal_tim.h

Then use "HAL_TIM_PWM_Start_DMA", the office parameters are equally follow:

HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA (TIM_HandleTypeDef * htim, uint32_t Aqueduct, uint32_t * pData, uint16_t Length)
Keep in listen that the pData is ever a 32-chip pointer! Then yous must redeclare the pointer as (uint32_t*)&PWM_DATA.

Length is the number of DMA discussion size! One-half Word = 16 scrap, so you must set the number of 16 bit values in the PWM data.
You tin set a single value, or a big assortment.

Example:

// Data array where the PWM values are stored
// Ensure it's aligned to 32bit, just in case.
__attribute__((aligned(4)))  volatile uint16_t PWM_CH1_Data[4] = { 0, 50, 100, 150 };   // This aqueduct uses 4 values

// Outset timer1 in PWM DMA mode
// Selected channel =  CH1
// DMA source = PWM_CH1_Data
// Length = 4

HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t*)&PWM_CH1_Data, four);


Repeat for the second aqueduct:

__attribute__((aligned(4)))  volatile uint16_t PWM_CH2_Data = { 100, 250 };   // This aqueduct uses ii values

// This doesn't piece of work if done instantly after starting the beginning channel
// HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_2, (uint32_t*)&PWM_CH2_Data, 2);

// Edit: Obviously the PWM stays BUSY until the first PWM cycle is done. This fixes the 2d aqueduct initialization
while( HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_2, (uint32_t*)&PWM_CH2_Data, two) == HAL_BUSY);


At this betoken both PWM channels should be working at 180KHz, and updating the PWM value at 20KHz.

Edit: In that location are strange behaviours using different DMA buffer sizes.
Sizes = two,4,8 work correctly. However size=half dozen fails and works with only two values.

Also when you get shut to 100% PWM it does the PWM cycle twice. In my current tests, with PWM menses = 549, the college value I tin can employ is 547.
Higher than that will indistinguishable that wheel. Not a single pwm cycle, simply the repetition counter cycle, so in this case all the 9 pwm cycles.
I don't understand why does this happen, the repetition counter clock source is the timer overflow, non the output compare.
Cheque the last picture.

First test:

STM32F411 100Mhz, PWM period = 554 (180180Hz).
__attribute__((aligned(4)))  uint16_t PWM_CH1_Data[] = { 50, 500 };
HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t*)&PWM_CH1_Data, sizeof(PWM_CH1_Data)/sizeof(uint16_t));

The measurements have a modest error due the analyzer 24MHz sampling rate causing some jittering.
PWM = five.542uS, 180180Hz
Update = 49.958uS, 20016Hz

This is the PWM duty bug. The code that outputs those channels:

__attribute__((aligned(4))) volatile uint16_t PWM_CH1_Data[8] = { 0, 540 };
__attribute__((aligned(4))) volatile uint16_t PWM_CH2_Data[four] = { 0, 100, 200, 540 };

HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t*)&PWM_CH1_Data[0], 2);
while (HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_2, (uint32_t*)&PWM_CH2_Data[0], 4) == HAL_BUSY){
  asm("nop");
}

Source: https://eevblog.com/forum/microcontrollers/stm32-dma-pwm-two-channels/

Posted by: rixroutionce86.blogspot.com

0 Response to "How To Update Stm32 Pwm Dynamically"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel