Implement IRQ handling of the button

master
LEdoian 5 years ago
parent 58f7ce498d
commit dc0ff5562c

@ -11,12 +11,17 @@
#include <libopencm3/stm32/rcc.h> #include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h> #include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/f1/exti.h>
#include <libopencm3/stm32/f1/nvic.h>
#include <stdbool.h> #include <stdbool.h>
//#define DELAY 8000000 // Should be a second, or maybe not (second iff 8MHz clk, 1/3second if 24MHz clk) // Too long!! //#define DELAY 8000000 // Should be a second, or maybe not (second iff 8MHz clk, 1/3second if 24MHz clk) // Too long!!
#define DELAY 400000 // This is bad -- it's a value that was found to be OK #define DELAY 4000000 // This is bad -- it's a value that was found to be OK
#define STM32F1 1 // Needed for libopencm3 #define STM32F1 1 // Needed for libopencm3
enum {FORWARD, BACKWARD} direction;
bool running = false;
void setup (void) { // All the blackbox code void setup (void) { // All the blackbox code
// Set up clock // Set up clock
@ -26,44 +31,59 @@ void setup (void) { // All the blackbox code
rcc_periph_clock_enable(RCC_GPIOC); rcc_periph_clock_enable(RCC_GPIOC);
rcc_periph_clock_enable(RCC_GPIOA); rcc_periph_clock_enable(RCC_GPIOA);
// Enable AFIO (we need that to map GPIO to EXTI)
rcc_periph_clock_enable(RCC_AFIO);
// Enable EXTI0 interrupt.
// The interrupts are a bit magic, as the Internet says (the datasheet for F100RBT6B does not mention the EXTI/NVIC interface)
// This one is for EXTI0 ~~ GPIOx0 pins
nvic_enable_irq(NVIC_EXTI0_IRQ);
// GPIO C8 amd C9 are the two LEDs // GPIO C8 amd C9 are the two LEDs
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO8 | GPIO9); gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO8 | GPIO9);
// GPIO A0 is the push button // GPIO A0 is the push button
// And we set it as a regular button and enable its interrupts in the next block
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO0); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO0);
// Configure the EXTI0 interrupts
// 1. Which pin
exti_select_source(EXTI0, GPIOA);
// 2. Which edge
exti_set_trigger(EXTI0, EXTI_TRIGGER_RISING);
// 3. Enable the interrupts
exti_enable_request(EXTI0);
} }
void initial_wait (void) { // libopencm3 has a pre-declared interrupt handlers, so it needs to have this name
gpio_clear(GPIOC, GPIO8 | GPIO9); void exti0_isr (void) {
while (gpio_get(GPIOA, GPIO0) == 0); // Clear the interrupt
return; exti_reset_request(EXTI0);
// NB: For some reason it is at the begining in the examples
// It needs to be here (possibly because of reordering, when this was at the end, I usually got the interrupt twice).
if (!running) {
direction = FORWARD;
} else {
direction = direction == FORWARD ? BACKWARD : FORWARD;
}
running = true;
} }
int main (void) { int main (void) {
setup(); setup();
initial_wait();
// Array of what leds should be on // Array of what leds should be on
uint16_t states[4] = {0, GPIO9, GPIO8, GPIO9 | GPIO8}; uint16_t states[4] = {0, GPIO9, GPIO8, GPIO9 | GPIO8};
enum {FORWARD, BACKWARD} direction = FORWARD;
bool pressed = true;
bool change = false;
char state = 0; char state = 0;
int i; int i;
while (true) { while (true) {
change = false;
for (i=0 ; i<DELAY ; i++) { for (i=0 ; i<DELAY ; i++) {
if (/*Button pressed, but was not*/ gpio_get(GPIOA, GPIO0) && (pressed == false) ) { __asm ("nop");
pressed = true;
change = true;
} else if (/*Button not pressed*/gpio_get(GPIOA, GPIO0) == 0) {
pressed = false;
}
} }
if (change) direction = (direction == FORWARD ? BACKWARD : FORWARD); // Switch direction
state = (direction == FORWARD ? (state + 1)%4 : (/*state+4-1*/ state+3)%4 ); // New state state = (direction == FORWARD ? (state + 1)%4 : (/*state+4-1*/ state+3)%4 ); // New state
gpio_set(GPIOC, states[state]); gpio_set(GPIOC, states[state]);

Loading…
Cancel
Save