cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 DISCO TIMER1 sine wave PWM generation?

parth kothiya
Senior

i want to generate sine wave pwm using advanced time1 of discovery board how can i do this?

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

The timer can't generate a sine wave on its own, you have to calculate the duty cycle values for a full period in advance, and store them in an array of uint16_t (or maybe uint8_t) values. These values can be transferred periodically to the CCR register of the timer channel by DMA.

Enable TIM1, DMA2, and the GPIO bank in RCC->APB2ENR and RCC->AHBENR, and set the timer channel output pin to alternate function. Find the alternate function number for the pin and TIM1 in the datasheet.

Find the DMA stream and channel belonging to the TIM1_UP (timer 1 update) event in the DMA2 request mapping table in the reference manual. Configure the DMA stream, the memory address (M0AR) is the array of samples, peripheral address is the address of the CCR register of the timer channel, and the number of samples in NDTR. Set the DMA stream control register, MSIZE and PSIZE fields according to the sample width, memory increment mode (MINC), circular mode (CIRC), and data transfer direction (DIR), then enable the DMA stream. Use the DMA register descriptions in the refrence manual.

Set up the timer channel as output, PWM mode 1 (OCxM bits in CCMR1 or CCMR2), enable output in CCER, and the MOE bit in BDTR, optionally set a repetition count in RCR (each sample will be repeated that many times), set the period in ARR, enable DMA on update (UDE bit in DIER), and start the timer (CEN bit of CR1). Use the timer register descriptions in the reference manual.

View solution in original post

3 REPLIES 3
berendi
Principal

The timer can't generate a sine wave on its own, you have to calculate the duty cycle values for a full period in advance, and store them in an array of uint16_t (or maybe uint8_t) values. These values can be transferred periodically to the CCR register of the timer channel by DMA.

Enable TIM1, DMA2, and the GPIO bank in RCC->APB2ENR and RCC->AHBENR, and set the timer channel output pin to alternate function. Find the alternate function number for the pin and TIM1 in the datasheet.

Find the DMA stream and channel belonging to the TIM1_UP (timer 1 update) event in the DMA2 request mapping table in the reference manual. Configure the DMA stream, the memory address (M0AR) is the array of samples, peripheral address is the address of the CCR register of the timer channel, and the number of samples in NDTR. Set the DMA stream control register, MSIZE and PSIZE fields according to the sample width, memory increment mode (MINC), circular mode (CIRC), and data transfer direction (DIR), then enable the DMA stream. Use the DMA register descriptions in the refrence manual.

Set up the timer channel as output, PWM mode 1 (OCxM bits in CCMR1 or CCMR2), enable output in CCER, and the MOE bit in BDTR, optionally set a repetition count in RCR (each sample will be repeated that many times), set the period in ARR, enable DMA on update (UDE bit in DIER), and start the timer (CEN bit of CR1). Use the timer register descriptions in the reference manual.

it is possible to without using dma by using this sine wave equation Vs = DUTY * sin(wt) where w = 2*pi*f ?

Instead of DMA, you can enable the update interrupt (UIE) in the last step, and update the CC register in the interrupt handler. The advantage is that you can take advantage of the symmetry of the sine function, and need only 1/4 of the precalculated table.

If the frequency is low, and the MCU has not much else to do, you can try calculating the values on the fly. Measure first how long does it take to compute a sine function.