From dd0018ffdf89210f04d5fb3ca153c9cbab7c3144 Mon Sep 17 00:00:00 2001 From: Piotr Esden-Tempski Date: Mon, 31 Jan 2011 13:28:54 -0800 Subject: 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. --- examples/stm32/stm32-h103/pwm_6step/pwm_6step.c | 225 ++++++++++++++++++++++-- 1 file changed, 209 insertions(+), 16 deletions(-) (limited to 'examples/stm32/stm32-h103/pwm_6step') 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 #include #include +#include + +#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"); -- cgit v1.2.3