Skip to content

Instantly share code, notes, and snippets.

@NikiSchlifke
Last active April 24, 2018 14:38
Show Gist options
  • Save NikiSchlifke/b532d345b71e13b1aab83920ecf191de to your computer and use it in GitHub Desktop.
Save NikiSchlifke/b532d345b71e13b1aab83920ecf191de to your computer and use it in GitHub Desktop.
Trying to get all 16 pwm outputs on a stm32f103rb
/**
* Trying to get all 16 pwm outputs on a stm32f103rb
*/
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/f1/timer.h>
#define MOTOR1_PHASE_A1 GPIO8 // PA8 fixed
#define MOTOR1_PHASE_A2 GPIO9 // PA9 fixed
#define MOTOR1_PHASE_B1 GPIO10 // PA10 fixed
#define MOTOR1_PHASE_B2 GPIO11 // PA11 fixed
#define MOTOR2_PHASE_A1 GPIO0 // PA0 ok
#define MOTOR2_PHASE_A2 GPIO1 // PA1 ok
#define MOTOR2_PHASE_B1 GPIO2 // PA2
#define MOTOR2_PHASE_B2 GPIO3 // PA3
#define MOTOR3_PHASE_A1 GPIO6 // PC6 ok
#define MOTOR3_PHASE_A2 GPIO7 // PC7 ok
#define MOTOR3_PHASE_B1 GPIO8 // PC8 ok
#define MOTOR3_PHASE_B2 GPIO9 // PC9 ok
#define MOTOR4_PHASE_A1 GPIO6 // PB6 ok
#define MOTOR4_PHASE_A2 GPIO7 // PB7 ok
#define MOTOR4_PHASE_B1 GPIO8 // PB8 ok
#define MOTOR4_PHASE_B2 GPIO9 // PB9 ok
/**
* Helper function for setting PWM timers
* @param port_clken
* @param tim_clken
* @param timer_peripheral
* @param prescaler
* @param period
*/
void pwm_init_timer(enum rcc_periph_clken port_clken, enum rcc_periph_clken tim_clken, uint32_t timer_peripheral,
uint32_t prescaler,
uint32_t period) {
rcc_periph_clock_enable(port_clken);
rcc_periph_clock_enable(tim_clken);
timer_reset(timer_peripheral);
timer_set_mode(timer_peripheral,
TIM_CR1_CKD_CK_INT,
TIM_CR1_CMS_EDGE,
TIM_CR1_DIR_UP);
timer_set_prescaler(timer_peripheral, prescaler);
timer_enable_preload(timer_peripheral);
timer_continuous_mode(timer_peripheral);
timer_set_period(timer_peripheral, period);
}
/**
* Helper function for setting PWM channels
* @param timer_peripheral
* @param gpio_reg
* @param gpio_en
* @param gpio_port
* @param gpio_pin
* @param cnf
*/
void pwm_init_output_channel(uint32_t timer_peripheral,
uint32_t gpio_port, uint16_t gpio_pin,
uint8_t cnf) {
timer_generate_event(timer_peripheral, TIM_EGR_UG);
timer_enable_counter(timer_peripheral);
gpio_set_mode(gpio_port, GPIO_MODE_OUTPUT_50_MHZ,
cnf,
gpio_pin);
/* Enable all 4 peripherals*/
timer_set_oc_mode(timer_peripheral, TIM_OC1, TIM_OCM_PWM1);
timer_enable_oc_output(timer_peripheral, TIM_OC1);
timer_set_oc_mode(timer_peripheral, TIM_OC2, TIM_OCM_PWM1);
timer_enable_oc_output(timer_peripheral, TIM_OC2);
timer_set_oc_mode(timer_peripheral, TIM_OC3, TIM_OCM_PWM1);
timer_enable_oc_output(timer_peripheral, TIM_OC3);
timer_set_oc_mode(timer_peripheral, TIM_OC4, TIM_OCM_PWM1);
timer_enable_oc_output(timer_peripheral, TIM_OC4);
}
void motor_setup(void) {
pwm_init_timer(RCC_GPIOA, RCC_TIM1, TIM1, 72, 2000);
pwm_init_timer(RCC_GPIOA, RCC_TIM2, TIM2, 72, 2000);
pwm_init_timer(RCC_GPIOC, RCC_TIM3, TIM3, 72, 2000);
pwm_init_timer(RCC_GPIOB, RCC_TIM4, TIM4, 72, 2000);
/* Set PWM motor output pins. */
pwm_init_output_channel(TIM1, GPIOA,
MOTOR1_PHASE_A1 | MOTOR1_PHASE_A2 | MOTOR1_PHASE_B1 | MOTOR1_PHASE_B2,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL);
pwm_init_output_channel(TIM2, GPIOA,
MOTOR2_PHASE_A1 | MOTOR2_PHASE_A2 | MOTOR2_PHASE_B1 | MOTOR2_PHASE_B2,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL);
pwm_init_output_channel(TIM3, GPIOC,
MOTOR3_PHASE_A1 | MOTOR3_PHASE_A2 | MOTOR3_PHASE_B1 | MOTOR3_PHASE_B2,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL);
pwm_init_output_channel(TIM4, GPIOB,
MOTOR4_PHASE_A1 | MOTOR4_PHASE_A2 | MOTOR4_PHASE_B1 | MOTOR4_PHASE_B2,
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL);
timer_set_oc_value(TIM1, TIM_OC1, 400);
timer_set_oc_value(TIM1, TIM_OC2, 500);
timer_set_oc_value(TIM1, TIM_OC3, 600);
timer_set_oc_value(TIM1, TIM_OC4, 700);
timer_set_oc_value(TIM2, TIM_OC1, 800);
timer_set_oc_value(TIM2, TIM_OC2, 900);
timer_set_oc_value(TIM2, TIM_OC3, 1000);
timer_set_oc_value(TIM2, TIM_OC4, 1100);
timer_set_oc_value(TIM3, TIM_OC1, 1200);
timer_set_oc_value(TIM3, TIM_OC2, 1300);
timer_set_oc_value(TIM3, TIM_OC3, 1400);
timer_set_oc_value(TIM3, TIM_OC4, 1500);
timer_set_oc_value(TIM4, TIM_OC1, 1600);
timer_set_oc_value(TIM4, TIM_OC2, 1700);
timer_set_oc_value(TIM4, TIM_OC3, 1800);
timer_set_oc_value(TIM4, TIM_OC4, 1900);
}
int main() {
rcc_clock_setup_in_hse_8mhz_out_72mhz();
rcc_periph_clock_enable(RCC_AFIO); // Needed for remapping to work.
gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON,
AFIO_MAPR_TIM3_REMAP_FULL_REMAP | AFIO_MAPR_TIM2_REMAP_NO_REMAP | AFIO_MAPR_TIM1_REMAP_NO_REMAP);
motor_setup();
timer_enable_break_main_output(TIM1); // Needed for TIM1 output
while (1) {
asm("NOP");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment