User Tools

Site Tools


STM32 PWM with opencm3 and on CMSIS

pwm.c
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/timer.h>
 
 
void delay(uint32_t n) {
    for (volatile int i = 0; i < n; i++)
        __asm__("nop");
}
 
int main(void) {
 
    rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);
 
    rcc_periph_clock_enable(RCC_GPIOA);
    rcc_periph_clock_enable(RCC_TIM5);
 
    rcc_periph_reset_pulse(RST_TIM5);
 
    gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
                                                      GPIO_TIM5_CH1);
    gpio_set(GPIOA, GPIO0);
 
    timer_enable_preload(TIM5);
    //TIM_CR1(TIM5) |= TIM_CR1_ARPE;
 
    timer_enable_oc_preload(TIM5, TIM_OC1);
    //TIM_CCMR1(TIM5) |= TIM_CCMR1_OC1PE;
 
    timer_set_oc_mode(TIM5, TIM_OC1, TIM_OCM_PWM1);
    //TIM_CCMR1(TIM5) &= ~TIM_CCMR1_CC1S_MASK;
    //TIM_CCMR1(TIM5) |= TIM_CCMR1_CC1S_OUT;
    //TIM_CCMR1(TIM5) &= ~TIM_CCMR1_OC1M_MASK;
    //TIM_CCMR1(TIM5) |= TIM_CCMR1_OC1M_PWM1;
 
    timer_continuous_mode(TIM5);
    //TIM_CR1(TIM5) &= ~TIM_CR1_OPM;
 
    timer_set_counter(TIM5, 0);
    //TIM_CNT(TIM5) = 0;
 
    int prescale = (rcc_apb1_frequency / (1000 * 1000)) - 1;
    timer_set_prescaler(TIM5, prescale);
    //TIM_PSC(TIM5) = prescale;
 
    int freq = 100;
    int period = (1000 * 1000 / freq) - 1;
    timer_set_period(TIM5, period);
    //TIM_ARR(TIM5) = period;
 
    int percent = 50;
    timer_set_oc_value(TIM5, TIM_OC1, period * percent / 100);
    //TIM_CCR1(TIM5) = period * percent / 100;
 
    timer_enable_oc_output(TIM5, TIM_OC1);
    //TIM_CCER(TIM5) |= TIM_CCER_CC1E;
 
    timer_enable_counter(TIM5);
    //TIM_CR1(TIM5) |= TIM_CR1_CEN;
 
    int max = 700;
    int min = 300;
    while (1) {
        for (int i = min; i < max; i += 1) {
            delay(1000000 * 0.02);
            timer_set_oc_value(TIM5, TIM_OC1, period * i / 1000);
            //TIM_CCR1(TIM5) = period * i/1000;
        }
        for (int i = max; i > min; i -= 1) {
            delay(1000000 * 0.02);
            timer_set_oc_value(TIM5, TIM_OC1, period * i / 1000);
            //TIM_CCR1(TIM5) = period * i/1000;
        }
    };
 
    return 0;
}
pwm_cm.c
#include <stm32f10x_can.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_pwr.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_usart.h>
#include <stm32f10x_tim.h>
#include <misc.h>
 
 
void delay(void) {
    volatile uint32_t i;
    for (i = 0; i != 0x70000; i++);
}
 
void usart_putc(uint8_t data) {
    while (!(USART1->SR & USART_SR_TC));
    USART1->DR = data;
}
 
void usart_puts(uint8_t * str) {
    uint32_t i = 0;
    while (str[i] != 0) {
        usart_putc(str[i]);
        i++;
    }
}
 
void RCC_Setup(void) {
 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
}
 
void USART_Setup(void) {
 
    GPIO_InitTypeDef gpio;
 
    gpio.GPIO_Pin      = GPIO_Pin_9;
    gpio.GPIO_Speed    = GPIO_Speed_50MHz;
    gpio.GPIO_Mode     = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &gpio);
 
    gpio.GPIO_Pin      = GPIO_Pin_10;
    gpio.GPIO_Speed    = GPIO_Speed_50MHz;
    gpio.GPIO_Mode     = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &gpio);
 
    USART_InitTypeDef usart;
 
    usart.USART_BaudRate   = 115200;
    usart.USART_WordLength = USART_WordLength_8b;
    usart.USART_StopBits   = USART_StopBits_1;
    usart.USART_Parity     = USART_Parity_No;
    usart.USART_Mode       = USART_Mode_Rx | USART_Mode_Tx;
    usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(USART1, &usart);
 
    USART_Cmd(USART1, ENABLE);
}
 
void TIM_Setup(void) {
 
    GPIO_InitTypeDef gpio;
 
    //gpio.GPIO_Pin   = GPIO_Pin_All;
    //gpio.GPIO_Speed = GPIO_Speed_2MHz;
    //gpio.GPIO_Mode  = GPIO_Mode_AIN;
    //GPIO_Init(GPIOA, &gpio);
 
    gpio.GPIO_Pin   = GPIO_Pin_0;
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    gpio.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &gpio);
 
    int period = 1000 * 1000;
    int frequency = 330;
 
    TIM_TimeBaseInitTypeDef  tim;
    tim.TIM_Period             = period / frequency - 1;            // ARR
    tim.TIM_Prescaler          = (SystemCoreClock / period) - 1;    // PCS
    tim.TIM_ClockDivision      = TIM_CKD_DIV1;
    tim.TIM_CounterMode        = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM5, &tim);
 
    int duty = 50;
 
    TIM_OCInitTypeDef timOC;
    timOC.TIM_OCMode         = TIM_OCMode_PWM2;
    timOC.TIM_OutputState    = TIM_OutputState_Enable;
    timOC.TIM_OCPolarity     = TIM_OCPolarity_Low;
    timOC.TIM_Pulse          = (period / frequency) * duty / 100 - 1;   // CCR1
 
    TIM_OC1Init(TIM5, &timOC);
 
    TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM5, ENABLE);
 
    TIM_Cmd(TIM5, ENABLE);
 
    duty = 80;
    TIM5->CCR1 = (period / frequency) * duty / 100;
 
}
 
int main(void) {
    RCC_Setup();
    USART_Setup();
    TIM_Setup();
 
    uint32_t i = 0;
    while (1) {
        delay();
        usart_putc(i % 4 + 'a');
        i++;
    }
}