An example Discovery program built on Anton's refactor branch.
/*
Example for Discovery board built on Anton's refactor branch.
Shows:
LCD module library
GPIO inputs and outputs
Timers
Timer interrupts
External interrupts
Interrupt handlers
Demonstrates usage of the HardwareTimer classes by blinking the LEDs
Created 22 April 2010, By Bryan Newbold for LeafLabs
Updated 8 June 2010, By Bryan Newbold for LeafLabs
Modified 21 March 2011, for Discovery board By ridgebackred
Modified 6 April 2011, for Discovery board refactor branch By ridgebackred
This code is released with no strings attached.
Demonstrates the use a 20x2 LCD display. The LiquidCrystal
library works with all LCD displays that are compatible with the
Hitachi HD44780 driver. There are many of them out there, and you
can usually tell them by the 16-pin interface.
The circuit:
* LCD +5V to 5V
* LCD GND to GND
* LCD RS pin to PB10, digital pin 29, 5 Volt tolerant
* LCD Enable pin to PB11, digital pin 30, 5 Volt tolerant
* LCD D4 pin to PB12, digital pin 31, 5 Volt tolerant
* LCD D5 pin to PB13, digital pin 32, 5 Volt tolerant
* LCD D6 pin to PB14, digital pin 33, 5 Volt tolerant
* LCD D7 pin to PB15, digital pin 34, 5 Volt tolerant
* LCD R/W pin to GND
* 10K potentiometer:
* one end to GND
* wiper to LCD VO pin (pin 3)
************************************************************/
#include "wirish.h"
//Change the path name for your system...
#include <C:\libmaple\discovery2\libraries\LiquidCrystal\LiquidCrystal.h>
// Initialize the LCD library with the numbers of the interface pins
LiquidCrystal lcd(29, 30, 31, 32, 33, 34);
void handler_green_led (void);
void handler_blue_led (void);
void handler1 (void);
void handler2 (void);
voidFuncPtr handlers[] = {handler1, handler2};
timer_dev *timers[] = {TIMER1, TIMER2, TIMER3, TIMER4};
void initTimer(timer_dev *dev);
void setTimerPeriod(timer_dev *dev, uint32 period_us);
void testTimerChannels(timer_dev *dev);
int timerNumber(timer_dev *dev);
// These variables won't change during program execution
const int blueledPin = 37;
const int greenledPin = 38;
const int userbuttonPin = 2;
const int BLUE_LED_RATE = 500000; // Units = microseconds; should give 0.5Hz toggles
// These variables change during program execution
int count1 = 0;
int count2 = 0;
int toggle_blue = 0;
// Do housekeeping activities once at power-up
void setup()
{
// Set up the LED pins as outputs
pinMode(blueledPin, OUTPUT);
pinMode(greenledPin, OUTPUT);
// Set up User Button pin as input and attach interrupt handler
pinMode(userbuttonPin, INPUT);
attachInterrupt(userbuttonPin, handler_green_led, RISING);
// Set up the LCD's number of rows and columns:
lcd.begin(20, 2);
lcd.print("LibMaple ~ Discovery");
lcd.setCursor(0, 1);
lcd.print("IDE0.0.9 refactor");
delay(1500); // Show splash screen for a few seconds
lcd.clear();
lcd.setCursor(0, 0); // 1st column, 1st row
lcd.print("Count1 Count2");
// Setup blue LED toggle Timer
timer_set_mode(TIMER2, TIMER_CH1, TIMER_OUTPUT_COMPARE);
setTimerPeriod(TIMER2, BLUE_LED_RATE);
timer_set_compare(TIMER2, 1, 1); // Overflow might be small
timer_attach_interrupt(TIMER2, TIMER_CC1_INTERRUPT, handler_blue_led);
// Setup the counting Timers
timer_set_mode(TIMER3, TIMER_CH1, TIMER_OUTPUT_COMPARE);
timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE);
timer_pause(TIMER3);
timer_pause(TIMER4);
timer_set_count(TIMER3, 0);
timer_set_count(TIMER4, 0);
timer_set_reload(TIMER3, 15000);
timer_set_reload(TIMER4, 30000);
timer_set_compare(TIMER3, 1, 1000);
timer_set_compare(TIMER4, 1, 1000);
timer_attach_interrupt(TIMER3, TIMER_CC1_INTERRUPT, handler1);
timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler2);
timer_resume(TIMER3);
timer_resume(TIMER4);
}
// Forever loop after running setup()
void loop() {
delay(250); // Slow down the updates to the LCD
lcd.setCursor(0, 1); // 1st column, 2nd row
lcd.print(count1);
lcd.setCursor(10, 1); // 11th column, 2nd row
lcd.print(count2);
digitalWrite(greenledPin, LOW); // in case the button interrupt was hit
timer_resume(TIMER4); // in case the button interrupt was hit, restart timer
}
// User Button interrupt handler
// Will ignore the delay in the 'loop' to become active
void handler_green_led(void) {
digitalWrite(greenledPin, HIGH);
timer_pause(TIMER4); //Stop TIMER4 until restarted in loop()
}
// Timer2 interrupt handler
void handler_blue_led(void) {
toggle_blue ^= 1;
digitalWrite(blueledPin, toggle_blue);
}
// Timer3 interrupt handler
void handler1(void) {
count1++;
}
// Timer4 interrupt handler
void handler2(void) {
count2++;
}
//The following will probably change with release of IDE0.0.10
void initTimer(timer_dev *dev) {
switch (dev->type) {
case TIMER_ADVANCED:
case TIMER_GENERAL:
//Serial2.print("Initializing timer ");
//Serial2.println(timerNumber(dev));
for (int c = 1; c <= 4; c++) {
timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
}
//Serial2.println("Done.");
break;
case TIMER_BASIC:
break;
}
}
// FIXME move this into the new wirish timer implementation
int timerNumber(timer_dev *dev) {
switch (dev->clk_id) {
case RCC_TIMER1:
return 1;
case RCC_TIMER2:
return 2;
case RCC_TIMER3:
return 3;
case RCC_TIMER4:
return 4;
#ifdef STM32_HIGH_DENSITY
case RCC_TIMER5:
return 5;
case RCC_TIMER6:
return 6;
case RCC_TIMER7:
return 7;
case RCC_TIMER8:
return 8;
#endif
default:
ASSERT(0);
return 0;
}
}
// FIXME move this into the new wirish timer implementation
void setTimerPeriod(timer_dev *dev, uint32 period_us) {
if (!period_us) {
// FIXME handle this case
ASSERT(0);
return;
}
uint32 cycles = period_us * CYCLES_PER_MICROSECOND;
uint16 pre = (uint16)((cycles >> 16) + 1);
timer_set_prescaler(dev, pre);
timer_set_reload(dev, cycles / pre - 1);
}
// Force init to be called *first*, i.e. before static object allocation.
// Otherwise, statically allocated objects that need libmaple may fail.
__attribute__(( constructor )) void premain() {
init();
}
int main(void) {
setup();
while (1) {
loop();
}
return 0;
}