diff --git a/examples/stm32/f4/stm32f4-discovery/pwm/Makefile b/examples/stm32/f4/stm32f4-discovery/pwm/Makefile new file mode 100644 index 00000000..1210075d --- /dev/null +++ b/examples/stm32/f4/stm32f4-discovery/pwm/Makefile @@ -0,0 +1,25 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +BINARY = pwm + +LDSCRIPT = ../stm32f4-discovery.ld + +include ../../Makefile.include + diff --git a/examples/stm32/f4/stm32f4-discovery/pwm/README.md b/examples/stm32/f4/stm32f4-discovery/pwm/README.md new file mode 100644 index 00000000..598a8e69 --- /dev/null +++ b/examples/stm32/f4/stm32f4-discovery/pwm/README.md @@ -0,0 +1,10 @@ +# README + +This example demonstrates the generation of PWM signal on alternate function pins. +There should be a complementary 32kHz 50% duty cycle PWM signal on pins PE12 and PE13. + +It's intended for the ST STM32F4DISCOVERY eval board. + +## Board connections + +*none required* diff --git a/examples/stm32/f4/stm32f4-discovery/pwm/pwm.c b/examples/stm32/f4/stm32f4-discovery/pwm/pwm.c new file mode 100644 index 00000000..d76f5ebe --- /dev/null +++ b/examples/stm32/f4/stm32f4-discovery/pwm/pwm.c @@ -0,0 +1,133 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * Copyright (C) 2013 Stephen Dwyer + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +static void clock_setup(void) +{ + rcc_clock_setup_hse_3v3(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]); + + /* Enable GPIOE clock. */ + rcc_periph_clock_enable(RCC_GPIOE); + + /* Enable TIM1 clock. */ + rcc_periph_clock_enable(RCC_TIM1); +} + + +static void timer1_setup(void) +{ + /* Reset TIM1 peripheral. */ + rcc_periph_reset_pulse(RST_TIM1); + + /* Timer global mode: + * - No divider + * - Alignment edge + * - Direction up + */ + timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, + TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + + /* Reset prescaler value. */ + timer_set_prescaler(TIM1, 0); + + /* Reset repetition counter value. */ + timer_set_repetition_counter(TIM1, 0); + + /* Enable preload. */ + timer_enable_preload(TIM1); + + /* Continuous mode. */ + timer_continuous_mode(TIM1); + + /* Period (32kHz). */ + /* TIM1 uses a clock from APB2, see reg RCC_APB2ENR in STM32F407 RM */ + /* APB2 PREESC was set to 2, so APB2 timer clocks is */ + /* 2 x rcc_apb2_frequency, see clock tree in STM32F407 RM */ + timer_set_period(TIM1, rcc_apb2_frequency*2 / 32000); + + /* Configure break and deadtime. */ + timer_set_deadtime(TIM1, 10); + timer_set_enabled_off_state_in_idle_mode(TIM1); + timer_set_enabled_off_state_in_run_mode(TIM1); + timer_disable_break(TIM1); + timer_set_break_polarity_high(TIM1); + timer_disable_break_automatic_output(TIM1); + timer_set_break_lock(TIM1, TIM_BDTR_LOCK_OFF); + + /* -- OC3 configuration -- */ + /* Disable outputs. */ + timer_disable_oc_output(TIM1, TIM_OC3); + timer_disable_oc_output(TIM1, TIM_OC3N); + + /* Configure global mode of line 3. */ + timer_disable_oc_clear(TIM1, TIM_OC3); + timer_enable_oc_preload(TIM1, TIM_OC3); + timer_set_oc_slow_mode(TIM1, TIM_OC3); + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM1); + + /* Configure OC3. */ + timer_set_oc_polarity_high(TIM1, TIM_OC3); + timer_set_oc_idle_state_set(TIM1, TIM_OC3); + + /* Configure OC3N. */ + timer_set_oc_polarity_high(TIM1, TIM_OC3N); + timer_set_oc_idle_state_set(TIM1, TIM_OC3N); + + /* Set the capture compare value for OC3. 50% duty */ + timer_set_oc_value(TIM1, TIM_OC3, rcc_apb2_frequency / 32000); + + /* Reenable outputs. */ + timer_enable_oc_output(TIM1, TIM_OC3); + timer_enable_oc_output(TIM1, TIM_OC3N); + + /* ARR reload enable. */ + timer_enable_preload(TIM1); + + /* Enable outputs in the break subsystem. */ + timer_enable_break_main_output(TIM1); + + /* Counter enable. */ + timer_enable_counter(TIM1); +} + +static void gpio_setup(void) +{ + /* Set GPIOE12 and GPIO13 to 'output push-pull' and AF1 (TIM1_CH3N, TIM1_CH3). */ + gpio_mode_setup(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12 | GPIO13); + gpio_set_af(GPIOE, GPIO_AF1, GPIO12 | GPIO13); + gpio_set_output_options(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO12 | GPIO13); +} + +int main(void) +{ + clock_setup(); + gpio_setup(); + timer1_setup(); + + while (1); + + return 0; +}