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

Lab 08

The document is a lab report on Timer Programming for the EE222 Microprocessor Systems course, focusing on the ATmega328p microcontroller. It includes acknowledgements, learning outcomes, hardware resources, and detailed sections on AVR timers, programming tasks, and example codes for implementing timer functionalities. The lab tasks involve creating a stopwatch and calculating timer values for precise delays.

Uploaded by

mokishere
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Lab 08

The document is a lab report on Timer Programming for the EE222 Microprocessor Systems course, focusing on the ATmega328p microcontroller. It includes acknowledgements, learning outcomes, hardware resources, and detailed sections on AVR timers, programming tasks, and example codes for implementing timer functionalities. The lab tasks involve creating a stopwatch and calculating timer values for precise delays.

Uploaded by

mokishere
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 17

Embedded System

Lab 08
Timer Programming

Submitted By:
Asna Maqsood
426990
BESE13 B
Embedded System
Lab 08
Timer Programming

Submitted By:
Muhammad Ahsan
406267
BESE13 B
Embedded System
Lab 08
Timer Programming

Submitted By:
Muhammad Owais Khan
404262
BESE13 B
Embedded System
Lab 08
Timer Programming

Submitted By:
Umar Farooq
406481
BESE13 B
Lab 8: Timer Programming
EE222: Microprocessor Systems

Contents
1 Acknowledgements..........................................................................................................................2
2 Administrivia.....................................................................................................................................2
2.1 Learning Outcomes..........................................................................................................................2
2.2 Deliverable........................................................................................................................................2
2.3 Hardware Resources........................................................................................................................2
3 Introduction.......................................................................................................................................3
3.1 AVR Timers.......................................................................................................................................3
3.2 AVR Timer 0 programming.............................................................................................................3
3.2.1 Timer Counter Zero (TCNT0)......................................................................................................3
3.2.2 Timer Counter Control Register Zero (TCCR0)..........................................................................3
3.2.3 Output Compare Register Zero (OCR0)......................................................................................4
3.2.4 Timer 0 Interrupt Flag Register (TIFR0)....................................................................................4
3.3 AVR Timer 1 programming.............................................................................................................4
3.3.1 Timer Counter One (TCNT1).......................................................................................................4
3.3.2 Timer Counter Control Register One (TCCR1)...........................................................................4
3.3.3 Output Compare Register One (OCR1).......................................................................................5
3.3.4 Timer 1 Interrupt Flag Register (TIFR1)....................................................................................5
3.3.5 Timer 1 CTC Mode (Clear Timer on Compare)...........................................................................5
3.3.6 Timer 1 CTC Mode Example.........................................................................................................6
4 Lab Tasks............................................................................................................................................7
4.1 Task A................................................................................................................................................7
4.2 Task B................................................................................................................................................7
4.3 Task C................................................................................................................................................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. Use Timers/Counters features of ATmega328p.

2. Create calculated, precise delays through timers.

2.2 Deliverable
You are required to submit

• Appropriately Commented Code

• Explicit Calculations for Timer Values

• Issues in Developing the Solution and your Response in the beginning of next lab

2.3 Hardware Resources


• Arduino Uno board with ATmega328p microcontroller

• Seven Segment Display x2

• Resistance 47Ω x2

• Switches
3 Introduction
3.1 AVR Timers
Timers are special registers in microcontrollers/microprocessors whose value increment
with every clock tick. In AVR, there are three timers, Timer 0, Timer 1 and Timer 2.

3.2 AVR Timer 0 programming


Timer 0 in AVR is manipulated using registers TCNT0, TCCR0A, TCCR0B, TIFR0, OCR0A and
OCR0B.

3.2.1 Timer Counter Zero (TCNT0)


TCNT0 is an 8-bit register which can count from 0 to 255. We can also load starting value in
this register from where the counter will start its counting.

3.2.2 Timer Counter Control Register Zero (TCCR0)


This register is used to configure the timer/counter. This register has two variants TCCR0A
and TCCR0B.

TCCR0A COM0A1 COM0A0 COM0B1 COM0B0 WGM01 WGM00

TCCR0B FOC0A FOC0B WGM02 CS02 CS01 CS00

For now only CS02:CS00 bits are of importance. These bits are used to apply prescalar to input
clock frequency
CS02:CS00 Function
000 Timer Counter Stopped
001 clk (No prescalar)
010 clk / 8
011 clk / 64
100 clk / 256
101 clk / 1024
WGM02:WGM00 Mode
000 Normal Mode
010 CTC Mode
3.2.3 Output Compare Register Zero (OCR0)
We can load some 8-bit value in this register, such that when the value in counter matches
it, the Output Compare Flag Zero (OCF0) is raised.
OCR0A: The output compare register A contains an 8-bit value that is continuously
compared with the counter value (TCNT0). A match can be used to generate a waveform
output on the OC0A pin.
OCR0B: The output compare register B contains an 8-bit value that is continuously
compared with the counter value (TCNT0). A match can be used to generate a waveform
output on the OC0B pin.
3.2.4 Timer 0 Interrupt Flag Register (TIFR0)
-- -- -- -- -- OCF0B OCF0A TOV0

TOV0 Timer 0 overflow flag


OCF0B Timer 0 output compare B match flag
OCF0A Timer 0 output compare A match flag

To clear a flag when it is set, write “1” to it.

3.3 AVR Timer 1 programming


Timer 1 in AVR is 16-bit wide which means it can count more than Timer 0. The range of
Timer 1 is 0-65535. Timer 1 in AVR is manipulated using TCNT1 = [TCNT1H:TCNT1L], TCCR1A,
TCCR1B, TCCR1C, OCR1A = [OCR1AH:OCR1AL], OCR1B = [OCR1BH:OCR1BL] and TIFR1.

3.3.1 Timer Counter One (TCNT1)

TCNT1 is a 16-bit register divided into two 8-bit chunks TCNT1H and TCNT1L. To load a 16-
bit value into it we must separate it into two 8-bit chunks, load the lower 8-bits in TCNT1L
and higher 8-bits in TCNT1H separately.

3.3.2 Timer Counter Control Register One (TCCR1)

TCCR1 has three variants TCCR1A, TCCR1B and TCCR1C.

TCCR1A COM1A1 COM1A0 COM1B1 COM1B0 -- -- WGM11 WGM10


TCCR1B ICNC1 ICESI -- WGM13 WGM12 CS12 CS11 CS10
TCCR1C FOC1A FOC1B -- -- -- -- -- --
CS12:CS10 Function
000 Timer Counter Stopped
001 clk (No prescalar)
010 clk / 8
011 clk / 64
100 clk / 256
101 clk / 1024

WGM13:WGM10 Mode

0000 Normal Mode


0100 CTC Mode

The lower two bits of WGM control are in TCCR1A and the higher two bits are in TCCR1B.

3.3.3 Output Compare Register One (OCR1)

For Timer 1, there are two output compare registers OCR1A and OCR1B, 16-bit each, with
compare match flag OCF1A and OCF1B in TIFR1.

3.3.4 Timer 1 Interrupt Flag Register (TIFR1)


-- -- ICF1 -- -- OCF1B OCF1A TOV1

TOV1 Timer 1 overflow flag


OCF1B Timer 1 output compare B match
OCF1A flag Timer 1 output compare A
ICF1 match flag Timer 1 Interrupt Capture
Flag

To clear a flag when it is set, write “1” to it.

3.3.5 Timer 1 CTC Mode (Clear Timer on Compare)


Usually when we have to toggle a pin of microcontroller with a specific frequency, using
timer delays, some inaccuracy is induced by control instructions (house keeping). For
example the instructions which load the timer, change the value of output ports, clear flags,
etc in each iteration, add some unwanted time lag in our original delay and our toggling
frequency is disturbed.
To avoid this unwanted lag AVR provides a special timer operating mode “Clear Timer on
Compare”. In this mode when the value in TCNT register becomes equal to the value in OCR,
the hardware clear the timer, raises OCF and start timer again all by its own in the same
Machine Cycle. No software instructions are needed in the process and a higher timing
accuracy is achieved.

3.3.6 Timer 1 CTC Mode Example


Suppose we wish to read pin 0 of port C every 500ms and send the ASCII of letter ‘L’ on port
D if its value is 0 else send ASCII of letter ‘H’ with high time precision.
If the clock frequency is 16MHz and prescalar we wish to use is clk/256 then,

Time for one tick = 256/16M = 16µs

Ticks for 500ms = 500m/16µ = 31250 = 0x7A12


#include <avr/io.h>
int main( )
{
DDRC = 0x00 ; // Set port C as
input DDRD = 0xFF; // Set port D
as output TCNT1 = 0;
//Initialize timer 1
OCR1A = 31250;// Set output compare register
TCCR1A = 0x00 ; // WGM13:WGM10 = 0100 , CS12:CS10
= 100 TCCR1B = 0x0C;
TCCR1C = 0x00;
unsigned char data ;
while (1)

{
if ( (TIFR1 & 0x02) != 0 ) // Check OCF1A flag bit
{
TIFR1 |= 0x02 ; // Clear
flag data = PINC; // Read
port C if ( ( data & 0x01)
== 0) PORTD = 'L' ;
else
PORTD= 'H' ;
}
}
}

In the example above, the time consumed by if-else statement and other instructions inside
while(1) loop will not affect the timer count because the timer has been restarted by
hardware after compare match and is running in parallel with these instructions.

Why have we used or-equals in line 16 and not simple equal? Find the answer.
4 Lab Tasks
4.1 Task A
Implement the code in example 2.3.6, just to get familiar with timer programming and paste
proper screenshots of output.
#include <avr/io.h> int
main( )
{
DDRC = 0x00 ; // Set port C as input
DDRD = 0xFF; // Set port D as output
TCNT1 = 0; //Initialize timer 1
OCR1A = 31250;// Set output compare register
TCCR1A = 0x00 ; // WGM13:WGM10 = 0100 , CS12:CS10 = 100
TCCR1B = 0x0C;
TCCR1C = 0x00;
unsigned char data ; while
(1)

{
if ( (TIFR1 & 0x02) != 0 ) // Check OCF1A flag bit
{
TIFR1 |= 0x02 ; // Clear flag
data = PINC; // Read port C
if ( ( data & 0x01) == 0)
PORTD = 0b00111000 ;
else
PORTD= 0b01110110 ;
}
}
}

Output:
4.2 Task B
Calculate and determine the value of compare match and prescalar for timer 1 such that it
produces a precise 1 second delay for 16MHz clock. Include your calculations in the report.
Code:

#include <avr/io.h>

int main() {
// Set Port D as output
DDRD = 0xFF;

// Initialize Timer 1
TCNT1 = 0; // Start count from 0
OCR1A = 62499; // Set compare match value for 1-second delay
TCCR1A = 0x00; // WGM13:WGM10 = 0100 (CTC mode)
TCCR1B = 0x0C; // WGM12 = 1, CS12:CS10 = 100 (prescalar = 256)

while (1) {
if (TIFR1 & 0x02) { // Check OCF1A flag
TIFR1 |= 0x02; // Clear flag by writing '1'
PORTD ^= 0xFF; // Toggle PORTD
}
}
return 0;
}

Calculations:
Given:
Clock Frequency (F_CPU) = 16 MHz = 16,000,000 Hz
Required Delay = 1 second
Prescaler = 256

Step 2: Calculate Required Number of Ticks


Number of Ticks = Required Delay/Timer Tick Period
Number of Ticks= Timer Tick Period/Required Delay

Number of Ticks = 1/0.000016


Number of Ticks= 0.000016/1
Number of Ticks = 62500 ticks

Step 3: Compare Match Value (OCR1A)


Since the timer starts counting from 0, the compare match value is:
OCR1A=Number of Ticks−1
OCR1A=62500-1
OCR1A=62499

Summary:
Timer Tick Period = 16 μs (16 microseconds)
Required Ticks = 62,500
OCR1A = 62,499

This configuration ensures that Timer 1 in CTC (Clear Timer on Compare Match) mode provides an
accurate delay of 1 second.

4.3 Task C
In this task you are required to create a “Digital Stop Watch” that records the time in
seconds precisely (use CTC mode).
1. Connect two 7-segment-Displays with your ATmega328p.
2. Connect two switches (say Sw1 and Sw2) with your ATmega328p.
3. If Sw1 is high, the Stop Watch must get reset to zero, no matter what is the state of Sw2.
4. If Sw2 is high and Sw1 is low, the Stop Watch must display the seconds passed.
5. If Sw2 is low and Sw1 is also low, the Stop Watch must pause its time and if Sw2 is
raised again, it should resume from where it was paused.
Hint: Using timer-1 is same as using timer-0. The difference is in size of the TCNTx. The example
provided in Section 2.3.6 serves as the code template for this task. You basically need to
enhance it with your functionality.
Code:

#define F_CPU 16000000UL


#include <avr/io.h>
#include <util/delay.h>

const uint8_t SEGMENT_CODES[] = {


0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B
};

void configure_ports(void) {
DDRB = 0xFF;
DDRD = 0xFF;
PORTB = 0x00;
PORTD = 0x00;
DDRC = 0x00;
}

void update_digit(uint8_t value, uint8_t port_flag) {


if (value > 9) return;

uint8_t code = SEGMENT_CODES[value];


if (port_flag == 0) {
PORTD = (PORTD & 0b10000000) | (code & 0x7F);
} else {
if (value == 4 || value == 1) {
PORTD = 0x00;
} else {
PORTD = 0x80;
}
PORTB = code;
}
}

void show_value(uint8_t num) {


if (num > 59) return;
uint8_t tens_place = num / 10;
uint8_t ones_place = num % 10;
update_digit(tens_place, 1);
update_digit(ones_place, 0);
}

int main(void) {
uint8_t time_val = 0;
configure_ports();
TCNT1 = 0;
OCR1A = 62500;
TCCR1A = 0x00;
TCCR1B = 0x0C;
TCCR1C = 0x00;

while (1) {
if ((TIFR1 & 0x02) != 0) {
TIFR1 |= 0x02;
if (PINC & 0x01) {
time_val = 0;
} else if (PINC & 0x02) {
time_val++;
if (time_val > 59) {
time_val = 0;
}
}
show_value(time_val);
}
}

return 0;
}

Output:

You might also like