0% found this document useful (0 votes)
114 views21 pages

Timer Programming in Embedded Systems

Lab 8 of the EE222 Embedded Systems course focuses on Timer Programming using the ATmega328p microcontroller. The lab covers the functionality and programming of AVR Timers, specifically Timer 0 and Timer 1, including their registers and modes, with an emphasis on achieving precise timing through the Clear Timer on Compare (CTC) mode. Students are required to complete tasks involving timer programming, including creating a digital stopwatch and calculating timer values for specific delays.

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 DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
114 views21 pages

Timer Programming in Embedded Systems

Lab 8 of the EE222 Embedded Systems course focuses on Timer Programming using the ATmega328p microcontroller. The lab covers the functionality and programming of AVR Timers, specifically Timer 0 and Timer 1, including their registers and modes, with an emphasis on achieving precise timing through the Clear Timer on Compare (CTC) mode. Students are required to complete tasks involving timer programming, including creating a digital stopwatch and calculating timer values for specific delays.

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 DOCX, PDF, TXT or read online on Scribd

EE222: Embedded Systems

Lab 8: Timer Programming

Class: BESE-13-B

Lab instructor: Syed Zain-ul-hasan

MEMBER 1
AHMED BILAL
417936 | BESE-13-B

1
EE222: Embedded Systems

Lab 8: Timer Programming

Class: BESE-13-B

Lab instructor: Syed Zain-ul-hasan

MEMBER 2
ALI AMAR
426014 | BESE-13-B

2
EE222: Embedded Systems

Lab 8: Timer Programming

Class: BESE-13-B

Lab instructor: Syed Zain-ul-hasan

MEMBER 3
MUHAMMAD ZAID
416952 | BESE-13-B

3
EE222: Embedded Systems

Lab 8: Timer Programming

Class: BESE-13-B

Lab instructor: Syed Zain-ul-hasan

MEMBER 4
MUHAMMAD ZOHAIB
413441 | BESE-13-B

4
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

5
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

6
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

7
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 -- -- -- -- -- --

8
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 outputs 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 (housekeeping). 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
9
Compare”. In this mode when the value in TCNT register becomes equal to the value in OCR,

1
0
the hardware clears 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.

1
1
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.

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.

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.

1
2
Solution

Introduction:
This lab focuses on Timer Programming in the ATmega328p microcontroller. The lab introduces
us to AVR timers, specifically Timer 0 and Timer 1, and their various programming modes, with
special emphasis on the Clear Timer on Compare (CTC) mode for precise timing operations.
Objectives
 Learn to use Timers/Counters features of ATmega328p
 Create calculated, precise delays through timers
 Understand and implement CTC mode for accurate timing operations
Hardware used:
Arduino Uno board with ATmega328p microcontroller, Two Seven Segment Displays, Resistors
Software used:
Atmel Studio 7, AVRDUDES, Timer programming registers (Timer 0, Timer 1)

Task 1

#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 ;
}
}}

1
3
Hardware Implmentation:

1
4
Task 2
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
 Prescalar = 256

Calculate Timer Tick Period:


Timer Tick Period = Prescalar / F_CPU
Timer Tick Period = 256 / 16,000,000
Timer Tick Period = 0.000016 seconds = 16 microseconds

1
5
Calculate Required Number of Ticks for 1 second:
Number of Ticks = Required Delay / Timer Tick Period
Number of Ticks = 1 / 0.000016
Number of Ticks = 62,500

Compare Match Value:


OCR1A = Number of Ticks - 1
OCR1A = 62,500 - 1
OCR1A = 62,499
The reason we subtract 1 is because the timer counts from 0, so to get 62,500 ticks, we
need to count from 0 to 62,499.

With these settings:


 Each timer tick takes 16 microseconds (due to prescalar of 256)
 The timer will count up to 62,499
 Total time = 62,500 ticks × 16 microseconds = 1 second exactly

This gives us a precise 1-second delay using Timer 1 in CTC mode.

Task 3
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

// Seven segment display patterns for digits 0-9


const uint8_t SEGMENT_PATTERNS[] = {
0x7E, // 0
0x30, // 1
0x6D, // 2
0x79, // 3

1
6
0x33, // 4
0x5B, // 5
0x5F, // 6
0x70, // 7
0x7F, // 8
0x7B, // 9
};

void init_ports(void)
{
// Set PORTB (pins 8-13) as output for tens digit
DDRB = 0xFF;
// Set PORTD (pins 0-7) as output for ones digit
DDRD = 0xFF;
// Initialize both ports to 0
PORTB = 0x00;
PORTD = 0x00;
DDRC = 0x00;
}

void display_digit(uint8_t digit, uint8_t port_select)


{
if (digit > 9)
return; // Validate input

// Get the segment pattern for the digit


uint8_t pattern = SEGMENT_PATTERNS[digit];

// Display on selected port


if (port_select == 0)
{
PORTD = (PORTD & 0b10000000) | (pattern & 0x7F);
}
else
{
if (digit == 4 || digit == 1)
{
PORTD = 0x00;
}
else
{
PORTD = 0x80;

1
7
}
PORTB = pattern; // Tens digit on PORTB
}
}

void display_number(uint8_t number)


{
if (number > 59)
return; // Validate input

uint8_t tens = number / 10;


uint8_t ones = number % 10;

// Display tens digit on PORTB


display_digit(tens, 1);
// Display ones digit on PORTD
display_digit(ones, 0);
}

int main(void)
{
uint8_t seconds = 0;

// Initialize ports
init_ports();
TCNT1 = 0; //Initialize timer 1
OCR1A = 62500;// Set output compare register
TCCR1A = 0x00 ; // WGM13:WGM10 = 0100 , CS12:CS10 = 100
TCCR1B = 0x0C;
TCCR1C = 0x00;

while (1)
{
// Display current seconds

if ( (TIFR1 & 0x02) != 0 ) // Check OCF1A flag bit


{
TIFR1 |= 0x02 ; // Clear flag
// Increment seconds and reset if necessary

if (PINC & 0x01) {


seconds = 0;

1
8
} else if (PINC & 0x02) {
seconds++;
if (seconds > 59)
{
seconds = 0;
}
}

display_number(seconds);
}

return 0;
}

Configuration:
 Defined display patterns for digits 0-9 using segment patterns
 Initialized ports: PORTB and PORTD for display output, PORTC
for switch inputs
 Switch 1 (PINC & 0x01): Resets the counter to zero
 Switch 2 (PINC & 0x02): Controls start/pause functionality
 Configured Timer 1 in CTC mode with appropriate compare value
(62500) for 1-second timing
 display_digit(): Manages individual digit display
 display_number(): Handles two-digit number display
 Used separate ports for tens and ones digits

Hardware:

1
9
2
0
2
1

Common questions

Powered by AI

In embedded systems development, appropriately commented code and explicit calculations enhance both maintainability and clarity, facilitating future modifications and debugging. Comments provide context and understanding, making the logic behind code implementation transparent to other developers or even the original programmer revisiting the code after some time. Explicit calculations ensure that any derived values, such as those used for timer presets or interrupts, are clearly documented, which is crucial for verifying accuracy and adjusting as system parameters change, such as clock frequencies or timing requirements. Documentation of assumptions and methodological steps builds a foundation for reliable and reproducible development .

Implementing a digital stopwatch using microcontroller timers requires consideration of both hardware and software elements to ensure correct operation. On the hardware side, the setup of input switches and output displays directly affects how controls and readouts function. Proper interfacing and configuration need special attention, such as properly managing debouncing of switches. On the software side, selecting and programming the appropriate timer configuration, such as using Timer 1 in CTC mode, enables accurate time tracking. Synchronization between hardware inputs, timer interrupts, and display output ensures that the stopwatch operates correctly and user interactions are properly handled .

Software-induced inaccuracies in timing applications can be minimized by using hardware features such as the CTC mode, which reduces the need for software intervention and subsequently minimizes control instruction delays that ordinarily add unwanted latency. Utilizing interrupts effectively to handle timing rather than polling constantly allows the CPU to perform other tasks while waiting for an interrupt signal, improving efficiency and precision. Additionally, carefully optimizing the instruction set used in timing-critical loops and ensuring a minimal code path in interrupt service routines can further reduce the discrepancies caused by overhead in software execution .

Using semi-automated features like CTC mode in timer programming offers considerable advantages over manual timing adjustments. CTC mode automates the reset and restart of timers upon reaching a compare threshold, ensuring precise timing without CPU interference. This automation reduces software overhead, minimizing CPU load and freeing up resources for other tasks, which is especially critical in time-sensitive applications. Manual adjustments often lead to inconsistencies due to human error or variations in software execution time. By contrast, CTC provides consistent and precise results, crucial for high-precision applications such as PWM generation or time-critical control systems .

The Timer Interrupt Flag Register (TIFR) plays a crucial role in managing timer interrupts by indicating when certain events related to the timer have occurred. The register contains various flags, such as the Timer Overflow Flag (TOV) and Output Compare Match Flag (OCF), which are set whenever an overflow or compare match event occurs. The corresponding interrupt service routine can be executed following these events. To acknowledge the interrupt and allow for subsequent interrupts, these flags must be manually cleared by writing a logic 1 to them. This mechanism ensures that the processor is informed about timer-related events and can respond appropriately, which is essential for maintaining timing accuracy and handling interrupts efficiently .

To compute the required number of timer ticks for a specific delay using Timer 1, the delay period is divided by the period of a single timer tick. The single timer tick period is determined by dividing the prescaled clock frequency by the CPU clock frequency. For instance, with a 16 MHz CPU clock and a prescaler of 256, the timer tick period is 256/16,000,000 = 16 microseconds. Therefore, to generate a 1-second delay, 1/0.000016 = 62,500 timer ticks are needed. The Output Compare Register (OCR) should be set to one less than this value (OCR = 62,499) to account for counting from zero .

The CTC mode is beneficial for achieving precise timing because it allows the timer to automatically reset and restart on a compare match without requiring intervention from the CPU. When the Timer/Counter reaches the Output Compare Register value, it is cleared and starts counting again immediately in the same machine cycle. This reduces latency in handling reset operations and minimizes delays induced by control instructions, thus increasing the accuracy and reliability of time-based functions in microcontroller applications .

In a stopwatch implemented with the ATmega328p microcontroller, switch inputs connected to specific pins handle start, pause, reset, and display functions. Two switches are typically used: one (Sw1) to reset the time to zero and the other (Sw2) to control the stop/start functionality. When Sw1 is set high, it forces the stopwatch to reset regardless of the state of Sw2. If Sw2 is high and Sw1 is low, the stopwatch starts or continues to count seconds. If both Sw1 and Sw2 are low, the stopwatch pauses. These functions can be implemented by continuously checking the states of the switches in a loop and updating the timer and display accordingly, using outputs from Timer 1 in CTC mode for precise second intervals .

Prescalers are used in timers to adjust the frequency of the clock signal driving the timer, thereby allowing the timer to count events at a reduced rate. This is particularly useful for obtaining large delays or matching specific timing requirements without the need for very large counter values. In the TCCR0 register, the CS02:CS00 bits control the prescaler setting for Timer 0. These bits can be set to various values (000 to 101), affecting the division of the input clock frequency by 1, 8, 64, 256, or 1024, thereby modifying the timing interval at which Timer 0 increments .

Timer 0 and Timer 1 differ primarily in bit-width and their counting capabilities. Timer 0 is an 8-bit timer, meaning it can count from 0 to 255 before overflowing, which limits its ability to handle large timing intervals. Conversely, Timer 1 is a 16-bit timer, capable of counting from 0 to 65535, allowing for much longer timing intervals and more precise control over time-based operations in an embedded system .

You might also like