0% found this document useful (0 votes)
9 views

Lab 09

This document details Lab 09 for an Embedded Systems course, focusing on AVR Timer Interrupts using the ATmega328p microcontroller. It outlines the learning outcomes, hardware resources, and provides a comprehensive explanation of timer interrupts, including their implementation and benefits. Additionally, it includes lab tasks that involve coding for a seven-segment display and an LCD, demonstrating the use of interrupts for efficient task management.

Uploaded by

mokishere
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

Lab 09

This document details Lab 09 for an Embedded Systems course, focusing on AVR Timer Interrupts using the ATmega328p microcontroller. It outlines the learning outcomes, hardware resources, and provides a comprehensive explanation of timer interrupts, including their implementation and benefits. Additionally, it includes lab tasks that involve coding for a seven-segment display and an LCD, demonstrating the use of interrupts for efficient task management.

Uploaded by

mokishere
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Embedded System

Lab 09
AVR Timer Interrupts

Submitted By:
Asna Maqsood
426990
BESE13 B

1
Embedded System
Lab 09
AVR Timer Interrupts

Submitted By:
Muhammad Ahsan
406267
BESE13 B

2
Embedded System
Lab 09
AVR Timer Interrupts

Submitted By:
Muhammad Owais Khan
404262
BESE13 B

3
Embedded System
Lab 09
AVR Timer Interrupts

Submitted By:
Umar Farooq
406481
BESE13 B

4
Lab 9: AVR Timer Interrupts
EE222: Microprocessor Systems

Contents
1 Acknowledgements .................................................................................................................... 1

2 Administrivia ............................................................................................................................... 1
2.1 Learning Outcomes ........................................................................................................................................... 1
2.2 Deliverables .......................................................................................................................................................... 2
3 Hardware Resources .................................................................................................................. 2
4 Interrupts....................................................................................................................................... 2
4.1 Timer Interrupts ................................................................................................................................................. 2
4.2 Understanding the merits of interrupts .................................................................................................. 3
5 Lab Tasks ...................................................................................................................................... 7
5.1 Task A........................................................................................................................................................................ 7

1 Acknowledgements
This lab exercise is prepared by Mohammad Azfar Tariq and Muhammad Usman under
the supervision of Dr. Rehan Ahmed for the course EE-222 Microprocessor Systems,
focusing on the ATmega16 microcontroller. Later on, the lab was revised for the
ATmega328p Arduino Uno-based microcontroller by Lab Engr. Shaiza. Reporting any
errors or discrepancies found in the text is appreciated.

2 Administrivia
2.1 Learning Outcomes
By the end of this lab you will be able to:

1. Code timer interrupts for efficient scheduling in ATmega328p.

5
2.2 Deliverables
You are required to submit

• Appropriately commented Source Code

• Experimental observations and problems you faced in the

beginning of next lab.

3 Hardware Resources
• Arduino Uno board with ATmega328p microcontroller

• Arduino USB cable

• Seven Segment Display

• Resistances 47Ω

• Switch

• LCD 16 x 2

4 Interrupts
In previous labs we implemented delays by polling the timer overflow flag. Although
accurate, but this still is a process that consumes all the processing time (and energy) just
waiting for a flag. In this lab we are going to use interrupts. Interrupts are implemented
through special block of hardware integrated inside the processing device. Whenever
some specified event occurs, the hardware halts the normal execution of code and move
instruction pointer to a reserved block of code called interrupt service routine and the
process is called interrupting the processor. To understand how this happens and in what
basic forms the technique can be exploited, we will use the timer interrupts in this lab.

4.1 Timer Interrupts


There are eight interrupts associated with timers. Whenever an event from the list below
occurs,

1. The hardware halts normal execution of code.

2. Pushes the address of next instruction on stack.

3. Jumps to Program memory location specified in the table below.

4. Execute the code written there.

6
5. After successful execution pops back the address of instruction and continue
normal execution.

Interrupt Program Memory Location


Timer 2 Compare Match A 0x000E
Timer 2 Compare Match B 0x0010
Timer 2 Overflow 0x0012
Timer 1 Capture Event 0x0014
Timer 1 Compare Match A 0x0016
Timer 1 Compare Match B 0x0018
Timer 1 Overflow 0x001A
Timer 0 Compare Match A 0x001C Timer
0 Compare Match B 0x001E
Timer 0 Overflow 0x0020

4.2 Understanding the merits of interrupts


Suppose we have to design a system such that two independent tasks are to be performed
at the same time. One is to toggle an led with 4Hz frequency and other is to relay the state
of a switch to another led.
If we use a delay function to produce 250ms delay, our microcontroller will get busy
polling over the overflow flag (or Compare match flag if using CTC mode) and it will not
be able attend the transitions in state of switch for about 250ms.
Interrupts can rescue us from such situations. Let us understand the code below,

7
#include <avr/io.h>
#include <avr/interrupt.h>
#define LED01 1 // defining led 1 location
#define LED02 2 // defining led 2 location
#define SW 7 // defining switch location int
main( )
{
/*
Setting the pin number specified by macros
LED01 and LED02 of port B as output pins .

Pin specified by macro SW will naturally


be set as input .*/
DDRD = (1<<LED01)|(1<<LED02) ;
PORTD = (1<<LED01) ; // turning on led 1
// initializing timer
TCNT1 = 49910;
TCCR1A = 0x00 ;
TCCR1B = 0x04 ; //Normal Mode and setting prescalar clk /256
TCCR1C = 0x00 ;
sei ( ) ; // enable global interrupt
TIMSK1 = 0x01 ; // enable timer 1 overflow interrupt
while (1)
{
if ( (PIND & (1 << SW) ) != 0) // check if switch is high
{
PORTD |= (1<<LED02) ; // turn on led 2
} else
{
PORTD &= !(1<<LED02) ; // turn off led 2
}
}
}
ISR (TIMER1_OVF_vect)
{
TCNT1 = 49910; // reload timer
PORTD = PORTD ^ (1<<LED01) ; // toggle led 1
}

We are using clock of 16MHz with 256 prescalar,


Time for one tick=256/16M=16us
Ticks for 250ms=250/16=15625

8
Value to be loaded in TCNT1=65535-15625=49910

“sei( )” function defined in “avr/interrupt.h” sets the global interrupt enable bit. If this
bit is not set, no interrupt will be responded to.
The TIMSK (Timer Interrupt Mask) registers in the ATmega328P microcontroller contain
bits to enable individual timer interrupts. There are three different TIMSK registers, each
corresponding to a specific timer:
1. TIMSK0: Related to Timer/Counter 0. 2.
TIMSK1: Related to Timer/Counter 1.
3. TIMSK2: Related to Timer/Counter 2.
Each of these registers allows you to enable or disable specific interrupts for their
respective timers.

TIMSK0 -- -- -- -- -- OCIE0B OCIE0A TOIE0

TIMSK1

TIMSK2 -- -- ICIE1 -- -- OCIE1B OCIE1A TOIE1


--
-- -- -- -- OCIE2B OCIE2A TOIE2
TIMSK bit Function
OCIE2B When 1, enables Timer 2 Compare Match B interrupt OCIE2A
When 1, enables Timer 2 Compare Match A interrupt TOIE2 When 1,
enables Timer 2 Overflow interrupt
TICIE1 When 1, enables Timer 1 Input Capture interrupt
OCIE1A When 1, enables Timer 1 Compare Match A interrupt
OCIE1B When 1, enables Timer 1 Compare Match B interrupt
TOIE1 When 1, enables Timer 1 Overflow interrupt
OCIE0B When 1, enables Timer 0 Compare Match B interrupt OCIE0A
When 1, enables Timer 0 Compare Match A interrupt TOIE0 When 1,
enables Timer 0 overflow interrupt
Note that the number of timer interrupts is same as the number of timers related flags in
Timer interrupt flag registers (TIFR).
In while loop the switch is being polled and its state is being relayed to led 2. In parallel
with this process, timer is continuously being incremented and as it overflows, the timer
1 overflow flag is set. The processor is interrupted, it stops whatever it is executing at that
moment (in the main function) and jumps to “ISR(TIMER1_OVF_vect)”, executes the
code written there and then resumes from where it stopped the normal processing. All
these steps are performed by hardware itself to make the life of programmer easy. While
the processor is attending an ISR (Interrupt Service Routine), the flag which was the cause
of that interrupt (like TOV1 in example above) is automatically cleared by the processor.
Service Routines for other timer interrupts can be written by passing following macros
(vector names) defined in “avr/interrupt.h” as an argument to ISR.

9
Interrupt Vector name
Timer2 Compare Match A TIMER2_COMPA_vect
Timer2 Compare Match B TIMER2_COMPB_vect
Timer2 Overflow TIMER2_OVF_vect
Timer1 Capture Event TIMER1_CAPT_vect
Timer1 Compare Match A TIMER1_COMPA_vect
Timer1 Compare Match B TIMER1_COMPB_vect
Timer1 Overflow TIMER1_OVF_vect
Timer0 Compare Match A TIMER0_COMPA_vect
Timer0 Compare Match B TIMER0_COMPB_vect
Timer0 Overflow TIMER0_OVF_vect
1 ISR (.......... )
2 {
3 ...
4 ...
5 }

More than one ISRs can be written in a program but for different interrupts (not for the
same interrupt). When the processor is servicing one interrupt, it ignores other
interrupts.

10
5 Lab Tasks
5.1 Task A

1. Connect a seven-segment display (SSD) to your ATmega328p and ensure it displays a


continuous counting sequence from 0-9 with a 1-second delay between each digit. Once
it reaches 9, the sequence should restart at 0.
2. Connect a switch (SW) to generate an interrupt signal. When the switch is pressed
(interrupt triggered), the SSD counting should pause. Instead of interacting with an LED,
a 16x2 LCD should display your name (e.g., "Syed Zain Ul Hassan") scrolling from
right to left across the screen.
3. The scrolling name on the LCD should continue until the switch is pressed again, at
which point the LCD display should stop, and the SSD should resume counting from
where it was paused.
4. Both tasks (SSD counting and LCD scrolling) must run independently and in parallel to
avoid lag when switching between functionalities.

Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

volatile bool interruptFlag = false;


volatile bool timerFlag = false;
volatile int currentNumber = 0;

void setup() {
lcd.begin(16, 2);
DDRB = 0xFF;
DDRC = 0xFF;
DDRD &= ~(1 << PD2);
DDRB |= 0x01;

enableINT0();
setupTimer1();
}

void loop() {
if (interruptFlag) {
String text = "Ahsan Owais Umar Asna";
int textLength = text.length();

for (int position = 0; position < textLength + 16; position++) {


lcd.clear();
lcd.setCursor(16 - position, 0);
lcd.print(text);
delay(200);
}
11
interruptFlag = false;
}

if (timerFlag) {
PORTC = SevenSegment(currentNumber);
bool v = (SevenSegment(currentNumber) >> 6) & 1;

if (v) {
PORTB = 0x01;
} else {
PORTB = 0x00;
}

currentNumber = (currentNumber + 1) % 10;


timerFlag = false;
}
}

void enableINT0() {
sei();
EIMSK |= (1 << INT0);
MCUCR &= ~((1 << ISC01) | (1 << ISC00));
}

void setupTimer1() {
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS12) | (1 << CS10);
OCR1A = 15624;
TIMSK1 |= (1 << OCIE1A);
sei();
}

ISR(INT0_vect) {
interruptFlag = true;
}

ISR(TIMER1_COMPA_vect) {
timerFlag = true;
}

char SevenSegment(char number) {


if (number == 0) return 0x7E;
else if (number == 1) return 0x30;
else if (number == 2) return 0x6D;
else if (number == 3) return 0x79;
else if (number == 4) return 0x33;
else if (number == 5) return 0x5B;
else if (number == 6) return 0x5F;
else if (number == 7) return 0x70;
else if (number == 8) return 0x7F;
else if (number == 9) return 0x7B;
else return 0x00;
12
}

int main(void) {
setup();
while (1) {
loop();
}
}

Output:

13

You might also like