'Blackpill STM32F411CEU6 - PWM with libopencm3 not working
I'm trying to get PWM working with timer 3, I've followed the reference manual and believe i have everything correct but i get nothing on the output.
My code is below, I must be missing something
rcc_periph_clock_enable(RCC_GPIOB);
gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
GPIO0 | GPIO4 | GPIO5);
gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,
GPIO0 | GPIO4 | GPIO5);
gpio_set_af(GPIOB, GPIO_AF2, GPIO0 | GPIO4 | GPIO5);
rcc_periph_clock_enable(RCC_TIM3);
timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
timer_set_prescaler(TIM3, 50000000 / 125000 - 1);
timer_enable_preload(TIM3);
timer_enable_oc_preload(TIM3, TIM_OC1);
timer_set_period(TIM3, 0xffff);
timer_enable_oc_output(TIM3, TIM_OC1);
timer_set_oc_mode(TIM3, TIM_OC1, TIM_OCM_PWM2);
// timer_set_oc_mode(TIM3, TIM_OC2, TIM_OCM_PWM2);
// timer_set_oc_mode(TIM3, TIM_OC3, TIM_OCM_PWM2);
timer_set_oc_value(TIM3, TIM_OC1, 0x7fff);
timer_enable_update_event(TIM3);
timer_generate_event(TIM3, TIM_EGR_UG);
timer_enable_counter(TIM3);
Solution 1:[1]
A few things to bear in mind:
- gpio_mode_setup() should use GPIO_MODE_AF, not GPIO_MODE_OUTPUT
- some timers take only 16-bit counters, some are 32-bit. Double-check that your timer is suitable
- different pins allow for various combinations of timer, channel, and alternate function number. Check the datasheet to ensure you're using the right values
Here's an example that outputs a frequency of 400Hz, 25% duty cycle to PA0 using TIM5 on an stm32f411re:
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/timer.h>
#include <libopencm3/cm3/nvic.h>
// PA0 TIM5_CH1. AF2
const uint32_t timer_peri = TIM5; // timer peripheral
const enum tim_oc_id oc_id = TIM_OC1; // output compare channel designator
int main(void)
{
// setup PA0 for PWM
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_TIM5); // enable TIM clock
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO0); // pin PA11 Alt Function
gpio_set_af(GPIOA, GPIO_AF2, GPIO0);
int freq = 400;
timer_set_prescaler(timer_peri, 16-1); // s/b 1MHz
int period = 1000000/freq; // assumes prescaled set to 1MHz
timer_enable_preload(timer_peri); // causes counter to be loaded from its ARR only at next update event
timer_set_period(timer_peri, period); // set the timer period in the (ARR) auto-reload register
timer_set_oc_value(timer_peri, oc_id, period * 1/4); // set duty cycle to 25%
timer_set_counter(timer_peri, 0); // TIM_CNT
timer_enable_oc_preload(timer_peri, oc_id);
timer_set_oc_mode(timer_peri, oc_id, TIM_OCM_PWM1); // output active when counter is lt compare register
timer_enable_oc_output(timer_peri, oc_id); // enable timer output compare
timer_continuous_mode(timer_peri); // enable the timer to run continuously
timer_generate_event(timer_peri, TIM_EGR_UG); // required!
timer_enable_counter(timer_peri);
//timer_enable_irq(timer_peri, TIM_DIER_COMIE); //enable commutation interrupt
//nvic_enable_irq(NVIC_TIM1_CC_IRQ);
while (1);
}
Adapt it to your needs.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | blippy |