aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32/stm32-h103/pwm_6step
diff options
context:
space:
mode:
authorPiotr Esden-Tempski2011-01-31 13:28:54 -0800
committerPiotr Esden-Tempski2011-01-31 13:28:54 -0800
commitdd0018ffdf89210f04d5fb3ca153c9cbab7c3144 (patch)
treeef704d9ac28a46da88af8e3df867debb9c3f726d /examples/stm32/stm32-h103/pwm_6step
parenta0091f18c71a19d68cf1c0de4ceb3d9e90c23c39 (diff)
Added interrupt and event generation handling functions to timer. Updated pwm 6step example to use those and commutate on button press using PWM ON scheme.
Diffstat (limited to 'examples/stm32/stm32-h103/pwm_6step')
-rw-r--r--examples/stm32/stm32-h103/pwm_6step/pwm_6step.c225
1 files changed, 209 insertions, 16 deletions
diff --git a/examples/stm32/stm32-h103/pwm_6step/pwm_6step.c b/examples/stm32/stm32-h103/pwm_6step/pwm_6step.c
index f93378d..9c04c9b 100644
--- a/examples/stm32/stm32-h103/pwm_6step/pwm_6step.c
+++ b/examples/stm32/stm32-h103/pwm_6step/pwm_6step.c
@@ -21,23 +21,24 @@
#include <libopencm3/stm32/nvic.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/timer.h>
+#include <libopencm3/stm32/exti.h>
+
+#define FALLING 0
+#define RISING 1
+
+u16 exti_direction = FALLING;
void clock_setup(void)
{
rcc_clock_setup_in_hse_8mhz_out_72mhz();
- /* Enable TIM1 clock. */
- rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_TIM1EN);
-
- /* Enable GPIOA, GPIOB and Alternate Function clocks. */
- rcc_peripheral_enable_clock(&RCC_APB2ENR,
- RCC_APB2ENR_IOPAEN |
- RCC_APB2ENR_IOPBEN |
- RCC_APB2ENR_AFIOEN);
}
void gpio_setup(void)
{
+ /* Enable GPIOC clock. */
+ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
+
/*
* Set GPIO12 (PORTC) (led) to
* 'output alternate function push-pull'.
@@ -45,6 +46,58 @@ void gpio_setup(void)
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
+}
+
+void exti_setup(void)
+{
+ /* Enable GPIOA clock. */
+ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
+
+ /* Enable AFIO clock. */
+ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN);
+
+ /* Enable EXTI0 interrupt */
+ nvic_enable_irq(NVIC_EXTI0_IRQ);
+
+ /* Set GPIO0 (in GPIO port A) to 'input open-drain'. */
+ gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
+ GPIO_CNF_INPUT_FLOAT, GPIO0);
+
+ /* configure EXTI subsystem */
+ exti_select_source(EXTI0, GPIOA);
+ exti_direction = FALLING;
+ exti_set_trigger(EXTI0, EXTI_TRIGGER_FALLING);
+ exti_enable_request(EXTI0);
+}
+
+void exti0_isr()
+{
+ exti_reset_request(EXTI0);
+
+ if (exti_direction == FALLING) {
+ //gpio_toggle(GPIOA, GPIO12);
+ exti_direction = RISING;
+ exti_set_trigger(EXTI0, EXTI_TRIGGER_RISING);
+ } else {
+ //gpio_toggle(GPIOA, GPIO12);
+ timer_generate_event(TIM1, TIM_EGR_COMG);
+ exti_direction = FALLING;
+ exti_set_trigger(EXTI0, EXTI_TRIGGER_FALLING);
+ }
+}
+
+void tim_setup(void)
+{
+
+ /* Enable TIM1 clock. */
+ rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_TIM1EN);
+
+ /* Enable GPIOA, GPIOB and Alternate Function clocks. */
+ rcc_peripheral_enable_clock(&RCC_APB2ENR,
+ RCC_APB2ENR_IOPAEN |
+ RCC_APB2ENR_IOPBEN |
+ RCC_APB2ENR_AFIOEN);
+
/*
* Set TIM1 chanel output pins to
* 'output alternate function push-pull'.
@@ -65,11 +118,6 @@ void gpio_setup(void)
GPIO_TIM1_CH2N |
GPIO_TIM1_CH3N);
-}
-
-void tim_setup(void)
-{
-
/* Enable TIM1 commutation interrupt. */
nvic_enable_irq(NVIC_TIM1_TRG_COM_IRQ);
@@ -95,7 +143,7 @@ void tim_setup(void)
timer_set_period(TIM1, 72000000 / 32000);
/* Configure break and deadtime */
- timer_set_deadtime(TIM1, 0);
+ 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);
@@ -151,7 +199,7 @@ void tim_setup(void)
timer_set_oc_idle_state_set(TIM1, TIM_OC2N);
/* Set the capture compare value for OC1. */
- timer_set_oc_value(TIM1, TIM_OC2, 200);
+ timer_set_oc_value(TIM1, TIM_OC2, 100);
/* Reenable outputs. */
timer_enable_oc_output(TIM1, TIM_OC2);
@@ -178,7 +226,7 @@ void tim_setup(void)
timer_set_oc_idle_state_set(TIM1, TIM_OC3N);
/* Set the capture compare value for OC3. */
- timer_set_oc_value(TIM1, TIM_OC3, 300);
+ timer_set_oc_value(TIM1, TIM_OC3, 100);
/* Reenable outputs. */
timer_enable_oc_output(TIM1, TIM_OC3);
@@ -188,11 +236,155 @@ void tim_setup(void)
/* ARR reload enable */
timer_enable_preload(TIM1);
+ /* Enable preload of complementary channel configurations and update on COM event */
+ timer_enable_preload_complementry_enable_bits(TIM1);
+
/* Enable outputs in the break subsystem */
timer_enable_break_main_output(TIM1);
/* Counter enable */
timer_enable_counter(TIM1);
+
+ /* Enable commutation interrupt */
+ timer_enable_irq(TIM1, TIM_DIER_COMIE);
+}
+
+void tim1_trg_com_isr(void)
+{
+ static int step = 0;
+
+ TIM1_SR &= ~TIM_SR_COMIF;
+
+ /* A simplified and inefficient implementation of PWM On
+ * scheme. Look at the implementation in Open-BLDC on
+ * http://open-bldc.org for the proper implementation. This
+ * one only serves as an example.
+ *
+ * Table of the pwm scheme zone configurations when driving:
+ * @verbatim
+ * | 1| 2| 3| 4| 5| 6|
+ * -+--+--+--+--+--+--+
+ * A|p+|++| |p-|--| |
+ * -+--+--+--+--+--+--+
+ * B| |p-|--| |p+|++|
+ * -+--+--+--+--+--+--+
+ * C|--| |p+|++| |p-|
+ * -+--+--+--+--+--+--+
+ * | | | | | | '- 360 Deg
+ * | | | | | '---- 300 Deg
+ * | | | | '------- 240 Deg
+ * | | | '---------- 180 Deg
+ * | | '------------- 120 Deg
+ * | '---------------- 60 Deg
+ * '------------------- 0 Deg
+ *
+ * Legend:
+ * p+: PWM on the high side
+ * p-: PWM on the low side
+ * --: Low side on
+ * ++: High side on
+ * : Floating/NC
+ * @endverbatim
+ */
+ switch (step) {
+ case 0: /* A PWM HIGH, B OFF, C LOW */
+ timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1);
+ timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_FROZEN);
+ timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_FORCE_LOW);
+
+ timer_enable_oc_output(TIM1, TIM_OC1);
+ timer_disable_oc_output(TIM1, TIM_OC1N);
+
+ timer_disable_oc_output(TIM1, TIM_OC2);
+ timer_disable_oc_output(TIM1, TIM_OC2N);
+
+ timer_enable_oc_output(TIM1, TIM_OC3);
+ timer_enable_oc_output(TIM1, TIM_OC3N);
+
+ step++;
+ break;
+ case 1: /* A HIGH, B PWM LOW, C OFF */
+ timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_FORCE_HIGH);
+ timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_PWM1);
+ timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_FROZEN);
+
+ timer_enable_oc_output(TIM1, TIM_OC1);
+ timer_enable_oc_output(TIM1, TIM_OC1N);
+
+ timer_disable_oc_output(TIM1, TIM_OC2);
+ timer_enable_oc_output(TIM1, TIM_OC2N);
+
+ timer_disable_oc_output(TIM1, TIM_OC3);
+ timer_disable_oc_output(TIM1, TIM_OC3N);
+
+ step++;
+ break;
+ case 2: /* A OFF, B LOW, C PWM HIGH */
+ timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_FROZEN);
+ timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_FORCE_LOW);
+ timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM1);
+
+ timer_disable_oc_output(TIM1, TIM_OC1);
+ timer_disable_oc_output(TIM1, TIM_OC1N);
+
+ timer_enable_oc_output(TIM1, TIM_OC2);
+ timer_enable_oc_output(TIM1, TIM_OC2N);
+
+ timer_enable_oc_output(TIM1, TIM_OC3);
+ timer_disable_oc_output(TIM1, TIM_OC3N);
+
+ step++;
+ break;
+ case 3: /* A PWM LOW, B OFF, C HIGH */
+ timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1);
+ timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_FROZEN);
+ timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_FORCE_HIGH);
+
+ timer_disable_oc_output(TIM1, TIM_OC1);
+ timer_enable_oc_output(TIM1, TIM_OC1N);
+
+ timer_disable_oc_output(TIM1, TIM_OC2);
+ timer_disable_oc_output(TIM1, TIM_OC2N);
+
+ timer_enable_oc_output(TIM1, TIM_OC3);
+ timer_enable_oc_output(TIM1, TIM_OC3N);
+
+ step++;
+ break;
+ case 4: /* A LOW, B PWM HIGH, C OFF */
+ timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_FORCE_LOW);
+ timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_PWM1);
+ timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_FROZEN);
+
+ timer_enable_oc_output(TIM1, TIM_OC1);
+ timer_enable_oc_output(TIM1, TIM_OC1N);
+
+ timer_enable_oc_output(TIM1, TIM_OC2);
+ timer_disable_oc_output(TIM1, TIM_OC2N);
+
+ timer_disable_oc_output(TIM1, TIM_OC3);
+ timer_disable_oc_output(TIM1, TIM_OC3N);
+
+ step++;
+ break;
+ case 5: /* A OFF, B HIGH, C PWM LOW */
+ timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_FROZEN);
+ timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_FORCE_HIGH);
+ timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM1);
+
+ timer_disable_oc_output(TIM1, TIM_OC1);
+ timer_disable_oc_output(TIM1, TIM_OC1N);
+
+ timer_enable_oc_output(TIM1, TIM_OC2);
+ timer_enable_oc_output(TIM1, TIM_OC2N);
+
+ timer_disable_oc_output(TIM1, TIM_OC3);
+ timer_enable_oc_output(TIM1, TIM_OC3N);
+
+ step=0;
+ break;
+ }
+ gpio_toggle(GPIOC, GPIO12);
}
int main(void)
@@ -200,6 +392,7 @@ int main(void)
clock_setup();
gpio_setup();
tim_setup();
+ exti_setup();
while (1) {
__asm("nop");