Title: Butterfly IO Ports
1Butterfly I/O Ports
2I/O for our labs
- To get data into and out of our Butterfly its a
little trickier than using printf and scanf as
you did in CS211 - Since the Butterfly 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 iom169.h which is included in
your program by io.h
3io.h
include ltavr/iom165p.hgt elif defined
(__AVR_ATmega168__)? include
ltavr/iom168.hgt elif defined (__AVR_ATmega168P__)?
include ltavr/iom168p.hgt elif defined
(__AVR_ATmega169__)? include
ltavr/iom169.hgt elif defined (__AVR_ATmega169P__)?
include ltavr/iom169p.hgt elif defined
(__AVR_ATmega8HVA__)? include
ltavr/iom8hva.hgt elif defined (__AVR_ATmega16HVA__
)?
4iom169.h
/ iom169.h - definitions for ATmega169 / /
This should be up to date with data sheet version
2514J-AVR-12/03. / ifndef _AVR_IOM169_H_ defin
e _AVR_IOM169_H_ 1 / This file should only be
included from ltavr/io.hgt, never directly.
/ ifndef _AVR_IO_H_ error "Include
ltavr/io.hgt instead of this file." endif ifndef
_AVR_IOXXX_H_ define _AVR_IOXXX_H_
"iom169.h" else error "Attempt to include
more than one ltavr/ioXXX.hgt file." endif /
I/O registers / / Port A / define PINA
_SFR_IO8(0x00)? define DDRA _SFR_IO8(0x01)? de
fine PORTA _SFR_IO8(0x02)? / Port B / define
PINB _SFR_IO8(0x03)? define DDRB
_SFR_IO8(0x04)?
5sfr_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 iom169.h the statement define
PINA _SFR_IO8(0x00) the symbol PINA is mapped
to the SFR at address 0x00 in SFR memory - _SFR_IO8( ) is a macro (look in sfr_defs.h )?
6Why this is done
- in your program you include io.h and io.h in
turn includes iom169.h (because in your project
definition you picked the ATmega169 as the
processor)? - pass 1 of the compiler does all includes and
macro substitutions ( in our example with PINA
all occurrences of the symbol PINA in your
program will be replaced with a reference to SFR
0x00)? - This makes all SFR references look like
references to C variables
7Memories
8Getting Data Into and Out Of
- Initialize the ports
- set the Data Direction Registers (DDRs)?
- use PORTB for input
- use the 8 input DIP switch for inputting data
- don't forget the pull-up resistors
- use PORTD for showing output
- use 8 LEDS
- don't forget the current limiting, series
resistors
9Design
- This warrants 3 subroutines
- one to do initialization
- one to do input
- one to do output
- These should be written very general purpose as
we will use them for many of the labs
10daemons
- 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)?
11Interrupts
- How Interrupts are handled
- Somewhere in your program you define an Interrupt
Servicing Subroutine, 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
12ATmega169 Interrupt Vector
13What 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
14The 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 PE2 // loop forever this is our daemon
15volatile 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
uint8_t flags 0
16char uint8_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.
17internal 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 0xFF DDRD 0x00 //turn on the
internal pullup resistors for Port D PORTD 0xFF
18Setting 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_CHANGE1)? ....
19Pin Change Interrupts
- Input lines on Ports B and E 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 PCMSK1
- Port E PCMSK0
20PCINT Mapping
PORT E PCINT7 7 SIG_PIN_CHANGE0 P
CINT6 6 PCINT5 5 PCINT4 4 PCINT3 3 PCINT2 2 PCINT
1 1 PCINT0 0 PORT B PCINT15 7
SIG_PIN_CHANGE1 PCINT14 6 PCINT13 5 PCINT12 4
PCINT11 3 PCINT10 2 PCINT9 1 PCINT8 0
21Example
//set bit 2 of Port B to cause an
interrupt PCMSK1 0x04 // set bit 2 of
Port B to cause interrupt EIMSK 0xC0
// Ext Int Mask Reg EIFR 0xC0 //
Ext Int Flag Reg DDRB 0xFB // make
bit 2 an input line PORTB 0x04 //
turn on pullup ISR(SIG_PIN_CHANGE1)?
cli( ) // disable interrupts . .
. sei( ) // enable interrupts