You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
stm32-better-blink/main.c

145 lines
3.7 KiB
C

9 years ago
/*
* My first project
*
* It blinks LEDs like counting in binary, when the button is pressed, it reverses the order
*
* Build on top of libopenocm3, blackbox parts of code (setup()) copied from
* libopencm3-examples/examples/stm32/f1/stm32vl-discovery/button project
*
* Open source licence, let's say Artistic Licence, although it doesn't matter, as it is local only
*/
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/f1/exti.h>
#include <libopencm3/stm32/f1/nvic.h>
#include <libopencm3/stm32/f1/timer.h>
9 years ago
#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 4000000 // This is bad -- it's a value that was found to be OK
9 years ago
#define STM32F1 1 // Needed for libopencm3
volatile enum {FORWARD, BACKWARD} direction;
volatile bool running = false;
void setup_system (void) {
// Set up clock
9 years ago
rcc_clock_setup_in_hse_8mhz_out_24mhz();
}
void setup_gpio_out (void) {
// Enable clock for GPIO C
9 years ago
rcc_periph_clock_enable(RCC_GPIOC);
// GPIO C8 amd C9 are the two LEDs
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO8 | GPIO9);
}
void setup_exti0_in (void) {
// Enable clock for GPIO A
9 years ago
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 A0 is the push button
// And we set it as a regular button and enable its interrupts in the next block
9 years ago
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);
9 years ago
}
void setup_tim6_periodic_irq (void) {
// Enable clock
rcc_periph_clock_enable(RCC_TIM6);
// Config:
// Set prescaler
timer_set_prescaler(TIM6, 65535);
// Set counter value
timer_set_period(TIM6, 183);
// Enable interrupts in NVIC
nvic_enable_irq(NVIC_TIM6_IRQ);
// Enable sending interrupts from the timer
timer_enable_irq(TIM6, TIM_DIER_UIE);
// Finally, enable the counter
timer_enable_counter(TIM6);
}
void setup (void) {
setup_system();
setup_gpio_out();
setup_exti0_in();
setup_tim6_periodic_irq();
}
// libopencm3 has a pre-declared interrupt handlers, so it needs to have this name
void exti0_isr (void) {
// Clear the interrupt
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;
9 years ago
}
void tim6_isr (void) {
timer_clear_flag(TIM6, TIM_SR_UIF);
// Just change value of GPIO C9 (green LED)
uint16_t cur = gpio_get(GPIOC, GPIO9);
if (cur) {
gpio_clear(GPIOC, GPIO9);
} else {
gpio_set(GPIOC, GPIO9);
}
}
9 years ago
int main (void) {
setup();
while (true) __asm ("wfi");
#ifdef NOT_ACTUALLY_DEFINED
9 years ago
// Array of what leds should be on
uint16_t states[4] = {0, 0, GPIO8, GPIO8};
char state = 0;
9 years ago
int i;
9 years ago
// Initial wait
while (!running) ;
9 years ago
while (true) {
9 years ago
for (i=0 ; i<DELAY ; i++) {
__asm ("nop");
9 years ago
}
9 years ago
state = (direction == FORWARD ? (state + 1)%4 : (/*state+4-1*/ state+3)%4 ); // New state
9 years ago
gpio_set(GPIOC, states[state]);
gpio_clear(GPIOC, (GPIO8) ^ states[state]);
9 years ago
}
#endif
9 years ago
return 0;
}
9 years ago