aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32/stm32-h103/pwm_6step
diff options
context:
space:
mode:
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");