CMP3006
EMBEDDED SYSTEMS
PROGRAMMING
LECTURE 5 INTERRUPTS & ANALOG INPUT (ADC)
Atmega 328 Pinout
I/O Memory (SFR) Overview
See. Datasheet of Atmega328
Interrupts
Allow program to respond to events when they occur
Allow program to ignore events until the occur
External events e.g.:
UART ready with/for next character
Signal change on pin
Action depends on context
# of edges arrived on pin
Internal events e.g.:
Power failure
Arithmetic exception
Timer “tick”
ATmega328 Interrupts
The ATmega328P provides support for 25 different interrupt sources. These
interrupts and the separate Reset Vector each have a separate program vector
located at the lowest addresses in the Flash program memory space.
The complete list of vectors is shown in Table 11-6 “Reset and Interrupt Vectors
in ATMega328P. Each Interrupt Vector occupies two instruction words.
The list also determines the priority levels of the different interrupts. The lower
the address the higher is the priority level.
RESET has the highest priority, and next is INT0 – the External Interrupt Request 0.
SREG – Status Register (0x5F)
Bit 7 – I: Global Interrupt Enable
Bit 6 – T: Bit Copy Storage
Bit 5 – H: Half Carry Flag
Bit 4 – S: Sign Bit
Bit 3 – V: Two’s Complement Overflow Flag
Bit 2 – N: Negative Flag
Bit 1 – Z: Zero Flag
Bit 0 – C: Carry Flag
ATmega328 Interrupts
ATmega328 Interrupts
Interrupt Model
When an interrupt event occurs:
Processor does an automatic procedure call
CALL automatically done to address for that interrupt
Push current PC, Jump to interrupt address
Each event has its own interrupt address
The global interrupt enable bit (in SREG) is automatically cleared
i.e. nested interrupts are disabled
SREG bit can be set to enable nested interrupts if desired
Interrupt procedure, aka “interrupt handler”
Does whatever it needs to, then returns via RETI
The global interrupt enable bit is automatically set on RETI
Interrupts
Type 1 – Event is remembered when interrupt is disabled
If interrupt is not enabled, flag is set
When interrupt is enabled again, interrupt takes place, and flag is reset
Type 2 – Event is not remembered when interrupt is disabled
Signal level causes interrupt
If level occurs when interrupt is enabled, interrupt takes place
If interrupt is not enabled, and level goes away before the interrupt is enabled, nothing
happens
Interrupt Model
Interrupt handler is invisible to program
Except through side-effects, e. g. via flags or variables
Changes program timing
Can’t rely on “dead-reckoning” using instruction timing
Must be written so they are invisible
Cannot stomp on program state, e. g. registers
Save and restore any registers used
Including SREG
Interrupt Vectors
Interrupt Vector
Table in memory containing the first instruction of each
interrupt handler
Typically at program address 0
Interrupt Vectors
If interrupts are not used, this memory can be used as part of the program
i.e. nothing special about this part of memory
Example interrupt routine
RESET: Sets up the stack pointer
Interrupts
Global interrupt enable
Bit in SREG
Allows all interrupts to be disabled with one bit
sei() – set the bit
cli() – clear the bit
Interrupt priority is determined by order in table
Lower addresses have higher priority
ISR(vector) – Interrupt routine definition
reti() – return from interrupt
automatically generated for ISR
External Interrupts
Monitors changes in signals on pins
What causes an interrupt can be configured by setting control registers
appropriately
Pins:
INT0 and INT1 – range of event options
INT0 – PORTD [2]
INT1 – PORTD [3]
PCINT[23:0] – any signal change (toggle)
PCINT[7:0] – PORT B [7:0]
PCINT[14:8] – PORT C [6:0]
PCINT[23:16] – PORT D [7:0]
Pulses on inputs must be slower than I/O clock rate
INT0 and INT1
External Interrupt Control Register
Sense Control (INT0 is the same)
INT0 and INT1
External Interrupt Mask Register
If INT# bit is set (and the SREG I-bit is set), then interrupts are enabled on pin INT#
External Interrupt Flag Register
Interrupt flag bit is set when a change triggers an interrupt request
Flag is cleared automatically when interrupt routine is executed
Flag can be cleared by writing a 1 to it
Arduino Platform Support for
External Interrupts
attachInterrupt(interrupt, function, mode)
interrupt: 0 or 1
function: interrupt function to call
mode: LOW, CHANGE, RISING, FALLING
detachInterrupt(interrupt)
interrupts( ) – Enable interrupts : sei( )
noInterrupts( ) – Disable interrupts : cli( )
Arduino Language Support for
External Interrupts
Variables shared between ISRs and normal functions should be declared
"volatile".
int pin = 13;
volatile int state = LOW;
attach interrupt
void setup() {
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}
Arduino Language Support for
External Interrupts
Write Interrupt Service Routine (ISR)
void blink() {
state = !state;
}
deattach
deattachInterrupt(0);
Arduino Macro for Interrupt Vector
•Use ISR Macro to handle interrupt
◦ ISR(EXT_INT0_vect)
{
◦ EIMSK = B00000001
◦ EICRA = B00000011
•Set Registers directly
ADC
AVR Architecture - ADC
•Analog inputs
•Convert voltage to a 10-bit digital value
•Can provide reference voltages
Analog I/O
Analog input pins: A0 – A5
Pins 14 – 19: PORTC [0:5]
Analog output pins: 3, 5, 6, 9, 10, 11 (digital pins)
Analog input functions
int val = analogRead(pin)
Converts 0 – 5v. voltage to a 10-bit number (0 – 1023)
Don’t use pinMode
analogReference(type) DEFAULT
Used to change how voltage is converted (advanced) INTERNAL
Analog output EXTERNA
L
analogWrite(pin, value)
value is 0 – 255
Generates a PWM output on digital pin (3, 5, 6, 9, 10, 11)
@490Hz frequencyS
Sample Circuits
Sample Circuits
ADC Registers
Bit 7 6 5 4 3 2 1 0
ADCSRA ADEN ADSC ADFR ADIF ADIE ADPS2 ADPS1 ADPS0
ADCSRB - ACME - - ADTS2 ADTS1 ADTS0
ADMUX REFS1 REFS0 ADLAR - MUX3 MUX2 MUX1 MUX0
ADCH
ADCL
ADC Registers
ADCMUX
REFSn: Reference Selection
00 AREF, Internal Vref turned off
01 AVCC with external capacitor at AREF pin
10 Reserved
11 Internal 1.1V Voltage Reference with external capacitor at AREF pin
ADLAR: ADC Left Adjust Result
MUXn: Analog Channel Selection
ADC Registers
ADCSRA
ADEN: ADC Enable
ADSC: ADC Start Conversion
ADATE: ADC Auto Trigger Enable
ADIF: ADC Interrupt Flag
ADIE: ADC Interrupt Enable
ADPSn: ADC Prescaler Select
ADPS[2:0] Division Factor
Bits Prescale
000 2
001 2
010 4
011 8
100 16
101 32
110 64
111 128
Analog Input
void adc_init(void)
{
ADMUX = (1<<REFS0); // select AVCC as reference
ADCSRA = (1<<ADEN) | 7; // enable and prescale = 128
// (16MHz/128 = 125kHz)
}
int readAdc(char chan)
{
ADMUX = (1<<REFS0) | (chan & 0x0f); //select input and ref
ADCSRA |= (1<<ADSC); //start the conversion
while (ADCSRA & (1<<ADSC)); //wait for end of conversion
return ADCW;
}