/* * 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 #include #include #include #include #include //#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 #define STM32F1 1 // Needed for libopencm3 volatile enum {FORWARD, BACKWARD} direction; volatile bool running = false; void setup_system (void) { // Set up clock rcc_clock_setup_in_hse_8mhz_out_24mhz(); } void setup_gpio_out (void) { // Enable clock for GPIO C 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 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 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 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; } 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); } } int main (void) { setup(); // Array of what leds should be on uint16_t states[4] = {0, 0, GPIO8, GPIO8}; char state = 0; int i; // Initial wait while (!running) ; while (true) { for (i=0 ; i