AVR Programming CS212 Dick Steflik ATmega 328 P

  • Slides: 22
Download presentation
AVR Programming CS-212 Dick Steflik

AVR Programming CS-212 Dick Steflik

ATmega 328 P

ATmega 328 P

I/O for our labs To get data into and out of our Arduino its

I/O for our labs To get data into and out of our Arduino its a little trickier than using printf and scanf as you did in CS 211 Since the Arduino doesn't have an Operating System we need to write and read data directly to/from the I/O ports Access to the ports is through the Special Function Registers (SFRs) that are defined symbolically in iom 328 p. h which is included in your program by io. h

io. h # include <avr/iom 165 p. h> #elif defined (__AVR_ATmega 168__) # include

io. h # include <avr/iom 165 p. h> #elif defined (__AVR_ATmega 168__) # include <avr/iom 168. h> #elif defined (__AVR_ATmega 168 P__) # include <avr/iom 168 p. h> #elif defined (__AVR_ATmega 169__) # include <avr/iom 169. h> #elif defined (__AVR_ATmega 169 P__) # include <avr/iom 169 p. h> #elif defined (__AVR_ATmega 8 HVA__) # include <avr/iom 8 hva. h> #elif defined (__AVR_ATmega 16 HVA__). . . # include <avr/iom 3250. h> #elif defined (__AVR_ATmega 3250 P__) # include <avr/iom 3250. h> #elif defined (__AVR_ATmega 328 P__) || defined (__AVR_ATmega 328__) # include <avr/iom 328 p. h> #elif defined (__AVR_ATmega 329__) # include <avr/iom 329. h> #

iom 328 p. h /* avr/iom 328 p. h - definitions for ATmega 328

iom 328 p. h /* avr/iom 328 p. h - definitions for ATmega 328 P. */ /* This file should only be included from <avr/io. h>, never directly. */ #ifndef _AVR_IO_H_ # error "Include <avr/io. h> instead of this file. " #endif #ifndef _AVR_IOXXX_H_ # define _AVR_IOXXX_H_ "iom 328 p. h" #else # error "Attempt to include more than one <avr/io. XXX. h> file. " #endif #ifndef _AVR_IOM 328 P_H_ #define _AVR_IOM 328 P_H_ 1 /* Registers and associated bit numbers */ #define PINB _SFR_IO 8(0 x 03) #define PINB 0 0 #define PINB 1 1 #define PINB 2 2 #define PINB 3 3 #define PINB 4 4 #define PINB 5 5 #define PINB 6 6 #define PINB 7 7 #define DDRB _SFR_IO 8(0 x 04) #define DDB 0 0 #define DDB 1 1 #define DDB 2 2 #define DDB 3 3 #define DDB 4 4

sfr_defs. h included in every compile via io. h contains macro definitions for accessing

sfr_defs. h included in every compile via io. h contains macro definitions for accessing Special Function Registers as if they were just c language variables in iom 328 p. h the statement: #define PINB _SFR_IO 8(0 x 03) the symbol PINA is mapped to the SFR at address 0 x 03 in SFR memory _SFR_IO 8( ) is a macro (look in sfr_defs. h )

Why this is done in your program you #include io. h and io. h

Why this is done in your program you #include io. h and io. h in turn includes iom 328 p. h (because in your project definition you picked the ATmega 328 p as the processor) pass 1 of the compiler does all includes and macro substitutions ( in our example with PINA all occurrences of the symbol PINB in your program will be replaced with a reference to SFR 0 x 03) This makes all SFR references look like references to C variables

Memories

Memories

Getting Digital Data Into and Out Of Initialize the ports B or D set

Getting Digital Data Into and Out Of Initialize the ports B or D set bits in the Data Direction Registers (DDRB and DDRD) for input or output use PORTB or PORTD for output 1 for output ; 0 for input don't forget the current limiting, series resistors use PINB or PIND for input don't forget the pull-up resistors

Blink. c /*---------------------------------------*/ /* Name: Blink. c */ /* Author: Steflik */ /* Description:

Blink. c /*---------------------------------------*/ /* Name: Blink. c */ /* Author: Steflik */ /* Description: This is the MCU equivalent of Hello World, instead of saying */ /* “Hello World” it blinks an led at a one second rate */ /*---------------------------------------*/ #include <avr/io. h> #define F_CPU 16000000 UL #include <util/delay. h> //This contains definitions for all the registers locations // other things, must always be included //F_CPU tells the compiler that our crystal is an 16 Mhz one // can generate an accurate delay, must be declared above // delay knows what is the value of F_CPU //Contains some delay functions that will generate accurate // of ms and us and some so it delay so delays int main(void){ //In ANSI C, the main function as always an int return and using // void will give you an warning DDRB |= (1<<PB 5); //Define digital pin 13/PORTB 5 as an output so we can blink our led while(1){ //This gives us an infinite loop, there should always be an infinite loop // in your code, because micro-controllers cant return from main // to anywhere and that will give you bad results and unpredicted // behavior PORTB |= (1<<PB 5); _delay_ms(1000); PORTB &= ~(1<<PB 5); _delay_ms(1000); } return 1; } //Turn //Wait led on, this is the led included in the arduino(digital pin 13) 1 second led off another second

daemons a daemon is a program that will sit in memory forever and run

daemons a daemon is a program that will sit in memory forever and run until the system loses power since most embedded system run forever (until they lose power) our main() should be written as a never ending loop. processing to be done can be done either in the body of the loop or asynchronously in response to an external or internal event (interrupt)

Interrupts How Interrupts are handled Somewhere in your program you define an Interrupt Servicing

Interrupts How Interrupts are handled Somewhere in your program you define an Interrupt Servicing Subroutine (ISS), the compiler will put the address of this routine into the proper location in the interrupt vector (low memory) When the interrupt occurs the system state is saved, a branch to the ISS is made via the interrupt vector The ISS executes and returns the state of the system and you are right where you were before the interrupt occurred

ATmega 328 p Interrupt Vector

ATmega 328 p Interrupt Vector

What we want to do use 8 LEDs for output 8 switches for input

What we want to do use 8 LEDs for output 8 switches for input 1 button to tell when it is OK to read the switches to do this we should us an interrupt

The way it should work /* Interrupt handler */ { // disable interruptes //

The way it should work /* Interrupt handler */ { // disable interruptes // read the switches // save the data at the next location in an array // light the lights // enable interrupts } int main () { // initialize ports B & D // initial Port E for interrupt on PE 2 // loop forever – this is our daemon }

volatile keyword the keyword “volatile” should be used to define any variable that may

volatile keyword the keyword “volatile” should be used to define any variable that may be modified inside of an interrupt handler “volatile” flags a variable to the optimizing compiler to not optimize variables with the “volatile” keyword volatile char switches = 0; volatile uint 8_t flags = 0;

char & uint 8_t Remember the char data type can be used for ASCII

char & uint 8_t Remember the char data type can be used for ASCII characters or a signed 8 bit integer The AVR header files define another data type that allows an unsigned 8 bit integer, this is convenient for working with gpio ports as they are not usually signed data.

internal pullups for gpio inputs on many MCUs you must add an external pullup

internal pullups for gpio inputs on many MCUs you must add an external pullup resistor on gpio input lines Atmel MCUs have built-in internal pullup resistors to use the internal pullups write a one to that line after it has been defined as an input line in the DDR // define Port B as all outputs and Port D as all inputs DDRB = 0 x. FF; DDRD = 0 x 00; //turn on the internal pullup resistors for Port D PORTD = 0 x. FF;

Setting up an interrupt handler Signal or ISR the ISR macro has superceded the

Setting up an interrupt handler Signal or ISR the ISR macro has superceded the Signal macro and is the preferred way of setting up an interrupt handler ISR( name of the int from processor. h file) {. . . . } ISR(SIG_PIN_CHANGE 1) {. . }

Pin Change Interrupts Input lines on Ports B, C and D can be set

Pin Change Interrupts Input lines on Ports B, C and D can be set up to generate a pin change interrupt Each port has an associated mask register to enable an interrupt put a 1 into the correct position in the appropriate mask register Port B PCMSK 2 Port C PCMSK 1 Port D PCMSK 0

PCINT Mapping PCINT 7 PCINT 6 PCINT 5 PCINT 4 PCINT 3 PCINT 2

PCINT Mapping PCINT 7 PCINT 6 PCINT 5 PCINT 4 PCINT 3 PCINT 2 PCINT 1 PCINT 0 PORT D 7 6 5 4 3 2 1 0 PCINT 23 PCINT 22 PCINT 21 PCINT 20 PCINT 19 PCINT 18 PCINT 17 PCINT 16 PORT B 7 6 5 4 3 2 1 0 SIG_PIN_CHANGE 1

Example //set bit 2 of Port B to cause an interrupt PCMSK 1 =

Example //set bit 2 of Port B to cause an interrupt PCMSK 1 = 0 x 04; // set bit 2 of Port B to cause interrupt EIMSK = 0 x. C 0; // Ext Int Mask Reg EIFR = 0 x. C 0; // Ext Int Flag Reg DDRB & = 0 x. FB; // make bit 2 an input line PORTB | = 0 x 04; // turn on pullup ISR(SIG_PIN_CHANGE 1) { cli( ); // disable interrupts. . . sei( ); // enable interrupts }