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.
This commit is contained in:
parent
a0091f18c7
commit
dd0018ffdf
@ -21,11 +21,74 @@
|
||||
#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();
|
||||
|
||||
}
|
||||
|
||||
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'.
|
||||
*/
|
||||
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);
|
||||
|
||||
@ -34,16 +97,6 @@ void clock_setup(void)
|
||||
RCC_APB2ENR_IOPAEN |
|
||||
RCC_APB2ENR_IOPBEN |
|
||||
RCC_APB2ENR_AFIOEN);
|
||||
}
|
||||
|
||||
void gpio_setup(void)
|
||||
{
|
||||
/*
|
||||
* Set GPIO12 (PORTC) (led) to
|
||||
* 'output alternate function push-pull'.
|
||||
*/
|
||||
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
|
||||
|
||||
/*
|
||||
* Set TIM1 chanel output pins to
|
||||
@ -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");
|
||||
|
@ -852,6 +852,8 @@ enum tim_oc_mode {
|
||||
};
|
||||
|
||||
/* --- TIM functions ------------------------------------------------------- */
|
||||
void timer_enable_irq(u32 timer_peripheral, u32 irq);
|
||||
void timer_disable_irq(u32 timer_peripheral, u32 irq);
|
||||
void timer_set_mode(u32 timer_peripheral, u8 clock_div,
|
||||
u8 alignment, u8 direction);
|
||||
void timer_set_clock_division(u32 timer_peripheral, u32 clock_div);
|
||||
@ -908,5 +910,6 @@ void timer_set_enabled_off_state_in_idle_mode(u32 timer_peripheral);
|
||||
void timer_set_disabled_off_state_in_idle_mode(u32 timer_peripheral);
|
||||
void timer_set_break_lock(u32 timer_peripheral, u32 lock);
|
||||
void timer_set_deadtime(u32 timer_peripheral, u32 deadtime);
|
||||
void timer_generate_event(u32 timer_peripheral, u32 event);
|
||||
|
||||
#endif
|
||||
|
@ -27,6 +27,16 @@
|
||||
|
||||
#include <libopencm3/stm32/timer.h>
|
||||
|
||||
void timer_enable_irq(u32 timer_peripheral, u32 irq)
|
||||
{
|
||||
TIM_DIER(timer_peripheral) |= irq;
|
||||
}
|
||||
|
||||
void timer_disable_irq(u32 timer_peripheral, u32 irq)
|
||||
{
|
||||
TIM_DIER(timer_peripheral) &= ~irq;
|
||||
}
|
||||
|
||||
void timer_set_mode(u32 timer_peripheral, u8 clock_div,
|
||||
u8 alignment, u8 direction)
|
||||
{
|
||||
@ -829,3 +839,8 @@ void timer_set_deadtime(u32 timer_peripheral, u32 deadtime)
|
||||
TIM_BDTR(timer_peripheral) |= deadtime;
|
||||
}
|
||||
}
|
||||
|
||||
void timer_generate_event(u32 timer_peripheral, u32 event)
|
||||
{
|
||||
TIM_EGR(timer_peripheral) |= event;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user