cancel
Showing results for 
Search instead for 
Did you mean: 

TIM DMA not working on STM32F429ZIT

Heidi
Associate II

I'm struggling to get DMA working on a PWM Timer. I've read just about everything i can, but  it is not working.

Running this code.. produces a PWM signal as expected on the output.

 /* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);

pwm_3.png

 

However, when I swap the code to the following, all I get is a one duty signal. It never produces a two duty PWM at all.

 

/* USER CODE BEGIN 2 */
neo_data[0] = 52; //104(puls)/2
neo_data[1] = 26; //104/4

HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_2, (uint32_t *)neo_data, 2); //tim3 ch2

SmartSelect_20231011_163256_Gallery.jpg

My expectation is that it should this. (youtube((4) STM32F103 네오픽셀 제어(Live Coding) - YouTube) capture)

pwm_tim.png

I have my scope on single shot, and triggered correctly.

I have DMA setup for the timer

TIMp1.png

TIMp2.png

TIMp3.png

6 REPLIES 6
Sarra.S
ST Employee

Welcome @Heidi  to ST Community, 

From what I understood, you want to change the timer's duty cycle using DMA. your code looks fine 

But notice that the APB1 timer clock is running at 84 MHz (you're interested in APB1 since TIM3 is connected to the APB1 clock as you can see in your product datasheet

SarraS_0-1697016278243.png

So, you need to change that value (45MHz) in the clock tree, and since you're using a prescaler 0 that means you are dividing this frequency by 1. 

By choosing ARR=100, you are dividing this frequency by 100 => 45KHz ( this will give you the advantage of changing the duty cycle to a percentage of 100) 

for example : 

neo_data[0] = 50; // 50% duty cycle
neo_data[1] = 30; // 30% duty cycle

 Your DMA setup looks functional and it should work! 

Edit: I've realized that you're configuring the pulse value in the TIM config, since you're changing the duty cycle in the code, leave the Pulse value as default (0).

Try that and you can always come back if there is an issue

Hope that helps!

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Read out and check/post content of TIM and DMA registers.

JW

Hello, @Sarra.S 

Thank you for your support.

I tried change the parameter settings

APB1 Timer clocks (MHz) : 42

TIM3 CH2

PSC: 0

ARR : 100

Pulse : 0

 

TIMp5.png

/* USER CODE BEGIN 0 */
uint8_t neo_data[2];
/* USER CODE BEGIN 2 */
neo_data[0] = 50; //duty 50%
neo_data[1] = 30; //duty

HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_2, (uint32_t *)neo_data, 2);

However, when I swap the code to the following, all I get is a one duty signal.

But I want to see 50% 30% duty..

스크린샷(2).png

 

 

Running this code.. (TIM parameter setting Pulse : 50)

produces a PWM signal as expected on the output.


HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);

스크린샷(3).png

TDK
Guru

Try defining neo_data as a uint16_t or uint32_t array instead. It definitely shouldn't be uint8_t.

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

Yes, I missed this line : 

uint8_t neo_data[2];

I thought it was declared in PV section, uint8_t is definitely incompatible with a parameter of type uint32_t in HAL_TIM_PWM_Start_DMA

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Heidi
Associate II

I don't know how I can produce diffirent duty like this.. 

Heidi_0-1697078616957.png

In my code have like this

HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
...
}

so  I running this code (uint32_t *)neo_data

HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_2, (uint32_t *)neo_data, 2);

What do I need to fix in my code to output a PWM with a different duty cycle?