2020-03-02 02:32 PM
Is it possible to run two or more channels on timer with DMA PWM mode?
This code starts only first Channel.
uint32_t PrawoPWM = 100;
uint32_t LewoPWM = 100;
HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_1 , &PrawoPWM, 1);
HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_2 , &LewoPWM, 1);
How can I start two channels?
2020-03-02 03:12 PM
You probably want to use the TIMx_DCR/TIMx_DMAR-based mechanism. Read the TIM chapter in RM.
I don't Cube, but you may be able to find an example in Cube, it appears that in Cube lingo this is called "DMA Burst".
JW
2020-03-03 12:49 AM
Why do you want to use DMA with a single value per channel? What do you want to achieve exactly?
2020-03-03 01:07 AM
I have an application where I need 4 channels with the same frequency but independent duty. This is for 4 motors.
2020-03-03 01:18 AM
Do the duty cycle values change in every cycle?
2020-03-03 01:22 AM
No. It is independent. Duty will be change from another part of program.
2020-03-03 01:33 AM
This is the very purpose of the mechanism I mentioned above.
JW
2020-03-03 02:04 AM
I will try DMA Burst.
Do you know how to use HAL for this purpose?
2020-03-03 02:18 AM
I still don't think that DMA is required for this.
I have no idea how to use HAL functions properly, here an example using the register interface.
Set period and duty cycle for all channels.
TIM4->ARR = period - 1;
TIM4->CCR1 = duty1 - 1;
TIM4->CCR2 = duty2 - 1;
TIM4->CCR3 = duty3 - 1;
TIM4->CCR4 = duty4 - 1;
Set PWM mode 1 and enable preload on all channels
TIM4->CCMR1 = TIM_CCMR1_OC2M_1|TIM_CCMR1_OC2M_2|TIM_CCMR1_OC2PE | TIM_CCMR1_OC1M_1|TIM_CCMR1_OC1M_2|TIM_CCMR1_OC1PE;
TIM4->CCMR2 = TIM_CCMR2_OC4M_1|TIM_CCMR2_OC4M_2|TIM_CCMR2_OC4PE | TIM_CCMR2_OC3M_1|TIM_CCMR2_OC3M_2|TIM_CCMR2_OC3PE;
Enable channel outputs
TIM4->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E;
Enable the counter
TIM4->CR1 = TIM_CR1_CEN;
Now you can change duty cycle values any time directly writing the CCR1 - CCR4 registers.
If perfectly synchronized changes are required, write the CCR registers just after the update event, either polling for it, or from the update interrupt handler.
volatile uint32_t duty1, duty2, duty3, duty4;
/* assign values to duty1 - duty 4 */
TIM4->DIER = TIM_DIER_UIE; // enable update interrupt
void TIM4_IRQHandler(void) {
TIM4->SR = 0; // reset status flags
TIM4->DIER = 0; // disable interrupts, they are no longer needed after the update
TIM4->CCR1 = duty1;
TIM4->CCR2 = duty2;
TIM4->CCR3 = duty3;
TIM4->CCR4 = duty4;
}
2020-10-15 11:50 PM
Dear @JSzem.1
Did any of the answers here help you solve your problem?
Best regards
Laurent Ca...