Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions examples/stm32/f4/stm32f4-discovery/pwm/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <[email protected]>
##
## 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 <http://www.gnu.org/licenses/>.
##

BINARY = pwm

LDSCRIPT = ../stm32f4-discovery.ld

include ../../Makefile.include

10 changes: 10 additions & 0 deletions examples/stm32/f4/stm32f4-discovery/pwm/README.md
Original file line number Diff line number Diff line change
@@ -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*
133 changes: 133 additions & 0 deletions examples/stm32/f4/stm32f4-discovery/pwm/pwm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <[email protected]>
* Copyright (C) 2013 Stephen Dwyer <[email protected]>
*
* 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 <http://www.gnu.org/licenses/>.
*/

#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/timer.h>
#include <stdio.h>
#include <errno.h>

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;
}