diff --git a/content/08_embedded_programming.md b/content/08_embedded_programming.md new file mode 100644 index 0000000000000000000000000000000000000000..23a3fe88cc08813d4ba9632b80b8e966401f397d --- /dev/null +++ b/content/08_embedded_programming.md @@ -0,0 +1,68 @@ ++++ +title = "Embedded Programming" +date = "2018-10-19" +menu = "main" +weight = 9 ++++ + +## Embedded Programming + +Files: [blink.c](/designs/07_blink.c) + +This week we need to take a board we've made and give it some new functionality. No more flashing with pre-written code. + +Two weeks ago I added an LED and a button to Neil's [hello world](http://academy.cba.mit.edu/classes/embedded_programming/index.html#echo) board, so I'll start by making the LED turn on. I attached my LED to port PB2, and my switch to port PA7. To turn on the LED, we only need to do two things: enable PB2 as an output, and set it high. Here's code that does just that. + +``` +#include <avr/io.h> + +#define led_pin (1 << PB2) + +int main(void) { + // Configure led_pin as an output. + DDRB |= led_pin; + + // Set led_pin high. + PORTB |= led_pin; + + // Nothing left to do, so just spin. + while (1) {} + + return 0; +} +``` + +Next let's use the button. The easiest approach is to use the button as a contact switch, turning on the LED only for the duration of the button press. To do this we'll need to configure pin PA7 as an input. I didn't add a pullup resistor on my board, so I also have to enable PA7's internal one. This will ensure that PA7 reads high when the button isn't pressed. + +``` +#include <avr/io.h> + +#define led_pin (1 << PB2) +#define switch_pin (1 << PA7) + +int main(void) { + // Configure led_pin as an output. + DDRB |= led_pin; + + // Configure switch_pin as an input. + DDRA |= switch_pin; + + // Activate switch_pin's pullup resistor. + PORTA |= switch_pin; + + while (1) { + // Turn on the LED when the button is pressed. + if (PINA & switch_pin) { + // Turn off the LED. + PORTB &= ~led_pin; + } else { + // Turn on the LED. + PORTB |= led_pin; + } + } + + return 0; +} +``` + + diff --git a/static/designs/08_blink.c b/static/designs/08_blink.c new file mode 100644 index 0000000000000000000000000000000000000000..eb33d733640c7d32202eaefefcca98ce8f427e00 --- /dev/null +++ b/static/designs/08_blink.c @@ -0,0 +1,78 @@ +#include <avr/io.h> + +#define switch_pin (1 << PA7) +#define led_pin (1 << PB2) + +int main(void) { + // Set the clock prescaler to 1. + CLKPR = (1 << CLKPCE); + CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); + + // Set the 8 bit timer's prescaler to 1/1024. + TCCR0B |= 0b00000101; + + // Configure led_pin as an output. + DDRB |= led_pin; + + // Configure switch_pin as an input. + DDRA |= switch_pin; + + // Activate switch_pin's pullup resistor. + PORTA |= switch_pin; + + //int count1 = 0; + //int count2 = 0; + + int bouncy_switch_state = 0; + int debounced_switch_state = 0; + + while (1) { + // Turn on the led when the button is pressed + /* + if (PINA & switch_pin) { + PORTB &= ~led_pin; + } else { + PORTB |= led_pin; + } + */ + + // ~5s blink period based on counting + /* + if (++count1 == 255) { + if (++count2 == 255) { + PORTB ^= led_pin; + count1 = 0; + count2 = 0; + } + } + */ + + // ~2.5s second blink period + // 255 * 200 * (1024 / 20M) = 2.6112 + /* + if (TCNT0 >= 200) { + TCNT0 = 0; + if (++count1 == 255) { + PORTB ^= led_pin; + count1 = 0; + } + } + */ + + // the button toggles the led (with debouncing) + if ((PINA & switch_pin) != bouncy_switch_state) { + bouncy_switch_state = PINA & switch_pin; + TCNT0 = 0; + } + if (TCNT0 >= 195) { + // It's been 10ms since the switch changed. + if (bouncy_switch_state != debounced_switch_state) { + debounced_switch_state = bouncy_switch_state; + if (debounced_switch_state == 0) { + PORTB ^= led_pin; + } + } + } + } +} +