0% found this document useful (0 votes)
4 views69 pages

Microprocessor Mid-Term Notes (Complete)

The document provides an overview of timers in Arduino (ATmega328), detailing the differences between 8-bit and 16-bit timers, their configurations, and the registers involved. It explains timer overflow behavior, modes of operation, and how to calculate timer counts for specific delays, including the use of pre-scalers for longer delays. Additionally, it outlines the maximum possible delays for Timer0 and Timer1 at a system frequency of 16 MHz.

Uploaded by

hbangladesh909
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)
4 views69 pages

Microprocessor Mid-Term Notes (Complete)

The document provides an overview of timers in Arduino (ATmega328), detailing the differences between 8-bit and 16-bit timers, their configurations, and the registers involved. It explains timer overflow behavior, modes of operation, and how to calculate timer counts for specific delays, including the use of pre-scalers for longer delays. Additionally, it outlines the maximum possible delays for Timer0 and Timer1 at a system frequency of 16 MHz.

Uploaded by

hbangladesh909
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

Mohsin Iban Hossain

AIUB, Microprocessor Notes


Table of Contents
Sl. No Topic Pages
1 Introduction to Timers 3-21
2 Arduino Interrupts 22-33
3 System Clock Options 34-41
4 Assembly Language 42-52
5 Switch Debouncing 53-69
Timer
≫A timer/counter is like a clock and can be used to measure time events.

Arduino Timers Overview (ATmega328)


 Arduino (ATmega328) has 3 timers: Timer0, Timer1, and Timer2.
 Timers are programmable using special registers.

8-bit vs 16-bit Timers in Arduino (ATmega328)


 Timer0 and Timer2 are 8-bit; Timer1 is 16-bit.
 8-bit timer: counts 0–255 (256 steps).
 16-bit timer: counts 0–65535 (65,536 steps).
 Main difference: timer resolution (counting range).

Timer Overflow and Counter Behavior in Arduino

 Timers are also called counters due to their counting ability.


 When max value is reached, they overflow and reset to zero.
 Example: Timer0 (8-bit) counts from 0 to 255, then resets and continues.
Registers for Timer0 Configura on in Arduino
 TCNT0 (Timer/Counter Register 0): stores the current timer count.
 TCCR0A & TCCR0B (Timer/Counter Control Registers A and B): define the mode
of operation and pre-scaler settings.
 TIFR0 (Timer/Counter Interrupt Flag Register 0): indicates if an overflow or
compare match has occurred.
 OCR0A & OCR0B (Output Compare Registers A and B): store custom values to
trigger actions when the timer count matches (used in CTC or PWM modes, not in
normal mode).

Configuring Timer0 Mode & Pre-scaler in Arduino


 TCCR0A (Timer/Counter Control Register A):
o Bits WGM01 and WGM00 (along with WGM02 from TCCR0B) decide the
timer mode (e.g., Normal, CTC, PWM).

 TCCR0B (Timer/Counter Control Register B):


o Bits CS02, CS01, CS00 select the clock source and pre-scaler value for Timer0.
Pre-scaler Configura on in Arduino Timers

Differences Between Timer0 and Timer1


 Timer1 uses a 16-bit Timer/Counter Register (TCNT1), divided into TCNT1H (high
byte) and TCNT1L (low byte).
 Timer1 has 16-bit output compare registers, made up of two 8-bit registers.
 Timer1 features an additional Input Capture Register.
 Timer1 supports multiple extra operating modes compared to Timer0.

Key Timer Terms


 BOTTOM: The counter reaches 0x00.
 MAX: The counter reaches its maximum value, 0xFF (255) for Timer0, and 0xFFFF
(65535) for Timer1.
 TOP: The counter reaches the highest value in the count sequence, either the fixed MAX
value or the value stored in the OCRnA or OCRnB Register.
Timer Modes: Normal Mode
 The counter increments (up counting) without resetting.
 Overflows occur when the counter exceeds its MAX value, restarting from 0.
 The Timer/Counter Overflow Flag (TOV0) is set when the counter overflows and
TCNT0 becomes zero.

Timer Delay Calculation Formula


 Timer requires a clock pulse for each transition to the next number.
𝟏 𝟏
 For 𝑭𝑪𝑷𝑼 , 𝒇 = 𝟏𝟔MHz, the system clock period is 𝑻 = = = 𝟔𝟐. 𝟓 𝒏𝒔 That means If the mer clock
𝒇 𝟏𝟔𝑴 matches the system clock, each
transi on (from 0 to 1, 1 to 2, etc.)
takes 62.5 ns.

 To calculate the necessary mer counts for a specific delay, the formula can be derived as:

𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝

Formula for Timer Count Based on Delay


 To count from 0 to 2, 3 me periods are needed. The formula for mer count is:

𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = (𝐍𝐮𝐦𝐛𝐞𝐫 𝐨𝐟 𝐭𝐢𝐦𝐞 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 𝐧𝐞𝐞𝐝𝐞𝐝 𝐭𝐨 𝐫𝐞𝐚𝐜𝐡 𝐭𝐡𝐞 𝐜𝐨𝐮𝐧𝐭) − 𝟏

 For a delay of 187.5 ns, 3 me periods are needed, each las ng 62.5 ns:
62.5ns × 3 = 187.5ns

𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐝𝐞𝐥𝐚𝐲
𝐍𝐮𝐦𝐛𝐞𝐫 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 𝐧𝐞𝐞𝐝𝐞𝐝 =
𝑪𝒍𝒐𝒄𝒌 𝑷𝒆𝒓𝒊𝒐𝒅
 Problem1: Suppose you need a delay of 1 millisecond (ms) in a microcontroller mer
applica on. Given that the system clock frequency (F_CPU) is 16 MHz, calculate the mer
count needed to achieve this delay.

 is given,
Required delay = 1ms,
f = 16MHz 𝑇 = = = 62.5𝑛𝑠

 We Know,

𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐝𝐞𝐥𝐚𝐲
𝐍𝐮𝐦𝐛𝐞𝐫 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 𝐧𝐞𝐞𝐝𝐞𝐝 =
𝑪𝒍𝒐𝒄𝒌 𝑷𝒆𝒓𝒊𝒐𝒅(𝑻)

Number of periods needed = = 16000


.

𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = (𝐍𝐮𝐦𝐛𝐞𝐫 𝐨𝐟 𝐭𝐢𝐦𝐞 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 𝐧𝐞𝐞𝐝𝐞𝐝 𝐭𝐨 𝐫𝐞𝐚𝐜𝐡 𝐭𝐡𝐞 𝐜𝐨𝐮𝐧𝐭) − 𝟏


= 16000 − 1 = 15999

So, the mer must count 15,999 cks to achieve a 1 ms delay.

Limitations of Timer Delays at System Frequency


 Maximum delay for Timer0 (8-bit) at 16 MHz:
 We Know,
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞𝒎𝒂𝒙 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬𝒎𝒂𝒙 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝐓)

𝟏 1
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞𝒎𝒂𝒙 = 𝟐𝒃𝒊𝒕𝒔 × =2 × = 256 × 62.5𝑛𝑠 = 𝟏𝟔𝝁𝒔
𝒇 16𝑀𝐻𝑧

 Maximum delay for Timer1 (16-bit) at 16 MHz:


 We Know,
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞𝒎𝒂𝒙 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬𝒎𝒂𝒙 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝐓)

𝟏 1
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞𝒎𝒂𝒙 = 𝟐𝒃𝒊𝒕𝒔 × =2 × = 65536 × 62.5𝑛𝑠 = 𝟒. 𝟎𝟗𝟔𝒎𝒔
𝒇 16𝑀𝐻𝑧

So, it is not possible to get longer delays. For longer delays, coun ng directly with the system clock doesn’t work
well because the mer reaches its limit too fast. To fix this, we use pre-scalers (which slow down the clock)
Using Pre-scaler to Calculate Timer Count
 To ensure safe operation and longer delays, a pre-scaler is used to slow down the timer
clock.

 For example, using the maximum pre-scaler of 1024:


 New Timer Clock Frequency:
𝑓 16MHz
f = = = 15,625 Hz
𝑝𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟(𝑝𝑠) 1024

 New Timer Clock Period:


T = 𝑇 × 𝑝𝑟𝑒𝑠𝑐𝑎𝑙𝑒𝑟 = 62.5ns × 1024 = 64𝝁𝒔

o For a delay of 1 ms, the Timer Count becomes:


𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = (𝐍𝐮𝐦𝐛𝐞𝐫 𝐨𝐟 𝐭𝐢𝐦𝐞 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 𝐧𝐞𝐞𝐝𝐞𝐝 𝐭𝐨 𝐫𝐞𝐚𝐜𝐡 𝐭𝐡𝐞 𝐜𝐨𝐮𝐧𝐭) − 𝟏
𝑅𝑒𝑞𝑢𝑖𝑟𝑒𝑑 𝑑𝑒𝑙𝑎𝑦
= −1
𝐶𝑙𝑜𝑐𝑘 𝑃𝑒𝑟𝑖𝑜𝑑(𝑇)
1𝑚𝑠
= − 1 = 15.625 − 1 = 14.625
64𝝁𝒔

So, the counter needs to count approximately 14.6 cks (𝒓𝒐𝒖𝒏𝒅𝒆𝒅 𝒃𝒂𝒔𝒆𝒅 𝒐𝒏 𝒓𝒆𝒔𝒐𝒍𝒖𝒕𝒊𝒐𝒏).

 The updated formula using pre-scaler is:


𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

or simply:
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲 × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐅𝐫𝐞𝐪𝐮𝐞𝐧𝐜𝐲(𝒇)
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔)
Maximum Possible Delay for Timers
 Maximum delay for Timer0 (8-bit) at 16 MHz (using pre-scaler 1024max):
 We Know,
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞𝒎𝒂𝒙 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬𝒎𝒂𝒙 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝐓)

𝟏 1024
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞𝒎𝒂𝒙 = 𝟐𝒃𝒊𝒕𝒔 × =2 × == 256 × 64𝜇𝑠 = 𝟏𝟔. 𝟑𝟖𝟒𝒎𝒔
𝒇 16𝑀𝐻𝑧
𝒑𝒔

 Maximum delay for Timer1 (16-bit) at 16 MHz(using pre-scaler 1024max):


 We Know,
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞𝒎𝒂𝒙 = 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭𝐬𝒎𝒂𝒙 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝐓)

𝟏 𝑝𝑠
𝐃𝐞𝐥𝐚𝐲 𝐓𝐢𝐦𝐞𝒎𝒂𝒙 = 𝟐𝒃𝒊𝒕𝒔 × =2 × = 65536 × 64𝜇𝑠 = 𝟒. 𝟏𝟗𝟒𝒔
𝒇 16𝑀𝐻𝑧
𝒑𝒔

Note: For delays longer than 4 seconds, use Timer1 in combina on with nested if statements or
overflow coun ng to extend the delay range further.

 Problem2: Make an LED blink every 2 milliseconds while using Arduino system frequency
(F_CPU) 16 MHz, using mer to generate the delay without any applica on of delay()
func on. Use a pre-scaler value of 1024

 is given,
Required delay = 2ms,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
ps = 1024
 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝟐𝒎𝒔
= − 𝟏 = 𝟑𝟎. 𝟐𝟓 ≈ 𝟑𝟏
𝟏𝟎𝟐𝟒 × 𝟔𝟐. 𝟓𝒏𝒔

Timer0 is suitable since 31 < 256


 Generate the delay without any applica on of delay() func on

#define PIN_USED 8

int milisec = 2;
int prescaler = 1024;
int clock_freq = 16000000 / prescaler;
float clock_period = 1.0 / (float)clock_freq;
int count = (milisec * 0.001 / clock_period) - 1;

void setup() {

pinMode(PIN_USED, OUTPUT);

TCCR0A = 0b00000000; WGM01 and WGM00 set to zero for normal mode
TCCR0B = 0b00000101; CS02, CS01, CS00 set to 1,0,1 for pre-scalar 1024
TCNT0 = 0; // Timer0
}

void loop() {
if (TCNT0 >= count) {

TCNT0 = 0; // Checking if delay time has passed


digitalWrite(PIN_USED, !digitalRead(PIN_USED)); // Toggle pin output
}
}

 Problem3: Make an LED blink every 2 Seconds while using Arduino system frequency
(F_CPU) 16 MHz, using mer to generate the delay without any applica on of delay()
func on. Use a pre-scaler value of 1024
 is given,
Required delay = 2s,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
ps = 1024
 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝟐𝒔
= − 𝟏 = 𝟑𝟎. 𝟐𝟓 ≈ 𝟑𝟏𝟐𝟓𝟎
𝟏𝟎𝟐𝟒 × 𝟔𝟐. 𝟓𝒏𝒔

Timer1 is suitable since 31250 < 65536


 Generate the delay without any applica on of delay() func on

#define PIN_USED 8

int milisec = 2000;


int prescaler = 1024;
int clock_freq = 16000000 / prescaler;
float clock_period = 1.0 / (float)clock_freq;
int count = (milisec * 0.001 / clock_period) - 1;

void setup() {

pinMode(PIN_USED, OUTPUT);

TCCR1A = 0b00000000; WGM01 and WGM00 set to zero for normal mode
TCCR1B = 0b00000101; CS02, CS01, CS00 set to 1,0,1 for pre-scalar 1024
TCNT1 = 0; // Timer1
}

void loop() {
if (TCNT1 >= count) {

TCNT1 = 0; // Checking if delay time has passed


digitalWrite(PIN_USED, !digitalRead(PIN_USED)); // Toggle pin output
}
}

 Problem4: You're working on an Arduino project running at 16 MHz. You want to create
a delay of 1 millisecond using Timer0 with a prescaler of 1024, without using the delay()
func on.

 is given,
Required delay = 1ms,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
ps = 1024
 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝟏𝒎𝒔
= − 𝟏 = 𝟏𝟒. 𝟔𝟐𝟓 ≈ 𝟏𝟓
𝟏𝟎𝟐𝟒 × 𝟔𝟐. 𝟓𝒏𝒔
 Declaring the mer func on to count 1 ms of delay

// Declaring the timer function to count 1 ms of delay instead of using delay()

int delay_timer(int milliseconds) {


int count = 0;

while (1) {
if (TCNT0 >= 16) { // Checking if 1 millisecond has passed (for 16MHz/1024 setup)
TCNT0 = 0;
count++;
}

if (count >= milliseconds) { // Checking if required milliseconds have passed


count = 0;
break; // Exit the loop
}
}

return 0;
}

 Problem5: If you want to make an LED of blue color blink every 2 seconds while using
an Arduino system frequency of 16 MHz using a mer to generate delay without any
applica on of the built-in delay() func on, select a suitable mer of the Arduino Uno for
your applica on. Use a pre-scaler value of 256. Determine the necessary register set-up
required for the program.

 is given,
Required delay = 2s,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
𝑝𝑠 = 256

 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝟐𝒔
= − 𝟏 = 𝟏𝟐𝟒𝟗𝟗𝟗
𝟐𝟓𝟔 × 𝟔𝟐. 𝟓𝒏𝒔
❌ Can we use Timer0 or Timer1?

 Timer0 → 8-bit → max 256


 Timer1 → 16-bit → max 65536
Both are too small for 124999 counts

✅ Solution:
 Use a subroutine (timer function) that gives 1 ms delay and call it 2000 times to make
2 seconds.
 Use Timer0 in Normal Mode (simple up-counting, overflow detection).

Register Setup (if using Timer0):


 Problem6: Determine the outputs of the program and correct the program if there are
any errors. Assume that a green color LED is connected to pin 5 and the Arduino
frequency is 16 MHz. Compute the number of counts required for a 3 ms delay in each
cycle for the given delay. Compute the number of mes the while_true loop will run to
execute the delays of LED ON/OFF mes. Use a pre-scaler value of 1024.

#define YELLOW_PIN 10
int green_on = 5000; // delay is given in ms void loop() {
int green_off = 4000; // delay is given in ms pinMode(GREEN_PIN, INPUT);
TCCR0A = 0b00000000;
int delay_timer (int milliseconds){ TCCR0B = 0b00000100;
int count = 0; TCNT1 = 0x0000;
while(1) { }
if(TCNT1 >= _____) {
TCNT1=0;
count++;
void loop() {
if (count == milliseconds) {
digitalWrite(BLUE_PIN, HIGH);
count=0;
delay(green_on);
break; }
}
digitalRead(GREEN_PIN, LOW);
}
delay_timer(blue_off);
return 0;
}
}

 Pre-scaler values and corresponding register contents

 First, let's calculate the mer count:


 is given,
Required delay = 3ms,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
𝑝𝑠 = 1024

 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝟑𝒎𝒔
= − 𝟏 = 𝟒𝟓. 𝟖𝟕𝟓 ≈ 𝟒𝟔
𝟏𝟎𝟐𝟒 × 𝟔𝟐. 𝟓𝒏𝒔
So, The output of the program is:
Make a green LED on pin 5 blink in the following pattern:
 ON for 5 seconds
 OFF for 4 seconds
 Repeat forever (until power off)

 The number of counts required for a 5 s (5000 ms) delay in each cycle for the LED ON me = = 1667.
 The number of counts required for a 4 s (4000 ms) delay in each cycle for the LED OFF me = = 1334.
So, we use Timer0 or Timer1?
 Timer0 → 8-bit → max 256
 Timer1 → 16-bit → max 65536
Timer1 is suitable since (1667|1334) < 65536

 Second, let's write the corrected codes.


#define YELLOW_PIN 10 GREEN_PIN 5
int green_on = 5000; // delay is given in ms void loop() {
int green_off = 4000; // delay is given in ms pinMode(GREEN_PIN, INPUT);
TCCR0A TCCR1A = 0b00000000;
int delay_timer (int milliseconds){ TCCR0B TCCR1B = 0b00000101;
int count = 0; TCNT1 = 0x0000;
while(1) { }
if(TCNT1 >= 46) {
TCNT1=0;
count++;
if (count == milliseconds) {
void loop() {
count=0;
digitalWrite(GREEN_PIN, HIGH);
break; }
delay_ timer(green_on);
}
}
digitalWrite(GREEN_PIN, LOW);
return 0;
delay_timer(green_off);
}
}
 Problem7: If you want to make an LED of red color blink every 4 seconds while using an
Arduino system frequency of 16 MHz using a mer to generate the delay without any
applica on of the delay() func on, which mer of the Arduino Uno is suitable for your
applica on? You may use a pre-scaler value of 256, 1024. Write the necessary register
set-up required for the program.

 is given,
Required delay = 4s,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
𝑝𝑠 = 1024

 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝟒𝒔
= − 𝟏 = 𝟔𝟐𝟒𝟗𝟗
𝟏𝟎𝟐𝟒 × 𝟔𝟐. 𝟓𝒏𝒔

Timer1 is suitable since 𝟔𝟐𝟒𝟗𝟗 < 𝟔𝟓𝟓𝟑𝟔

Register Setup (Timer1):

Name Value
TCCR1A 0b00000000
TCCR1B 0b00000101
void setup() {

pinMode(PIN_USED, OUTPUT);

TCCR1A = 0b00000000; WGM01 and WGM00 set to zero for normal mode
TCCR1B = 0b00000101; CS02, CS01, CS00 set to 1,0,1 for pre-scalar 1024
TCNT1 = 0; // Timer1
}
 Problem8: A simple IC test kit using the available ATMega328P MCU test kit will generate
2 pulse waves with a period of 400 ns and 400 ms to test the IC chips. The student decided
to generate these pulses using the mer modules in the ATMega328P. The MCU is running
at 16 MHz and there are 3 mer modules (Timer0, Timer1, and Timer2) available of which
Timer0 and Timer2 are 8-bit mers and Timer1 is a 16-bit mer. The available pre-scalers
are 1, 8, 64, 256, and 1024. Select appropriate mers to be used for this test kit. Compute
the necessary mer counts to generate the stated pulse wave periods using the selected
mers.

 is given,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
𝐴𝑣𝑎𝑖𝑙𝑎𝑏𝑙𝑒 𝑝𝑠 = 1, 8, 64, 256, 1024
 For 400 ns Period Pulse (very fast),
Required delay = 400 ns,
Let, 𝑝𝑠 = 1(𝑛𝑜 𝑝𝑟𝑒𝑠𝑐𝑎𝑙𝑖𝑛𝑔)

 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝟒𝟎𝟎𝒏𝒔
= − 𝟏 = 𝟓. 𝟒 ≈ 𝟔
𝟏 × 𝟔𝟐. 𝟓𝒏𝒔

Timer0 & Timer2 is suitable since 𝟔 < 𝟐𝟓𝟔


Let’s Select Timer0

 For 400 ms Period Pulse (much slower),


Required delay = 400 ms,
Let, 𝑝𝑠 = 256

 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝟒𝟎𝟎𝒎𝒔
= − 𝟏 = 𝟐𝟒𝟗𝟗𝟗
𝟐𝟓𝟔 × 𝟔𝟐. 𝟓𝒏𝒔

Timer1 is suitable since 𝟐𝟒𝟗𝟗𝟗 < 𝟔𝟓𝟑𝟔𝟔

Although 𝒑𝒔 = 1024 is acceptable, but less accurate.


 Problem9: Prepare the necessary setup func on for the pins and registers associated
with an 8-bit mer to a ain the mer count computed in Problem8. The mer is to be
running in normal mode. [Hint: TCCRxA and TCCRxB must be ini alized. The useful bits of
TCCRxA are bit 0 and bit 1 which represent WGMx0 and WGMx1 respec vely. Bits 0 to 3
are the useful bits from TCCRxB. Bit 3 represents WGMx2. Bits 0 to 2 represent the clock
select func ons CSx0, CSx1, and CSx2, respec vely. For the normal mode of opera on,
WGM =0. The bits not men oned here can be considered as 0.

Table 1 Clock select bits and corresponding prescaler values for Timers.
CSx2 CSx1 CSx0 Prescaler
0 0 1 1
0 1 0 8
0 1 1 64
1 0 0 256
1 0 1 1024

 Since Setup Func on for 8-bit Timer (Timer0 in Normal Mode)

void setup_timer0_normal_mode() {

pinMode(5, OUTPUT);

TCCR0A = 0b00000000; // WGM01=0, WGM00=0


TCCR0B = 0b00000001; // CS00=1 (prescaler = 1), WGM02=0

// Load timer count for 400ns (i.e., count = 6 → load TCNT0 = 256 - 6 = 250)
TCNT0 = 250;

}
 Problem10: Prepare the setup func on for the pins from which the two pulses of
Problem8 are available Using the following template. Hint: Timer should be run in normal
mode.

void setup() {
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
TCCR......= 0b................; // {COMnA1}{COMnA0}{COMnB1}{COMnB0}-1-{WGMn1}{WGMn0}
TCCR......= 0b................; // {FOCnA}{FOCnB}-1-{WGMn2}{CSn2}{CSn1}{CSn0}
TCCR......= 0b................; // {COMnA1}{COMnA0}{COMnB1}{COMnB0}-1-{WGMn1}{WGMn0}
TCCR......= 0b................; // {FOCnA}{FOCnB}-1-{WGMn2}{CSn2}{CSn1}{CSn0}
}

Table 1 Clock select bits and corresponding prescaler values for Timers.
CSx2 CSx1 CSx0 Prescaler
0 0 1 1
0 1 0 8
0 1 1 64
1 0 0 256
1 0 1 1024

 Since Setup Func on for 2 Pulses of Problem8 (Timer0, Timer1 in Normal Mode)

void setup() {
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);

TCCR0A= 0b00000000; // {COMnA1}{COMnA0}{COMnB1}{COMnB0}-1-{WGMn1}{WGMn0}


TCCR0B= 0b00000001; // {FOCnA}{FOCnB}-1-{WGMn2}{CSn2}{CSn1}{CSn0}
TCCR1A= 0b00000000; // {COMnA1}{COMnA0}{COMnB1}{COMnB0}-1-{WGMn1}{WGMn0}
TCCR1B= 0b00000100; // {FOCnA}{FOCnB}-1-{WGMn2}{CSn2}{CSn1}{CSn0}
}
Interrupts
 An interrupt is a request to the processor to stop what it’s doing.
 It is also called a trap.
 The processor pauses the current task.
 It saves its current state (so it can continue later).
 It runs a special code called Interrupt Service Routine (ISR) or Interrupt Handler.
 After the ISR runs, the processor goes back to what it was doing before.
 Interrupts are useful when using switch debouncing (to handle noisy signals from
buttons).

Atmega328p Interrupt Processing


 On interrupt, microcontroller finishes current instruction.
 Saves next instruction address on the stack.
 Disables further interrupts by clearing Global Interrupt Enable (I-bit) in SREG.
 Interrupt flag is cleared only for Type 1 interrupts.
 Status Register (SREG) is not auto-saved or restored — must be done by software.

Atmega328p Interrupt Processing-Type 1


 User can set I-bit to enable nested interrupts (interrupt inside interrupt).
 RETI sets the I-bit to enable interrupts again.
 Type 1 interrupts happen when an Interrupt Flag is set.
 Program Counter jumps to the ISR address (Interrupt Vector).
 Hardware clears the Interrupt Flag after handling.
 If interrupt is disabled, the flag is remembered until it is enabled or cleared.
 Write 1 to flag bit to clear it manually.
 If I-bit is cleared, multiple interrupt flags can still be set and will be served later by
priority when I-bit is re-enabled.
Atmega328p Interrupt Processing-Type 2
 Type 2 interrupts are active as long as the condition exists.
 They may not have Interrupt Flags.
 If the condition ends before enabling, the interrupt won’t trigger.

TIMSK0 – Timer/Counter0 Interrupt Mask Register

 Bits 7–3: Reserved – Always read as 0.


 Bit 2 – OCIE0B: Timer/Counter 0 Output Compare B Match Flag
o Enables Compare Match B interrupt.
o Needs both OCIE0B = 1 and I-bit = 1.
o Triggered when OCF0B is set in TIFR0.

 Bit 1 – OCIE0A: Timer/Counter 0 Output Compare A Match Flag


o Enables Compare Match A interrupt.
o Needs OCIE0A = 1 and I-bit = 1.
o Triggered when OCF0A is set in TIFR0.

 Bit 0 – TOIE0: Timer/Counter0 Overflow Flag


o Enables Overflow interrupt.
o Needs TOIE0 = 1 and I-bit = 1.
o Triggered when TOV0 is set in TIFR0.

TIFR0 – Timer/Counter0 Interrupt Flag Register


 Bits 7–3: Reserved – Always read as 0.
 Bit 2 – OCF0B: Timer/Counter 0 Output Compare B Match Flag
 Set when Compare Match occurs with OCR0B.
 Cleared by:
o Hardware (after ISR runs), or
o Writing logic 1 to it.
 Interrupt runs when I-bit + OCIE0B + OCF0B are set.

 Bit 1 – OCF0A: Timer/Counter 0 Output Compare A Match Flag


 Set on Compare Match with OCR0A.
 Cleared same way as OCF0B.
 Interrupt runs when I-bit + OCIE0A + OCF0A are set.

 Bit 0 – TOV0: Timer/Counter0 Overflow Flag


 Set when Timer0 overflows.
 Cleared by:
o Hardware (after ISR), or
o Writing logic 1 to it.
 Interrupt runs when I-bit + TOIE0 + TOV0 are set.
 Depends on WGM02:0 (Waveform Generation Mode).

TIMSK1 – Timer/Counter1 Interrupt Mask Register

 Bits 7, 6: Reserved (always 0).


 Bit 5 (ICIE1): Enables Timer/Counter1 Input Capture Interrupt when set, if global
interrupts are enabled.
 Bits 4, 3: Reserved (always 0).
 Bit 2 (OCIE1B): Enables Timer/Counter1 Output Compare B Match Interrupt when set,
if global interrupts are enabled.
 Bit 1 (OCIE1A): Enables Timer/Counter1 Output Compare A Match Interrupt when set,
if global interrupts are enabled.
 Bit 0 (TOIE1): Enables Timer/Counter1 Overflow Interrupt when set, if global interrupts
are enabled.
TIFR1 – Timer/Counter1 Interrupt Flag Register

 Bits 7, 6: Reserved (always 0).


 Bit 5 (ICF1): Set when a capture event occurs on the ICP1 pin or when the counter
reaches the TOP value in certain modes. Cleared automatically when the Input Capture
Interrupt Vector is executed or manually by writing a 1.
 Bits 4, 3: Reserved (always 0).
 Bit 2 (OCF1B): Set when the counter matches OCR1B. Cleared automatically by the
Output Compare Match B Interrupt Vector or manually by writing a 1.
 Bit 1 (OCF1A): Set when the counter matches OCR1A. Cleared automatically by the
Output Compare Match A Interrupt Vector or manually by writing a 1.
 Bit 0 (TOV1): Set when the timer overflows in Normal and CTC modes. Cleared automatically
by the Timer/Counter1 Overflow Interrupt Vector or manually by writing a 1.

"500ms LED Blink using Timer1 Interrupts on AVR Microcontroller"

1. Reset Timer Registers:


o Set TCCR1A and TCCR1B to 0 to clear settings.
o Set TCCR1B = 00000100 for a prescaler of 256.
2. Enable Compare Match Interrupt:
3. Set the OCIE1A bit in TIMSK1 (Interrupt Mask Register) using TIMSK1 |=
00000010
4. Set OCR1A Register:
o Set OCR1A = 31250 to generate an interrupt every 500ms with the prescaler of
256.
5. Interrupt Service Routine (ISR):
o Define the ISR for the compare match event: ISR(TIMER1_COMPA_vect).
o Invert the LED state (e.g., using
digitalWrite(LED_PIN,!digitalRead(LED_PIN)); ).
6. Timer Reset:
o Ensure the timer resets on each interrupt to avoid overflow and keep the 500ms
timing consistent.
Code Structure:
void setup() {
pinMode(13, OUTPUT)
Cli();

TCCR1A = 0; // Clear control register A


TCCR1B = 0; //Resrt Entire TCCR1B

TCCR1B |= B00000100; // Set prescaler


OCR1A = 31250; // Set compare match value (500ms)
TIMSK1 |= B00000010; // Enable Timer1 Compare A interrupt

pinMode(LED_PIN, OUTPUT); // Set LED pin as output


}

ISR(TIMER1_COMPA_vect) {
digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Invert LED state
}

void loop() {
// Main loop is empty, blinking is handled by the ISR
}

Different Timer Interrupt Vectors:

 AVR microcontrollers have mul ple mers (Timer0, Timer1, Timer2), and each mer can
generate two types of interrupts: Compare Match A and Compare Match B.
o TIMER1_COMPA_vect: This vector is used for Timer1 Compare Match A interrupt.
o TIMER1_COMPB_vect: This vector is used for Timer1 Compare Match B interrupt.
o TIMER2_COMPA_vect: This vector is used for Timer2 Compare Match A interrupt.
o TIMER2_COMPB_vect: This vector is used for Timer2 Compare Match B interrupt.
o TIMER0_COMPA_vect: This vector is used for Timer0 Compare Match A interrupt.
o TIMER0_COMPB_vect: This vector is used for Timer0 Compare Match B interrupt.

We use these vectors to trigger different ac ons depending on which mer’s compare match
has occurred.
 Problem1: A space research facility is planning to shoot high-frequency pulses into space for
research. These pulses are to be shot at a 100 ns interval. The facility has an ATMega328P
MCU available and decided to use it to count the me. Every 100 ns a mer interrupt will be
triggered by the MCU to shoot the pulse. It has been decided that the Timer2 interrupt will
be used. If the MCU is running at 16 MHz, prepare a program that triggers the Timer2
interrupt pin every 100 ns. The available pre-scalers for Timer2 are 1, 8, 64, 256, and 1024.
[Hint: Bits 0 to 2 of the TCCR2B register must be set. These bits correspond to the pre- scaler
to be used. The pre-scaler selec on bits are shown in Table 1. Output Compare Register,
OCR2B holds the necessary Timer2 count to achieve the required delay. Bit 1 from TIMSK2 is
OCIE2B - this bit must be set to enable a comparison match with the OCR2B register. Any bits
not men oned here are to be considered as 0].

Table 1 Clock select bits and corresponding pre-scaler values for Timers.
CSx2 CSx1 CSx0 Pre-scaler
0 0 1 1
0 1 0 8
0 1 1 64
1 0 0 256
1 0 1 1024

 is given,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
𝐴𝑣𝑎𝑖𝑙𝑎𝑏𝑙𝑒 𝑝𝑠 = 1, 8, 64, 256, 1024
Required interrupt interval = 100 ns

 Step 1: Calculate Number of Clock Periods Needed:

 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐝𝐞𝐥𝐚𝐲
𝐍𝐮𝐦𝐛𝐞𝐫 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 𝐧𝐞𝐞𝐝𝐞𝐝 =
𝑪𝒍𝒐𝒄𝒌 𝑷𝒆𝒓𝒊𝒐𝒅 (𝑻)

100 ns [Since we can't have


Number of periods needed = = 1.6 = 1 𝑜𝑟 2 a frac on of a clock]
62.5 𝑛𝑠
cycle,
 Step 2: Determine Actual Achievable Delay:
 If , 𝐍𝐨 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 = 𝟐
 We Know,
𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 𝐍𝐨 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝 (𝐓)
𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 𝟐 × 𝟔𝟐. 𝟓𝐧𝐬 = 𝟏𝟐𝟓𝐧𝐬 (25% error)[This is the minimum possible
interrupt interval achievable
without prescaling]
 If , 𝐍𝐨 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 = 𝟏
 We Know,
𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 𝐍𝐨 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝 (𝐓)
𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 𝟏 × 𝟔𝟐. 𝟓𝐧𝐬 = 𝟔𝟐. 𝟓𝐧𝐬 (37.5% error)

 Step 3: Determine the optimal prescaler:


o We need to find the smallest prescaler that allows us to achieve at least 100 ns interval.
 We Know,

1. 𝐄𝐟𝐟𝐞𝐜𝐭𝐢𝐯𝐞 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝 = 𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
2. 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 (𝐓𝐂/𝐎𝐂𝐑𝟐𝐁) = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔)×𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

3. 𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 (𝐀𝐃) = (𝐓𝐂 + 𝟏) × 𝐄𝐟𝐟𝐞𝐜𝐭𝐢𝐯𝐞 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝

o For 𝑃𝑆 = 1:

𝟏𝟎𝟎𝒏𝒔
𝐓𝐂 = − 𝟏 = 𝒓𝒐𝒖𝒏𝒅(𝟎. 𝟔) = 𝟏
𝟏 × 𝟔𝟐. 𝟓𝒏𝒔

𝐀𝐃 = (𝟏 + 𝟏) × (𝟏 × 𝟔𝟐. 𝟓 𝒏𝒔) = 𝟏𝟐𝟓 𝒏𝒔

o For 𝑃𝑆 = 8:

𝟏𝟎𝟎𝒏𝒔
𝐓𝐂 = − 𝟏 = −𝟎. 𝟗𝟗𝟖 = 𝟎 [Since Nega ve value? → Not possible!]
𝟖 × 𝟔𝟐. 𝟓𝒏𝒔 Assume it 0
𝐀𝐃 = (𝟎 + 𝟏) × (𝟖 × 𝟔𝟐. 𝟓 𝒏𝒔) = 𝟓𝟎𝟎 𝒏𝒔

o For 𝑃𝑆 = 64:

𝟏𝟎𝟎𝒏𝒔
𝐓𝐂 = − 𝟏 = −𝟏 = 𝟎
𝟔𝟒 × 𝟔𝟐. 𝟓𝒏𝒔

𝐀𝐃 = (𝟎 + 𝟏) × (𝟔𝟒 × 𝟔𝟐. 𝟓 𝒏𝒔) = 𝟒𝟎𝟎𝟎 𝒏𝒔

 So, Higher prescalers only make the interval longer. Therefore, prescaler = 1 gives
us the closest possible interval (125 ns).
 Step 4: Observa on:
 No prescaler gives 𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 exactly 100 ns.
 Solu on: Use the smallest possible prescaler (1) and accept a slight error.

 Step 5: Best Possible Configuration:


Prescaler = 1 → 𝐄𝐟𝐟𝐞𝐜𝐭𝐢𝐯𝐞 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝 = 1 × 62.5 ns = 62.5ns
OCR2B = 1 → 𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 2 × 62.5 ns = 125 ns (25% error)
OCR2B = 0 → 𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 1 × 62.5 ns = 62.5ns (37.5% error)

 Timer2 Configuration (CTC Mode):

1. Set WGM21 (CTC Mode) → TCCR2A = (1 << WGM21) = 0b00000010;


2. Set Prescaler = 1 (CS20 bit) → TCCR2B = (1 << CS20) = 0b00000001;
3. Set OCR2B = 1 → OCR2B = 1
4. Enable Compare Match Interrupt → TIMSK2 = (1 << OCIE2B) = 0b00000100

C Program:
#include <avr/io.h>

void timer2_init() {

DDRD |= 0b01000000; // Set PD6 as output (binary: 01000000 = 0x40)

TCCR2A = 0b00000010; // Set Timer2 in CTC mode (WGM21 = 1, WGM20 = 0)


TCCR2B = 0b00000001; // Prescaler = 1 (CS22:0 = 001)

OCR2B = 1; // Compare value for OCR2B

TIMSK2 = 0b00000100; // Enable interrupt on compare match B

sei(); // Enable global interrupts


}

ISR(TIMER2_COMPB_vect) {

PORTD ^= 0b01000000; // Toggle PD6 (pulse generation)


}
 Problem2: Compute the output of the program if the signal at pin 5 becomes 1 from 0.
Assume that an LED is connected to pin 3 and a pull-up switch is connected to pin 5.

volatile boolean var_b;

void isr_f() {
var_b = false;
digitalWrite(3, HIGH);}

void setup() {
attachInterrupt(digitalPinToInterrupt(5), isr_f, CHANGE);
pinMode(3, OUTPUT);
digitalWrite(3, LOW);
}

void loop() {
if (var_b) {
// interrupt has occurred
}

 Output When Pin 5 Changes from 0 to 1

1. Pin 5 has a CHANGE interrupt — it triggers on any transi on (0→1 or 1→0).


2. When pin 5 goes from 0 to 1, the interrupt is triggered.
3. The ISR (isr_f) runs, which:
o Sets var_b = false
o Turns LED ON by digitalWrite(3, HIGH)
4. In setup(), the LED was ini ally OFF (digitalWrite(3, LOW)), so the interrupt causes
it to turn ON.
5. In the loop(), the condi on if (var_b) is false, because the ISR set var_b = false.
6. Therefore, the block inside if (var_b) does not execute.
 Problem3: A space research facility is planning to shoot high-frequency pulses into
space at a 200 ns interval using Timer1 of the ATMega328P MCU. Every 200 ns a mer
interrupt should be triggered to shoot the pulse. The system frequency is 16 MHz and
pre-scalers for Timer2 are 1, 8, 64, 256, and 1024. Compute the mer count and prepare
a flow chart to develop a program. Output Compare Register, OCR2B holds the
necessary Timer2 count to achieve the required delay. Bit 1 from TIMSK2 is OCIE2B -
this bit must be set to enable a comparison match with the OCR2B register. Any bits not
men oned here are to be considered as 0].

Table 1 Clock select bits and corresponding pre-scaler values for Timers.
CSx2 CSx1 CSx0 Pre-scaler
0 0 1 1
0 1 0 8
0 1 1 64
1 0 0 256
1 0 1 1024

 is given,
f = 16MHz, 𝑇 = = = 62.5𝑛𝑠
𝐴𝑣𝑎𝑖𝑙𝑎𝑏𝑙𝑒 𝑝𝑠 = 1, 8, 64, 256, 1024
Required interrupt interval = 100 ns

 Step 1: Calculate Number of Clock Periods Needed:

 We Know,
𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐝𝐞𝐥𝐚𝐲
𝐍𝐮𝐦𝐛𝐞𝐫 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 𝐧𝐞𝐞𝐝𝐞𝐝 =
𝑪𝒍𝒐𝒄𝒌 𝑷𝒆𝒓𝒊𝒐𝒅 (𝑻)
200 ns
Number of periods needed = = 3.2 = 3 𝑜𝑟 4 [Since we can't have
62.5 𝑛𝑠 a frac on of a clock]
 Step 2: Determine Actual Achievable Delay: cycle,
 If , 𝐍𝐨 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 = 𝟑
 We Know,
𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 𝐍𝐨 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝 (𝐓)
𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 𝟑 × 𝟔𝟐. 𝟓𝐧𝐬 = 𝟏𝟖𝟕. 𝟓𝐧𝐬 (6.25% error) [This is the minimum possible
interrupt interval achievable
without prescaling]
 If , 𝐍𝐨 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 = 𝟒
 We Know,
𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 𝐍𝐨 𝐨𝐟 𝐩𝐞𝐫𝐢𝐨𝐝𝐬 × 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝 (𝐓)
𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 𝟒 × 𝟔𝟐. 𝟓𝐧𝐬 = 𝟐𝟓𝟎𝐧𝐬 (20% error)

 Step 3: Determine the optimal prescaler:


o We need to find the smallest prescaler that allows us to achieve at least 200 ns interval.
 We Know,

4. 𝐄𝐟𝐟𝐞𝐜𝐭𝐢𝐯𝐞 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝 = 𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔) × 𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

𝐑𝐞𝐪𝐮𝐢𝐫𝐞𝐝 𝐃𝐞𝐥𝐚𝐲
5. 𝐓𝐢𝐦𝐞𝐫 𝐂𝐨𝐮𝐧𝐭 (𝐓𝐂/𝐎𝐂𝐑𝟐𝐁) = −𝟏
𝐏𝐫𝐞𝐬𝐜𝐚𝐥𝐞𝐫(𝒑𝒔)×𝐒𝐲𝐬𝐭𝐞𝐦 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝(𝑻)

6. 𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 (𝐀𝐃) = (𝐓𝐂 + 𝟏) × 𝐄𝐟𝐟𝐞𝐜𝐭𝐢𝐯𝐞 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝

o For 𝑃𝑆 = 1:

𝟐𝟎𝟎𝒏𝒔
𝐓𝐂 = − 𝟏 = 𝒓𝒐𝒖𝒏𝒅(𝟐. 𝟐) = 𝟐
𝟏 × 𝟔𝟐. 𝟓𝒏𝒔

𝐀𝐃 = (𝟐 + 𝟏) × (𝟏 × 𝟔𝟐. 𝟓 𝒏𝒔) = 𝟏𝟖𝟕. 𝟓 𝒏𝒔

o For 𝑃𝑆 = 8:

𝟐𝟎𝟎𝒏𝒔
𝐓𝐂 = − 𝟏 = −𝟎. 𝟔 = 𝟎 [Since Nega ve value? → Not possible!]
𝟖 × 𝟔𝟐. 𝟓𝒏𝒔 Assume it 0
𝐀𝐃 = (𝟎 + 𝟏) × (𝟖 × 𝟔𝟐. 𝟓 𝒏𝒔) = 𝟓𝟎𝟎 𝒏𝒔

o For 𝑃𝑆 = 64:

𝟐𝟎𝟎𝒏𝒔
𝐓𝐂 = − 𝟏 = −𝟎. 𝟗𝟓 = 𝟎
𝟔𝟒 × 𝟔𝟐. 𝟓𝒏𝒔

𝐀𝐃 = (𝟎 + 𝟏) × (𝟔𝟒 × 𝟔𝟐. 𝟓 𝒏𝒔) = 𝟒𝟎𝟎𝟎 𝒏𝒔

 So, Higher prescalers only make the interval longer. Therefore, prescaler = 1 gives
us the closest possible interval (125 ns).
 Step 4: Observa on:
 No prescaler gives 𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 exactly 200 ns.
 Solu on: Use the smallest possible prescaler (1) and accept a slight error.

 Step 5: Best Possible Configuration:


Prescaler = 1 → 𝐄𝐟𝐟𝐞𝐜𝐭𝐢𝐯𝐞 𝐂𝐥𝐨𝐜𝐤 𝐏𝐞𝐫𝐢𝐨𝐝 = 1 × 62.5 ns = 62.5ns
OCR2B = 2 → 𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 3 × 62.5 ns = 187.5 ns (6.25% error)
OCR2B = 3 → 𝐀𝐜𝐭𝐮𝐚𝐥 𝐃𝐞𝐥𝐚𝐲 = 4 × 62.5 ns = 250ns (20% error)

 Timer2 Configuration (CTC Mode):

5. Set WGM21 (CTC Mode) → TCCR2A = (1 << WGM21) = 0b00000010;


6. Set Prescaler = 1 (CS20 bit) → TCCR2B = (1 << CS20) = 0b00000001;
7. Set OCR2B = 1 → OCR2B = 2
8. Enable Compare Match Interrupt → TIMSK2 = (1 << OCIE2B) = 0b00000100

C Program:
#include <avr/io.h>
#include <avr/interrupt.h>

void timer2_init() {

DDRD |= 0b01000000; // Set PD6 as output (binary: 01000000 = 0x40)

TCCR2A = 0b00000010; // Set Timer2 in CTC mode (WGM21 = 1, WGM20 = 0)


TCCR2B = 0b00000001; // Prescaler = 1 (CS22:0 = 001)

OCR2B = 2; // Compare value for OCR2B

TIMSK2 = 0b00000100; // Enable interrupt on compare match B

sei(); // Enable global interrupts


}

ISR(TIMER2_COMPB_vect) {

PORTD ^= 0b01000000; // Toggle PD6 (pulse generation)


}
INTRODUCTION
 Clock Source Importance:
o Drives CPU, memory, peripherals.
o Affects instruction speed, baud rate, ADC timing, etc.

 CPU Clock Speed:


o Higher speed → faster performance (e.g., 3.2 GHz = 3.2 billion cycles/sec).

 Oscillator Selection:
o Based on performance, cost, and complexity.
o Check the microcontroller datasheet for supported options.

 Types of Oscillators:
o Internal:
 R-C phase shift oscillator
 Phase-Locked Loop (PLL)
o External:
 Crystal oscillator
 Ceramic resonator
 CMOS clock
 R-C oscillator
 Capacitor-only oscillator

 Selection Considerations:
o Balance between accuracy, cost, and simplicity.

Timer/Counter Oscillator
 Crystal Sharing:
o Same crystal used for low-frequency and Timer/Counter oscillator.
 Pin Sharing:
o TOSC1 ↔ XTAL1, TOSC2 ↔ XTAL2.
o Timer/Counter oscillator shares pins with system oscillator.
 Usage Condition:
o Timer/Counter oscillator only usable with internal RC oscillator as system
clock.
 Clock Frequency Rule:
o System clock must be 4× the oscillator frequency for Timer/Counter usage.
 External Clock Input:
o Can apply external clock to TOSC1.
o Set EXTCLK = 1 in ASSR register to use external clock instead of 32.768 kHz
crystal.
System clock Pre-scalar
 Prescaler Available:
o System clock can be divided using CLKPR (Clock Prescale Register).
 Purpose:
o Reduce clock frequency and power consumption when low processing power is
needed.
 Compatibility:
o Works with all clock sources.
 Effect:
o Affects CPU and all synchronous peripherals.

CLKPR-Clock Pre-scale Register

 Bit 7 – CLKPCE (Clock Prescaler Change Enable):


o Must be set to 1 to enable changes to CLKPS bits.
o All other bits in CLKPR must be 0 during this write.
o Cleared automatically after 4 clock cycles or after writing CLKPS.
o Rewriting CLKPCE within the 4-cycle window has no effect.

 Bits 3:0 – CLKPS3..0 (Clock Pre-scaler Select):


o Set the division factor for the system clock.
o Can be changed at runtime to adjust performance/power.
o Affects CPU speed and all synchronous peripherals.
Clock Pre-scaler Select

Power Management & Sleep Modes


 Purpose:
o Reduce power consumption by shutting down unused modules.

 Flexibility:
o Multiple sleep modes available.

o Helps optimize power use based on application needs.


SMCR – Sleep Mode Control Register

 Purpose:
o Controls power management and sleep mode behavior.

 Key Bits:
o SM2:SM0 → Select the sleep mode (functions defined elsewhere).
o Other bits manage sleep enable/disable features.
PRR – Power Reduction Register

 The PRR (Power Reduction Register) allows selective disabling of specific MCU modules to
reduce power consumption. Disabling a module stops its clock, significantly lowering
current draw.

Bit-by-Bit Descrip on:

 Bit 7 – PRTWI (Power Reduction TWI)


o Disables the Two-Wire Interface (TWI/I²C).
o Set to 1 to turn off the TWI module and save power when it's not used.
o Must be cleared to 0 before using TWI functions again.

 Bit 6 – PRTIM2 (Power Reduction Timer/Counter2)


o Disables Timer/Counter2.
o Useful when Timer2 is not needed, especially in sleep or low-power modes.

 Bit 5 – PRTIM0 (Power Reduction Timer/Counter0)


o Disables Timer/Counter0, which is often used for timing and PWM.
o Set only if Timer0 features are not required.

 Bit 4 – Reserved
o Do not modify this bit.
o Write it as 0 to avoid undefined behavior.

 Bit 3 – PRTIM1 (Power Reduction Timer/Counter1)


o Disables Timer/Counter1, a 16-bit timer.
o Disabling it saves power when Timer1 is idle.

 Bit 2 – PRSPI (Power Reduction SPI)


o Disables the Serial Peripheral Interface (SPI) module.
o Saves power when SPI communication is not in use.

 Bit 1 – PRUSART0 (Power Reduction USART0)


o Disables the USART0 module (used for serial communication).
o Power-saving when UART functions like Tx/Rx are not needed.

 Bit 0 – PRADC (Power Reduction ADC)


o Disables the Analog-to-Digital Converter (ADC).
o ADC draws current even when idle, so disabling it can save power.
 Problem1: Prepare an C program setup to set the Sleep Mode Control Register (SMCR) so
that the system remains in the power-save mode and power reduc on mode (PRR) for its
Timer0, Timer1, and SPI. Use the following table for the SMx bits of the SMCR register. The
PRR register bits are shown, too.

 We need to:
 Set the Sleep Mode Control Register (SMCR) to Power-save mode.
 Enable Power Reduction Mode (PRR) for Timer0, Timer1, and SPI.

 Now, Set SMCR for Power-save Mode:


≫From the sleep mode table:

SM2 SM1 SM0 Sleep Mode


0 1 1 Power-save mode

So, SM2:SM0 = 011


Also, SE (Sleep Enable) = 1 to enable sleep mode
SMCR = 0b00000111
 Now, Enable PRR for Timer0, Timer1, and SPI:
≫ From PRR bits:

PRTIM0 PRTIM1 PRSPI


Bit 5 Bit 3 Bit 2

So, 𝑺𝒆𝒕 𝒃𝒊𝒕𝒔 𝟓, 𝟑, 𝒂𝒏𝒅 𝟐 = 𝟎𝒃𝟎𝟎𝟏𝟎𝟏𝟏𝟎𝟎


PRR = 𝟎𝐛𝟎𝟎𝟏𝟎𝟏𝟏𝟎𝟎
C Program:
void setup_sleep_mode() {
SMCR = 0b00000111; // Power-save mode + sleep enable
PRR = 0b00101100; // Disable Timer0, Timer1, SPI
}
AVR Architecture of CPU
 Arithme c Logic Unit (ALU)
 32 General Purpose Register
(GPR)
o each 8-bit
 Program Counter (PC)
 Instruc on Decoder
 Status Register (SREG)

CPU Components of AVR Microcontroller

1. Arithme c Logic Unit (ALU)

 Performs arithmetic and logical operations.


 Works closely with the General Purpose Registers and Status Register.

2. 32 General Purpose Registers (GPR)

 Total: 32 registers
 Size: Each register is 8-bit
 Purpose: Used for fast data access and manipulation without needing to access RAM.
 Can be used individually (8-bit) or in pairs (16-bit) for certain operations.

3. Program Counter (PC)

 Holds the address of the next instruction to be executed.


 Automatically increments after fetching each instruction.

4. Instruc on Decoder

 Translates the binary instruction codes fetched from memory into control signals.
 Directs other components (ALU, registers, etc.) on what operations to perform.
5. Status Register (SREG)

 Contains flag bits that reflect the outcome of operations in the ALU.
 Common flags:
o C: Carry
o Z: Zero
o N: Negative
o V: Overflow
o S: Sign
o H: Half Carry
o T: Transfer Bit
o I: Global Interrupt Enable

Assembly Language Programming Instruction Set Summary

Flags Clock
Mnemonics Operands Description Operation
Affected Cycles

ADD Rd, Rr Add two registers Rd = Rd + Rr Z, C, N, V, H 1

ADDC Rd, Rr Add with Carry two registers Rd = Rd + Rr + C Z, C, N, V, H 1

SUB Rd, Rr Subtract two registers Rd = Rd - Rr Z, C, N, V, H 1

SUBI Rd, K Subtract constant from register Rd = Rd - K Z, C, N, V, H 1

AND Rd, Rr Logical AND Rd = Rd • Rr Z, N, V 1


OR Rd, Rr Logical OR Rd = Rd ∨ Rr Z, N, V 1
NEG Rd Two’s complement Rd = 0x00 - Rd Z, C, N, V, H 1
INC Rd Increment Rd = Rd + 1 Z, N, V 1
DEC Rd Decrement Rd = Rd - 1 Z, N, V 1

MUL Rd, Rr Multiply unsigned R1:R0 = Rd × Rr Z, C 2

TST Rd Test for Zero or Minus Rd = Rd • Rd Z, N, V 1

CLR Rd Clear Register Rd = Rd ⊕ Rd Z, N, V 1

MOV Rd, Rr Move between Registers Rd = Rr None 1


Flags Clock
Mnemonics Operands Description Operation
Affected Cycles

LDI Rd, K Load Immediate Rd = K None 1

LDS Rd, K Load Direct from Data Space Rd = [K] None 1

IN Rd, P Input from Port P to Register Rd = P None 1

OUT P, Rr Output from Register to Port P P = Rr None 1

PUSH Rr Push Register onto Stack STACK = Rr None 2

POP Rd Pop Register from Stack Rd = STACK None 2

NOP — No Operation — None 1

Break (for On-chip Debug


BREAK — — N/A —
only)

STS K, Rr Store Register to Data Space [K] = Rr None 1

Set bit b of register


SBI A, b Set Bit in I/O Register None 1
A

Clear bit b of
CBI A, b Clear Bit in I/O Register None 1
register A

Skip if Bit in I/O Register is If bit b of A = 0,


SBIC A, b None 1
Cleared skip

Skip if Bit in I/O Register is If bit b of A = 1,


SBIS A, b None 1
Set skip

RJUMP K Relative Jump PC = PC + K + 1 None 1


 Problem1: For the processor ATmega328P, show the contents of registers(R20,R21) and the
8-bit data memory loca ons(0x120) a er the following program is executed.
LDI R20, 5;
LDI R21, 2;
ADD R20,R21;
ADD R20,R21;
STS 0x120, R20;

 Let’s execute the program line by line:

≫ 𝑳𝑫𝑰 𝑹𝟐𝟎, 𝟓; 𝐑𝟐𝟎 = 𝟓

≫ 𝑳𝑫𝑰 𝑹𝟐𝟏, 𝟐; 𝐑𝟐𝟏 = 𝟐

≫ 𝑨𝑫𝑫 𝑹𝟐𝟎, 𝑹𝟐𝟏; 𝐑𝟐𝟎 = 𝐑𝟐𝟎 + 𝐑𝟐𝟏 = 𝟓 + 𝟐 = 𝟕

≫ 𝑨𝑫𝑫 𝑹𝟐𝟎, 𝑹𝟐𝟏; 𝐑𝟐𝟎 = 𝐑𝟐𝟎 + 𝐑𝟐𝟏 = 𝟕 + 𝟐 = 𝟗

≫ 𝑺𝑻𝑺 𝟎𝐱𝟏𝟐𝟎, 𝑹𝟐𝟎; 𝟎𝐱𝟏𝟐𝟎 = 𝐑𝟐𝟎 = 𝟗

 A er the following program is executed


 Registers contents
R20 = 9
R21 = 2
 memory loca ons contents
0x120 = 9

 Problem2: For the processor ATmega328P, show the State contents of RAM loca ons of
$212, $213, $214, $215, and $216 a er execu ng the following program.
LDI R16, 0x99
STS 0x212, R16
LDI R16, 0x85
STS 0x213, R16
LDI R16, 0x3F
STS 0x214, R16
LDI R16, 0x63
STS 0x215, R16
LDI R16, 0x12
STS 0x216, R16
 Let’s execute the program line by line:

≫LDI R16,0x99 R16 = 0x99


≫STS 0x212, R16 0x212 = R16 = 0x99
≫LDI R16, 0x85 R16 = 0x85
≫STS 0x213, R16 0x213 = R16 = 0x85
≫LDI R16, 0x3F R16 = 0x3F
≫STS 0x214, R16 0x214 = R16 = 0x3F
≫LDI R16, 0x63 R16 = 0x63
≫STS 0x215, R16 0x215 = R16 = 0x63
≫LDI R16, 0x12 R16 = 0x12
≫STS 0x216, R16 0x216 = R16 = 0x12

 A er the following program is executed


 memory loca ons contents
0x212 = 0x99
0x213 = 0x85
0x214 = 0x3F
0x215 = 0x63
0x216 = 0x12

 Problem3: For the processor ATmega328P, show the contents of registers and the 8-bit data
memory loca ons from OxFA41 to OxFA44 a er the following program is executed Assume,
C = 1.
LDI R18, 0x98;
LDI R29, Ox65:
SUB R29, R18;
STS OxFA41, R29;
ADDC R18, R29;
STS OxFA42, R18;
LDI R16, 0b11101101;
LDI R20, 0b11011011;
AND R20, R16;
XOR R29, R20;
STS OxFA43, R20;
STS OxFA44, R29;
 Let’s execute the program line by line:

≫LDI R18, 0x98; R18 = 0x98


≫LDI R29, Ox65: R29 = 0x65
≫SUB R29, R18; R29 = R29 – R18 = 0x65 - 0x98 = 0xCD
≫STS OxFA41, R29; 0XFA41 = R29 = 0xCD✅
≫ADDC R18, R29; R18 = R18 + R29 + C = 0x98 + 0xCD + 1 = 0x66
≫STS OxFA42, R18; 0XFA42 = R18 = 0x66 ✅
≫LDI R16, 0b11101101; R16 = 0b11101101 = 0xED
≫LDI R20, 0b11011011; R20 = 0b11011011 = 0xDB
≫AND R20, R16; R20 = R20 & R16 = 0XDB & 0xED = 0xC9
≫XOR R29, R20; R29 = R29 ^ R20 = 0xCD ^ 0xC9 = 0x04
≫STS OxFA43, R20; 0XFA43 = R20 = 0xC9✅
≫STS OxFA44, R29; 0XFA44 = R29 = 0x04✅

 A er the following program is executed


 Registers contents
R16 = 0xED
R18 = 0x66
R20 = 0xC9
R29 = 0x04
 memory loca ons contents
0XFA41 = 0xCD
0XFA42 = 0x66
0XFA43 = 0xC9
0XFA44 = 0x04
Basic Terms in Assembly for ATmega328P
Keyword/Instruction Meaning

ldi
Load Immediate: Load a value directly into a register. Example: ldi r16,
0x55 loads 0x55 into register r16.

out
Output to I/O Register: Send data from a register to a hardware register
(like EECR, EEAR, etc.).

in
Input from I/O Register: Read data from a hardware register into a
general register.

sbi
Set Bit in I/O Register: Sets a single bit (makes it 1) in an I/O register.
Example: sbi EECR, EEPE sets the EEPE bit in the EECR register.

sbic
Skip if Bit in I/O Register is Cleared: If the bit is 0, the next instruction is
skipped.

cli
Clear Interrupts: Disables global interrupts (like turning off interrupt
handling temporarily).
sei Set Interrupts: Enables global interrupts.

ret
Return from Subroutine: Jumps back to the place where the subroutine
was called.

rjmp
Relative Jump: Jumps to a different instruction location (used for loops,
etc.).

Difference Between Assembly and C

 Global Interrupt Enable and Sleep Mode

Function Assembly C

Enable Interrupt sei __enable_interrupt();

Enter Sleep sleep __sleep();


 EEPROM Write Func on

Assembly C

EEPROM_write: void EEPROM_write(unsigned int addr, unsigned char data) {


sbic EECR, EEPE ; Wait if EEPROM is busy while (EECR & (1 << EEPE)); // Wait if busy
rjmp EEPROM_write EEAR = addr; // Set address
out EEARH, r18 ; Set address high EEDR = data; // Set data
out EEARL, r17 ; Set address low EECR |= (1 << EEMPE); // Enable write mode
out EEDR, r16 ; Set data to write EECR |= (1 << EEPE); // Start write
sbi EECR, EEMPE ; Enable write mode }
sbi EECR, EEPE ; Start write
ret

 EEPROM Read Func on

Assembly C

EEPROM_read: unsigned char EEPROM_read(unsigned int addr) {


sbic EECR, EEPE ; Wait if EEPROM is busy while (EECR & (1 << EEPE)); // Wait if busy
rjmp EEPROM_read EEAR = addr;
out EEARH, r18 EECR |= (1 << EERE); // Start read
out EEARL, r17 return EEDR;
sbi EECR, EERE ; Start read }
in r16, EEDR ; Load data
ret

 Change Interrupt Vector Loca on

Assembly C

Move_interrupts: void Move_interrupts(void) {


ldi r16, (1 << IVCE) MCUCR = (1 << IVCE); // Enable move
out MCUCR, r16 MCUCR = (1 << IVSEL); // Move to boot section

ldi r16, (1 << IVSEL) }


out MCUCR, r16
ret
 Read 16-bit Timer Value (TCNT1) Atomically

Assembly C

TIM16_ReadTCNT1: unsigned int TIM16_ReadTCNT1(void) {


in r18, SREG ; Save status unsigned char sreg = SREG;
cli ; Disable interrupts _CLI(); // Disable interrupts

in r16, TCNT1L unsigned int i = TCNT1;


in r17, TCNT1H SREG = sreg; // Restore status
out SREG, r18 ; Restore status return i;
ret }

 Write 16-bit Timer Value (TCNT1) Atomically

Assembly C

Atomic_Write_TCNT1: void TIM16_WriteTCNT1(unsigned int value) {


in r18, SREG unsigned char sreg = SREG;
cli _CLI(); // Disable interrupts
out TCNT1L, r16 TCNT1 = value;
out TCNT1H, r17 SREG = sreg;
out SREG, r18 }
ret

 Problem1: Prepare an Assembly program to set the Sleep Mode Control Register (SMCR) so
that the system remains in the power-save mode and power reduc on mode (PRR) for its
Timer0, Timer1, and SPI. Use the following table for the SMx bits of the SMCR register. The
PRR register bits are shown, too.
 We need to:
 Set the Sleep Mode Control Register (SMCR) to Power-save mode.
 Enable Power Reduction Mode (PRR) for Timer0, Timer1, and SPI.

 Now, Set SMCR for Power-save Mode:


≫From the sleep mode table:

SM2 SM1 SM0 Sleep Mode


0 1 1 Power-save mode

So, SM2:SM0 = 011


Also, SE (Sleep Enable) = 1 to enable sleep mode
SMCR = 0b00000111 = 𝟎𝐱𝟎𝟕
 Now, Enable PRR for Timer0, Timer1, and SPI:
≫ From PRR bits:

PRTIM0 PRTIM1 PRSPI


Bit 5 Bit 3 Bit 2

So, 𝑺𝒆𝒕 𝒃𝒊𝒕𝒔 𝟓, 𝟑, 𝒂𝒏𝒅 𝟐 = 𝟎𝒃𝟎𝟎𝟏𝟎𝟏𝟏𝟎𝟎


PRR = 𝟎𝐛𝟎𝟎𝟏𝟎𝟏𝟏𝟎𝟎 = 𝟎𝐱𝟐𝐂
Assembly Program:
ldi r16, 0x07 ; SMCR = 0b00000111 (Power-save + Sleep Enable)
out SMCR, r16 ; Set sleep mode
ldi r16, 0x2C ; PRR = 𝟎𝐛𝟎𝟎𝟏𝟎𝟏𝟏𝟎𝟎 (disable Timer0, Timer1, SPI)
out PRR, r16 ; Apply power reduction
ret
What is Debouncing?
 When you press a mechanical switch or button, the connection inside doesn't happen instantly.
The metal parts can bounce, causing the signal to quickly switch between HIGH and LOW
before settling. This is called bouncing.

 Debouncing is the process of fixing this issue, so one press is counted as only one signal, not
many.

In Arduino or digital circuits, debouncing removes these false signals to ensure accurate button
or switch input.

Why Does Bouncing Happen?


 Bouncing happens because mechanical switches use metal contacts. When you press a
switch, the metal parts don’t connect smoothly—they bounce for a short time, causing the
signal to flicker between HIGH and LOW.

 This bouncing causes multiple signals instead of one. It can mess up digital circuits like
counters.

 It happens in switches like SPST and SPDT, and can also be affected by electrical noise
like:

 Crosstalk
 EMI (Electromagnetic Interference)
 RFI (Radio Frequency Interference)
 ESD (Electrostatic Discharge)

How Does Bouncing Happen?


 A resistor (R1) is used as a pull-up resistor.
o When the switch is open, the output is HIGH (5V).
o When the switch is closed, it connects to LOW (0V).
 But when you press the switch, the metal contacts don’t connect cleanly. They bounce,
causing the signal to quickly jump between HIGH and LOW before settling.
 So instead of one clean transition (0 → 1 → 0), you get multiple quick changes, which
can confuse digital circuits or microcontrollers.
 Microcontrollers don’t like signals that jump around between logic 0 and logic 1.
How to Avoid Bouncing?
1. Use a Schmitt Trigger:
o A normal buffer switches output even on small noise.

o A Schmitt trigger has two thresholds (high and low), so it ignores small
bounces.
o This behavior is called hysteresis, meaning it remembers the last state and
changes only when the input clearly crosses set levels.

2. Use an RC Debounce Circuit:


o Combine a resistor (R) and capacitor (C) to filter out fast changes.

o Add a Schmitt trigger buffer after the RC network to clean the signal before it
reaches the microcontroller.

3. Inverting Schmitt triggers are often used because they are faster than non-inverting
ones.

Why Do We Need Debouncing?


 When you press a button, bouncing can cause multiple signals instead of one.
 This can trigger multiple interrupts or unwanted actions in your program.

Example:
If a TV remote button isn't debounced, pressing once could change the channel multiple times.

Types of Debouncing:
1. Hardware Debouncing:
o Use physical components (resistors, capacitors, Schmitt triggers) to remove bounces.

2. Software Debouncing:
o Use code to ignore rapid changes in the button state for a short time.

3. Digital Debouncing:
o Like software, done using digital logic or microcontrollers.

4. VHDL Debouncing:
o Debouncing done in hardware description language (used for FPGAs or digital
design).
What is Hardware Debouncing?
 A method using electronic components (like resistors, capacitors, and Schmitt triggers)
to clean up the noisy signal caused by bouncing in switches.

 It ensures only one clean pulse is sent when a switch is pressed or released.

 Goal: Eliminate switch bounce using hardware (resistor, capacitor, and Schmitt trigger).

 Basic RC Debouncing Circuit


 Components:
o Resistor (R)
o Capacitor (C)
o Switch (SPST)
 Circuit Diagram:

 How it Works:
o When the switch is open, the capacitor charges through R, pulling the
output HIGH.
o When the switch is closed, the capacitor discharges, pulling the output LOW.
o The RC time constant (𝝉 = 𝑹 × 𝑪) must be longer than the bounce
time (typically 10–20 ms).
 Problem:
 The capacitor charges/discharges slowly, causing intermediate voltages that can confuse
digital logic.
 Adding a Schmitt Trigger (e.g: 74AHCT14)
 Why?
o The Schmitt trigger has hysteresis, ensuring a clean transition between HIGH and
LOW.
o It inverts the signal (use two in series if non-inverted output is needed).
 Improved Circuit:

 How it Works:
 Switch Open:
 Capacitor charges through R1 + diode (D1) → Output = LOW (inverted).
 Switch Closed:
 Capacitor discharges through R2 → Output = HIGH (inverted).

 The charging equation of capacitor:


𝒕
𝑽𝒄 = 𝑽𝒇𝒊𝒏𝒂𝒍 (𝟏 − 𝒆 𝑹𝑪 )

 The discharging equation of capacitor:


𝒕
𝑽𝒄 = 𝑽𝒇𝒊𝒏𝒂𝒍 𝒆 𝑹𝑪
 Component Selection (Example for 5V Logic)
 Assume:
o Max bounce time (t) = 20 𝑚𝑠
o Leakage current = 1μA
o Best-case switching threshold =0.5V
o Schmitt trigger thresholds (Worse Case):
 Vth+ (LOW→HIGH) = 0.9V

 Vth- (HIGH→LOW) = 1.7V

 Step 1: Choose Capacitor (C)


 A small, cheap capacitor, let C= 0.1 µF

 Step 2: Calculate R2 (Discharge Capacitor)


o When the switch is closed, the capacitor discharges through R2.
o Formula:

t
R =−
V
C × ln( )
V

o For Vfinal = 5V, Vth- = 1.7V, C = 0.1 µF:

20 × 10
R =− ≈ 180 𝒌𝜴
1.7
0.1µF × ln( )
5
o Problem: Leakage current may cause false triggering.

≫The input leakage current (1μA) of the 74AHCT14 causes a small voltage drop across
R2:

V=I ×R

V = 1𝛍𝐀 × 180 𝒌𝜴 = 𝟎. 𝟏𝟖𝑽


≫This is too close to the best-case switching threshold (0.5V), risking false triggering.
o Solution:

1. Use 𝐶 × 10 = 1µ𝐹 𝑅 = 18 kΩ (10 times larger value).

2. Leakage voltage now:

V = 1𝛍𝐀 × 18 𝒌𝜴 = 0.018𝑉 (≪ 0.5𝑉 → 𝑎𝑐𝑐𝑒𝑝𝑡𝑎𝑏𝑙𝑒)

 Step 3: Calculate R1+R2 (Charging Capacitor)(Assume that there is No diode)


o When the switch is open, the capacitor charges through R1 + R2.
o Formula:

t
R +R =−
V
C × ln(1 − )
V

o For Vfinal = 5V, Vth+ = 0.9V, C = 1 µF:


20 × 10
R +R =− ≈ 100 𝒌𝜴
0.9
1µF × ln(1 − )
5
 Step 4: Calculate R2:
R = (R + R ) − R
R = 100𝒌𝜴 − 18𝒌𝜴 = 𝟖𝟐 𝒌𝜴

 Step 5: Hysteresis Voltage:


o Hysteresis (ΔV) is the difference between the two threshold voltages:

ΔV = (Vth− − Vth+ )
ΔV = 1.7 − 0.9 = 0.8 V
 Step 3.1: Calculate R1 (Charging Capacitor)(Assume that there is a diode)
 Some mes, the math gives R1 + R2 < R2, which doesn't make sense. In that case: we use diode
o When the switch is open, if we use diode then the capacitor charges through R1 + diode.
o Formula (with diode drop 0.7V → Vfinal = 4.3V):

t
R =−
V
C × ln(1 − )
V

o For Vfinal = 4.3V, Vth+ = 0.9V, C = 1 µF:


20 × 10
R =− ≈ 85 𝒌𝜴
0.9
1µF × ln(1 − )
4.3
But in our case, we don’t need it because R1 + R2 > R2.
 Problem1: A TV remote control is to be designed for the selec on of channels. The
channel selec on bu ons are required to be debounced, that is, one press must cause the
remote to change to the subsequent channel. It was observed that the switches exhibit
bounce mes well under 5 ms and the duty cycle is 50%. Design a circuit using the
74HC14 Schmi trigger IC along with the resistance and capacitance and calculate the
hysteresis voltage. The worst-case Vth of 74HC14 for a signal going low is 2.2 V and that
of when going high is 0.8 V. Consider that the CMOS device leakage current is 15µA and
the gate's best-case switching point is of the order of 0.4 V. Also, consider that a Si diode
is connected in the circuit and its forward voltage drop, VD = 0.7 V. The supply voltage of
the IC is Vcc = 5 V.

 Is Given:
≫Supply Voltage (Vcc) = 5 V
≫Schmi Trigger Thresholds:
Posi ve-going (Vth₊) = 0.8 V
Nega ve-going (Vth₋) = 2.2 V
≫Input Leakage Current (Ileak) = 15 µA
≫Debounce Time (t) = 5 ms & duty cycle is 50% = 10 ms to ensure stability.
≫Diode Forward Voltage (VD) = 0.7 V (Si diode)
≫ best-case switching threshold = 0.4V

 Step 1: Choose Capacitor (C)


 A small, cheap capacitor, let C= 0.1 µF

 Step 2: Calculate R2 (Discharge Capacitor)


o When the switch is closed, the capacitor discharges through R2.
o Formula:

t
R =−
V
C × ln( )
V

o For Vfinal = 5V, Vth- = 2.2V, C = 0.1 µF:

10 × 10
R =− ≈ 120 𝒌𝜴
2.2
0.1µF × ln
5
o Problem: Leakage current may cause false triggering.

≫The input leakage current (15μA) of the 74AHCT14 causes a small voltage drop across
R2:

V𝒍𝒆𝒂𝒌 = I ×R

V𝒍𝒆𝒂𝒌 = 15𝛍𝐀 × 120 𝒌𝜴 = 𝟏. 𝟖𝑽


≫ Vleak> best-case switching threshold (0.4V), risking false triggering.

o Solution:

1. Use 𝐶 × 10 = 1µ𝐹 (10 times larger value).

 For Vfinal = 5V, Vth- = 2.2V, C = 1 µF:

10 × 10
R =− ≈ 12 𝒌𝜴
2.2
1µF × ln
5

>> Leakage voltage now:

V = 15𝛍𝐀 × 12 𝒌𝜴 = 0.18𝑉 (≪ 0.4𝑉 → 𝑎𝑐𝑐𝑒𝑝𝑡𝑎𝑏𝑙𝑒)

 Step 3: Calculate R1 (Charging Capacitor)


o When the switch is open, if we use diode then the capacitor charges through R1 + diode.
o Formula (with diode drop 0.7V → Vfinal = 4.3V):

t
R =−
V
C × ln(1 − )
V
o For Vfinal = 4.3V, Vth+ = 0.8V, C = 1 µF:
10 × 10
R =− ≈ 48 𝒌𝜴
0.8
1µF × ln(1 − )
4.3
 Step 4: Hysteresis Voltage:
o Hysteresis (ΔV) is the difference between the two threshold voltages:

ΔV = (Vth− − Vth+ )
ΔV = 2.2 − 0.8 = 1.4 V
 Final Component Values:
 Capacitor (C): 1 µF
 Resistor R₂ (discharge): 12 kΩ
 Resistor R₁ (charge): 48 kΩ
 Diode (D1): Si diode
 Hysteresis Voltage (VH): 2.2 V - 0.8 V = 1.4 V

 Final Circuit Design:


 Problem2: A hex inver ng Schmi trigger (74HCT14) dribbles about 1.5 µA from the
inputs. The posi ve and nega ve-going threshold voltages are 3.2 V and 1.8 V,
respec vely. Resistors, R1 and R2 control the capacitor's charging and discharging mes,
respec vely. Design the debounce circuit for a debounce me of 10 ms. Consider that a
Si diode is connected across R2 and its forward voltage drop, VD = 0.65 V. The supply
voltage of the IC is Vcc = 5 V. Compute the best LOW voltage condi on and hysteresis
voltage. Draw the final designed circuit with appropriate parameter values.

 Is Given:
≫Vcc = 5 V
≫Schmi Trigger Thresholds:
Vth₊ = 3.2 V
Vth₋ = 1.8 V
≫ Ileak = 1.5 µA
≫ t = 10 ms
≫ VD = 0.65 V (Si diode)

 Step 1: Choose Capacitor (C)


 A small, cheap capacitor, let C= 0.1 µF

 Step 2: Calculate R2 (Discharge Capacitor)


o When the switch is closed, the capacitor discharges through R2.
o Formula:

t
R =−
V
C × ln( )
V

o For Vfinal = 5V, Vth- = 1.8V, C = 0.1 µF:

10 × 10
R =− = 97.88 ≈ 100 𝒌𝜴
1.8
0.1µF × ln
5
o Problem: Leakage current may cause false triggering.

≫The input leakage current (1.5μA) of the 74AHCT14 causes a small voltage drop across
R2:

V𝒍𝒆𝒂𝒌 = I ×R

V𝒍𝒆𝒂𝒌 = 1.5𝛍𝐀 × 100 𝒌𝜴 = 𝟎. 𝟏𝟓𝑽


≫ VLeak(0.15V) <Vth- (1.8V)→ (𝑎𝑐𝑐𝑒𝑝𝑡𝑎𝑏𝑙𝑒)

 Step 3: Calculate R1 (Charging Capacitor)


o When the switch is open, if we use diode then the capacitor charges through R1 + diode.
o Formula (with diode drop 0.65V → Vfinal = 4.35V):

t
R =−
V
C × ln(1 − )
V

o For Vfinal = 4.35V, Vth+ = 3.2V, C = 0.1 µF:


10 × 10
R =− ≈ 75 𝒌𝜴
3.2
0.1µF × ln(1 − )
4.35

 Step 4: Hysteresis Voltage:


o Hysteresis (ΔV) is the difference between the two threshold voltages:

ΔV = (Vth+ − Vth− )
ΔV = 3.2 − 1.8 = 1.4 V
 Step 5: Best LOW Voltage Condi on:
o The best LOW voltage condition ensures that the capacitor fully discharges
below Vth_low = 1.8 V during bouncing.

o For R2 = 100 𝐤𝛀, & C = 0.1µF the discharge time constant is:

𝜏 = R2 × 𝐶

𝝉 = 100𝐤𝛀 × 𝟎. 𝟏µ𝑭 = 𝟏𝟎𝒎𝒔


This ensures the capacitor discharges sufficiently within the debounce
period.

o The Best LOW Input Voltage:

V , =I ×R

V , = 1.5 𝛍𝐀 × 100 𝒌𝜴 = 0.15 𝐕


 Final Component Values:
 Capacitor (C): 0.1 µF
 Resistor R₂ (discharge): 100 kΩ
 Resistor R₁ (charge): 75 kΩ
 Hysteresis Voltage (VH) = 1.4 V

 Final Circuit Design:


 Problem3: A hex inver ng Schmi trigger (74HCT14) dribbles about 2 µA from the inputs.
The posi ve and nega ve-going threshold voltages are 3.1 V and 1.9 V, respec vely.
Resistors, R1 and R2 control the capacitor's charging and discharging mes, respec vely.
Design the debounce circuit for a debounce me of 20 ms. Consider that a Si diode is
connected across R2 and its forward voltage drop, VD = 0.55 V. The supply voltage of the
IC is Vcc = 5 V. Compute the best LOW voltage condi on and hysteresis voltage. Draw
the final designed circuit with appropriate parameter values.

 Is Given:
≫Vcc = 5 V
≫Schmi Trigger Thresholds:
Vth₊ = 3.1 V
Vth₋ = 1.9 V
≫ Ileak = 2 µA
≫ t = 20 ms
≫ VD = 0.55 V (Si diode)

 Step 1: Choose Capacitor (C)


 A small, cheap capacitor, let C= 0.1 µF

 Step 2: Calculate R2 (Discharge Capacitor)


o When the switch is closed, the capacitor discharges through R2.
o Formula:

t
R =−
V
C × ln( )
V

o For Vfinal = 5V, Vth- = 1.9V, C = 0.1 µF:

20 × 10
R =− = 206.70 ≈ 205 𝒌𝜴
1.9
0.1µF × ln
5
 Step 3: Recheck: Input Leakage Voltage Bias

≫ For 𝐈𝐥𝐞𝐚𝐤 = 2 𝛍𝐀, R2 = 205 𝒌𝜴:

V𝒍𝒆𝒂𝒌 = I ×R
V𝒍𝒆𝒂𝒌 = 2𝛍𝐀 × 205 𝒌𝜴 = 0.41𝑽
≫ VLeak(0.41V) <Vth- (1.9V)→ (𝑎𝑐𝑐𝑒𝑝𝑡𝑎𝑏𝑙𝑒)

 Step 4: Calculate R1 (Charging Capacitor)


o When the switch is open, if we use diode then the capacitor charges through R1 + diode.
o Formula (with diode drop 0.55V → Vfinal = 4.45V):

t
R =−
V
C × ln(1 − )
V

o For Vfinal = 4.45V, Vth+ = 3.1V, C = 0.1 µF:


20 × 10
R =− ≈ 170 𝒌𝜴
3.1
0.1µF × ln(1 − )
4.45

 Step 5: Hysteresis Voltage:


o Hysteresis (ΔV) is the difference between the two threshold voltages:

ΔV = (Vth+ − Vth− )
ΔV = 3.1 − 1.9 = 1.2 V
 Step 5: Best LOW Voltage Condi on:
V , =I ×R
V , = 2 𝛍𝐀 × 205 𝒌𝜴 = 0.41 𝐕

 Final Component Values:


 Capacitor (C): 0.1 µF
 Resistor R₂ (discharge): 205 kΩ
 Resistor R₁ (charge): 170 kΩ
 Hysteresis Voltage (VH) = 1.2 V

 Final Circuit Design:

You might also like