Lecture 7

Introduction to µC¶ Programming for Microcontrollers

Start
‡ int main(void) { while (1) { } } // start // repeat nothing to //infinity

Super Loop
‡ int main(void) { Initialize(); // program starts here // executed once // Superloop starts here // These tasks will be executed repetitively while (1) { Task1(); // say read temperature Task2(); // say process temperature Task3(); // say display temperature } } ‡ ‡ ‡ Microcontrollers repeat their operation so we use ³super loop architecture´. Internal or external interrupts produce an event that causes a routine to be executed at the triggering time, then normal execution goes on. The super loop architecture is used for tasks of low (and medium) complexity.

LED
‡ ‡ ‡ ‡ ‡ ‡ ‡ ‡ LEDs require about 20mA. When 20mA current flows forward into the LED, the voltage across it is around 2V. The rest 3V are across the resistor. For setting the current to 20mA, R1 should be 3V/20mA=150ohms. Less means excessive current and more means maximum brightness. 20mA is maximum so we choose less about 180ohms. 0 for on and 1 for off. Pin as output.

Button
‡ ‡ ‡ ‡ Configure pin as input. When not pressed the pin stays at logic 1. If pressed, current flows through the button and the port pin is grounded, logic 0. The current flowing is about 1mA and there is no reason for having more than that, even the internal 50k pull-up could be used instead. 1 for not pressed and 0 for pressed. The capacitor will smooth things out, it acts as a low pass filter preventing fast voltage changes when button bounces

‡ ‡

Switch it on
‡ #include <avr/io.h> int main(void) { DDRB = 255; PORTB = 0; return (0); } // header file // program starts here // set port B for output // set port B pins to 0 // return something

typedef
‡ ‡ typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to assign alternative names to existing types, most often those whose standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another. Both sections of code do the same thing. The use of typedef in the second example makes it easier to comprehend what is going on, namely, that one variable contains information about apples while the other contains information about oranges. ‡ Consider this code: int coxes; char jaffa; ... coxes++; ... if (jaffa == 'c') ... ‡ Now consider this: typedef int Apple; typedef char Orange; Apple coxes; Orange jaffa; ... coxes++; ... if (jaffa == 'c') ...

‡

C Language Bit Operators
‡ | bit OR & bit AND ~ bit NOT ^ bit EXLUSIVE OR (XOR) << bit LEFT SHIFT >> bit RIGHT SHIFT ‡ These operators work on the individual bits inside the byte.

Bit Setting
‡ Code: unsigned char foo = 0; To set bit 0 in foo and then store the result back into foo: Code: foo = foo | 0x01; Shorter one: Code: foo |= 0x01;

Bit Clearing
‡ Code: foo = foo & ~0x01; Shorter one: ‡ Code: foo &= ~0x01;

Bit Testing
‡ To see if a bit is set or clear just requires the AND operator, but with no assignment. ‡ Code: if(foo & 0x80) { } ‡ The condition will be NON-ZERO when the bit is set.

Bit Inversion
‡ Code: foo = foo ^ 0x01; Or ‡ Code: foo ^= 0x01;

Creating Bit Mask
‡ The way to build a bit mask with only a bit number is to LEFT SHIFT a bit by the bit number. ‡ To build a bit mask that has bit number 2 set: Code: (0x01 << 2) ‡ To build a bit mask that has bit number 7 set: Code: (0x01 << 7) ‡ To build a bit mask that has bit number 0 set: Code: (0x01 << 0)

Macros
‡ It provides a fast way of understanding what is happening when reading the code, or it provides additional functionality. ‡ Macros are replaced with actual code upon compilation. ‡ Code: ‡ #define bit_get(p,m) ((p) & (m)) #define bit_set(p,m) ((p) |= (m)) #define bit_clear(p,m) ((p) &= ~(m)) #define bit_flip(p,m) ((p) ^= (m)) #define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m)) #define BIT(x) (0x01 << (x)) #define LONGBIT(x) ((unsigned long)0x00000001 << (x))

Macro Examples
‡ To set a bit: Code: bit_set(foo, 0x01); ‡ To set bit number 5: Code: bit_set(foo, BIT(5)); ‡ To clear bit number 6 with a bit mask: Code: bit_clear(foo, 0x40); ‡ To flip bit number 0: Code: bit_flip(foo, BIT(0));

Macro Examples
‡ To check bit number 3: Code: if(bit_get(foo, BIT(3))) { } ‡ To set or clear a bit based on bit number 4: Code: if(bit_get(foo, BIT(4))) { bit_set(bar, BIT(0)); } else { bit_clear(bar, BIT(0)); } ‡ To do it with a macro: Code: bit_write(bit_get(foo, BIT(4)), bar, BIT(0));

Blinking LED
#include <avr/io.h> /// Typedefs ////////// typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long u32; /// Defines /////////// #define forever #define LEDOFF (1<<4) #define LEDON ~(1<<4) 117 PORTB |= PORTB &= int main(void) { InitPorts(); while (forever) { LEDON; Delay(20000); LEDOFF; Delay(20000); } } void InitPorts(void) { DDRB |= 1<<DDB4; } void Delay(u32 count) { while(count--); }

/// Prototypes //////// void InitPorts (void); void Delay (u32 count);

Blink with button
‡ int main(void) { u8 btnState; InitPorts(); LEDOFF; while (forever) { // button pin reading btnState = ~PINB & (1<<3); // action if (btnState) { LEDON; Delay(5000); LEDOFF; Delay(5000); } } }

Blinky
#include <avr/io.h> #include <avr/delay.h> int main (void) { // set PORTD for output DDRD = 0xFF; while(1) { for(int i = 1; i <= 128; i = i*2) { PORTD = i; _delay_loop_2(30000); } for(int i = 128; i > 1; i -= i/2) { PORTD = i; _delay_loop_2(30000); } } return 1; }

Sign up to vote on this title
UsefulNot useful