EE 212 L Microprocessor and Microcontroller: Lab Manual
EE 212 L Microprocessor and Microcontroller: Lab Manual
EE 212 L
Lab Manual
Subject Teacher:
Lab Instructor:
Student
Name
Reg.
No.
Section
Prepared by:
OBJECTIVE
The objective of this lab is to,
Understand the design of 8-bit Simple as Possible Computer (SAP-1).
Learn interfacing and programming of AVR based microcontroller.
Do programming for Arduino boards in C++.
[i]
Lab Manual: Microprocessor and Microcontroller
[ii]
LIST OF EXPERIMENTS
[iii]
International Islamic University Islamabad
Faculty of Engineering & Technology
Department of Electrical Engineering
Objectives:
The purpose of this lab is to introduce the basic concept of SAP-1, its functions and
parts and simulate the following components of SAP-1
Program Counter which generates a 4-bit address code of memory
the Accumulator register
An 8-bit Adder-Subtractor
B register
Resources Required:
A computer
Proteus 7.0x or higher
Introduction to SAP-1:
SAP simply called Simple as Possibleis a bus organized computer. SAP-1 is
the first stage in evolution towards the modern computers. The main purpose of SAP
is to introduce all the crucial ideas behind computer operations. Being a simple
computer, SAP-1 also covers many advanced concepts.
Main Features:
Simple-As-Possible
One output device (8 LEDs)
16 bytes of read-only memory
5 instructions: 3 with 1 operand, 2 with implicit operands
Accumulator architecture: Accumulator, Out Register, B Register,
Memory Address Register (MAR) and Instruction Register (IR)
Architecture:
8-bit "W" bus
4-bit program counter, only counts up (starts execution at 0)
4-bit Memory Address Register (MAR)
16x8-bit Memory
8-bit Instruction Register (IR)
6-cycle controller with 12-bit microinstruction word
8-bit Accumulator
8-bit B Register
8-bit Adder-Subtractor
8-bit Output Register
SAP-1 is a bus organized computer. All registers are connected to the W bus with
the help of tri-state buffers. A block diagram of SAP-1 is shown in figure below.
Chip 74LS107, is a dual J-K flip flop that produces the upper 2 address bits. Chip
C2, another 74LS107, produces the lower 2 address bits. Chip is a 74LS126, a quad
tristate normally open switch, it gives the program counter a three state output.
At the start of the computer run, a low CLR resets the program counter to 0000.
During the T1 state, a high EP latches the address on W bus. During the T2 state, a
high CP is applied to program counter, midway through this state, the negative CLR
edge increments the program counter.
Accumulator:
The Accumulator is a buffer register that stores intermediate answers during a
computer run. The accumulator has both a two-state and a three-state output. The
twostate output goes directly to the adder-subtractor and the three-state output goes
to the W bus via a buffer. Therefore, the 8-bit Accumulator word continuously drives
the adder-subtractor; the same word appears on the W bus when EA is high. Chips
74LS173s, is the accumulator. Pins 1 and 2 are grounded on both chips to produce
a two-state output for the adder-subtractor. Chips 74LS126s; these three-state
switches place the accumulator contents on the W bus when EA is high.
Adder-Subtractor:
SAP-1 uses a 2's complement adder-subtractor. When Su is low, the sum out of
the adder-subtractor is A = A+B. When Su is high, the difference appears: A = A+B'
(Recall that the 2's complement is equivalent to a decimal sign change). The adder-
subtractor is asynchronous (unclocked); this means that its contents can change as
soon as the input words change.
When EU is high, these contents appear on the W bus. Chips 74LS86; these
ExclusiveOR gates are a controlled inverter. When SU is low, the contents of the B
register are transmitted. When SU is high, the 1's complement is transmitted and a 1
is added to the LSB to form the 2's complement. Chips 74LS83; these 4-bit full adders
combine to produce an 8-bit sum or difference. Chips 74LS126s, convert the 8-bit
answer into a three-state output for driving the W bus.
B-Register:
This is another 8 bit buffer register. It is used in arithmetic operations. It supplies
the number to be added or subtracted from the contents of accumulator to the
addersubtractor.
A low LB and a positive clock edge load the word on the W bus into the B
register. The two state output of the B register drives the Adder-Subtractor,
supplying the number to be added or subtracted from the contents of the
accumulator.
The input to the Accumulator should be through switches, which will be one 8-bit
binary number. This number is later sent to adder-subtractor. There should be a static
8-bit binary number as the other input to the adder-subtractor. The output of the
addersubtractor should be connected to LEDs. By proper input to the Su pin, the
LEDs should be showing the results of adder-subtractor.
Lab No. 2: Implementation of Input and MAR, RAM, RAM Programming, Instruction
Register, Output Register & Binary Display Page 10
Lab Manual: Microprocessor and Microcontroller
Objective:
The objective of this lab is to implement simulation of Input and MAR, Random
Access Memory (RAM), RAM Programming, Instruction Register (IR), Output
register and Binary Display for SAP-1 Computer.
Resources Required:
• A computer
• Proteus 7.0x or higher
Input Unit:
Input unit is 2-to-1 nibble multiplexer. IC 74157 is used as input unit. It has 8bit
inputs and 4 bit output. Circuit for input unit is shown in figure. The left nibble, (pins
14, 11, 5, 2), comes from the manual input address switch register S1 (these are just
4 DIP switches of your trainer and will be used to manually program your RAM). The
right nibble, (pins 13, 10, 6, 3), comes from the MAR.
The RUN-PROG switch S2 selects the nibble containing address to access
RAM location. When S2 is in the PROG position (i.e. when it is low), the nibble out
of the address switch register is selected. On the other hand, when S2 is in the RUN
position (i.e. when it is high), the output of the MAR is selected.
Procedure:
Connect the circuit as shown in the figure.
Lab No. 2: Implementation of Input and MAR, RAM, RAM Programming, Instruction
Register, Output Register & Binary Display Page 11
Lab Manual: Microprocessor and Microcontroller
Lab No. 2: Implementation of Input and MAR, RAM, RAM Programming, Instruction
Register, Output Register & Binary Display Page 12
Lab Manual: Microprocessor and Microcontroller
Instruction Register:
The Instruction Register is part of the Control Unit. To fetch an instruction from
the memory the computer does a memory read operation. This places the contents
of the addressed memory location on the W bus. At the same time, the Instruction
Register is set up for loading on the next positive clock edge.
The contents of the instruction register are split into two nibbles. The upper nibble
is a two-state output that goes directly to the block labeled "Controller-sequencer" The
lower nibble is a three-state output that is read onto the W bus when needed.
The chips used are 74LS173s. Each chip is a 4-bit three-state buffer register.
The two chips are the Instruction Register. Grounding pins 1 and 2 of C8 convert the
three state output to a two-state output, I7I6I5I4, this nibble goes to the instruction
decoder in the controller sequencer. Signal E1 controls the output of C9, the lower
nibble in the Instruction Register. When E1 is low, this nibble is placed on word bus.
Instruction Register should be able to read instruction from RAM. When L1' is
active and by making the E1' pin active, the upper nibble (Opcode) should be ready
for control matrix circuit and lower nibble (memory address) should be ready to be fed
to the MAR.
Lab No. 2: Implementation of Input and MAR, RAM, RAM Programming, Instruction
Register, Output Register & Binary Display Page 13
Lab Manual: Microprocessor and Microcontroller
Output Register:
At the end of an arithmetic operation the accumulator contains the word
representing the answer; it is then loaded into the output register to be displayed to
the outside world through the Binary Display.
Binary Display:
The binary display is a row of 8 LEDs. Since each LED is connected to one flip-
flop of the output port, the binary display shows the contents of the Output register
Circuit for B register in connection with Output Register, adder and accumulator is
shown below.
Lab No. 2: Implementation of Input and MAR, RAM, RAM Programming, Instruction
Register, Output Register & Binary Display Page 14
Lab Manual: Microprocessor and Microcontroller
Programming SAP-I:
SAP-1 Instruction Set:
SAP-1 computer has a set of five instructions. This instruction set is a list of basic
operations this computer can perform. The instructions are: • LDA
• ADD
• SUB
• OUT
• HLT
Mnemonics:
LDA, ADD, SUB, OUT and HLT represent the abbreviated form of the instruction set
called Mnemonics.
Memory referenced instructions:
LDA, ADD and SUB are memory-referenced instructions because they use the data
stored in memory.
OUT and HLT are not memory-referenced instructions since they do not use the data
stored in memory.
LDA
LDA stands for "Load the Accumulator". A complete LDA instruction includes the
hexadecimal address of the data to be loaded. For instance, LDA 8H means load the
accumulator with the data 8H.
Lab No. 2: Implementation of Input and MAR, RAM, RAM Programming, Instruction
Register, Output Register & Binary Display Page 15
Lab Manual: Microprocessor and Microcontroller
ADD
ADD is another SAP-1 instruction. A complete ADD instruction includes the address
of the word to be added. For instance Add 9H means add the contents of memory
location 9H to the contents of the accumulator; the sum replaces the original contents
of accumulator. First the contents of 9H are loaded into B register, and instantly the
adder-subtractor forms the sum of A and B.
SUB
A complete SUB instruction includes the address of the word to be subtracted. For
example SUB CH means subtract the contents of memory location CH from the
contents of the accumulator. First, contents of CH are loaded into B register and then
instantly the adder-subtractor forms the difference of A and B.
OUT
The OUT instruction transfers the contents of accumulator to the Output port. After
the execution, the answer to the problem in the program can be seen on the LED
display. OUT is not memory-referenced instruction; it does not need an address.
HLT
HLT stands for Halt. This instruction tells the computer to stop processing the data.
HLT marks the end of a program similar to the way a period marks the end of a
sentence. You must use a HLT instruction at the end of every SAP-1 program,
otherwise you get computer trash. HLT is complete in itself; it does not require RAM
word since this instruction does not involve memory.
Programming:
To load an instruction in memory we use some kind of code that the computer can
interpret. Following table shows a set of codes. The number 0000 is a code for LDA,
0001 for ADD, 0010 for SUB, 1110 for OUT and 1111 for HLT. Since a code tells the
computer which operation to perform, it is called Opcode.
Mnemonic Opcode
LDA 0000
ADD 0001
SUB 0010
OUT 1110
HLT 1111
Lab No. 2: Implementation of Input and MAR, RAM, RAM Programming, Instruction
Register, Output Register & Binary Display Page 16
Lab Manual: Microprocessor and Microcontroller
Example:
Address Mnemonics
0H LDA 9H
1H ADD AH
2H ADD BH
3H SUB CH
4H OUT
5H HLT
Address Data
6H FFH
7H FFH
8H FFH
9H 01H
AH 02H
BH 03H
CH 04H
DH FFH
EH FFH
FH FFH
Lab No. 2: Implementation of Input and MAR, RAM, RAM Programming, Instruction
Register, Output Register & Binary Display Page 17
International Islamic University Islamabad
Faculty of Engineering & Technology
Department of Electrical Engineering
Objectives:
The objective of the lab is to implement controller part of the SAP-1.
Resources Required:
A computer
Proteus V7 or higher
Components Required:
4 bit D-type Register, 74LS173 (1)
Quad 2-to-1 Data Selector/Multiplexer, 74LS157 (1)
Quad Two-Input NAND Gate, 74LS00 (6)
Tri Three-Input NAND Gate, 74LS10 (1)
Dual Four-Input NAND Gate, 74LS20 (5)
Hex Inverter, 74LS04 (5)
Dual J-K Flip Flop, 74LS107 (3)
Connecting Wires
Instruction Decoder:
This part of the controller decodes the instruction that are fed by instruction
register. A hex inverter produces complements of the Opcode bits, I7 I6 I5 I4. Then
the 4-input NAND gates decode the five output signals, LDA, ADD, SUB, OUT and
HLT. HLT is the only active low signal, while all others are active high. When the HLT
instruction is in the Instruction Register, all bits I7 I6 I5 I4 are 1111 and HLT is low.
This signal returns to the single-step clock (you made in Lab-1). In either case that is
AUTO or MANUAL, the clock stops and the computer run ends.
Ring Counter:
The Ring counter, sometimes called the State Counter, consists of three flip flop
chips, 74LS107. This counter is reset whenever the Clear-Start button S5 is pressed.
The output of the last flip-flop is inverted so that the Q output drives the J input of the
first flip-flop. Due to this, T1 output is initially high. The CLK signal drives an active
low input; this means that the negative edge of the CLK signal initiates each T state.
Lab No. 3: Implementation of Controller / Sequencer for the SAP-1 and Complete
Integration of SAP-1 Page 14
Lab Manual: Microprocessor and Microcontroller
Lab No. 3: Implementation of Controller / Sequencer for the SAP-1 and Complete
Integration of SAP-1 Page 15
Lab Manual: Microprocessor and Microcontroller
initial state T1 starts with a negative clock edge and ends with the next negative clock
edge. During this T state the T1 output of the Ring Counter is high.
During the next state, T2 is high; the following state T3 is high and so on. As you can
see the ring counter produces six T states. Each instruction is fetched and executed
during these six T states.
Address State
The T1 state is called the address state because the address in the PC is transferred
to the MAR during this state. During this state, EP and LM are active; all other control
bits are inactive. This means that the controller sequencer is sending out a control
word of:
CON = CP EP LM CE LI EI LA EA SU EU LB LO
0 1 0 1 1 1 1 0 0 0 1 1
Increment State
During the Increment State T2, only CP is active, causing the PC to increment
to the next memory location.
CON = CP EP LM CE LI EI LA EA SU EU LB LO
1 0 1 1 1 1 1 0 0 0 1 1
Memory State
The T3 state is called the memory state because the addressed RAM instruction is
transferred from the memory to the Instruction Register. The only active control bits
are CE and LI and the word out of the controller is:
CON = CP EP LM CE LI EI LA EA SU EU LB LO
0 0 1 0 0 1 1 0 0 0 1 1
Fetch Cycle
The address, increment and memory states are called the fetch cycle of SAP-1.
Execution Cycle
The next three states T4 T5 T6 are three states of the execution cycle of SAP-1. The
register transfer during this execution depends on a particular instruction being
executed. Each instruction has its own control routine.
Lab No. 3: Implementation of Controller / Sequencer for the SAP-1 and Complete
Integration of SAP-1 Page 16
Lab Manual: Microprocessor and Microcontroller
Control Matrix
The LDA, SUB, ADD and OUT signals from the Instruction Decoder drive the
control matrix. At the same time the Ring Counter signals T1 to T6 also drive the
matrix. The matrix produces CON, a 12-bit micro-instruction that tells the rest of the
computer what to do.
The control unit is the key to a computer's automatic operation. The Control unit
generates the control words that fetch and execute each instruction. While each
instruction is fetched and executed, the computer passes though different T states, or
timing states, that is periods during which register contents change.
Procedure:
Connect the circuit as shown in the circuit diagram. Connect I7 I6 I5 I4 to DIP switches
on your trainer and give the different opcodes for different instructions. For instance
for HLT instruction, opcode is 1111, this means keeping all DIP switches in "Hi"
position will generate an active low HLT signal. Similarly you can check for other
instructions. Check the signals with the oscilloscope and get your work verified by your
lab instructor. You will be graded for this Lab on the output and functionality of your
circuit.
Lab No. 3: Implementation of Controller / Sequencer for the SAP-1 and Complete
Integration of SAP-1 Page 17
Lab Manual: Microprocessor and Microcontroller
Lab No. 3: Implementation of Controller / Sequencer for the SAP-1 and Complete
Integration of SAP-1 Page 18
Lab Manual: Microprocessor and Microcontroller
Lab No. 3: Implementation of Controller / Sequencer for the SAP-1 and Complete
Integration of SAP-1 Page 19
International Islamic University Islamabad
Faculty of Engineering & Technology
Department of Electrical Engineering
Experiment No. 4: I/O Ports Programming & LED Interfacing with Arduino Page 20
Lab Manual: Microprocessor and Microcontroller
Objectives:
To familiarize the student with the basic operation of the Arduino Uno board, and
Integrated Development Environment (IDE). By the end of the exercise, the student
should be able to know the basic functionalities of the IDE.
To understand that how to make a port input or output
First C++ Program to blink LEDs
Arduino Overview:
Arduino is a prototype platform (open-source) based on an easy-to-use hardware
and software. It consists of a circuit board, which can be programed (referred to as a
microcontroller) and a ready-made software called Arduino IDE (Integrated
Development Environment), which is used to write and upload the computer code to
the physical board.
The key features are:
Arduino boards are able to read analog or digital input signals from different
sensors and turn it into an output such as activating a motor, turning LED on/off,
connect to the cloud and many other actions.
You can control your board functions by sending a set of instructions to the
microcontroller on the board via Arduino IDE (referred to as uploading software).
Unlike most previous programmable circuit boards, Arduino does not need an extra
piece of hardware (called a programmer) in order to load a new code onto the
board. You can simply use a USB cable.
Additionally, the Arduino IDE uses a simplified version of C++, making it easier to
learn to program.
Finally, Arduino provides a standard form factor that breaks the functions of the
microcontroller into a more accessible package
Arduino UNO Component View:
Analog Input Pins – Pins (A0-A5) that take-in analog values to be converted to
be represented with a number range 0-1023 through a 10-bit Analog to Digital
Converter (ADC).
ATmega328 Chip – 8-bit microcontroller that processes the sketch you
programmed.
Built-in LED – in order to gain access or control of this pin, you have to change
the configuration of pin 13 where it is connected to.
Crystal Oscillator – Clock that has a frequency of 16MHz
DC Jack – where the power source (AC-to-DC adapter or battery) should be
connected. It is limited to input values between 6-20V but recommended to be
around 7-12V.
Digital I/O Pins – Input and Output pins (0-13) of which 6 of them (3, 5, 6, 9, 10
and 11) also provide PWM (Pulse Width Modulated) output by using the
analogWrite() function. Pins (0 (RX) and 1 (TX)) are also used to transmit and
receive serial data.
ICSP Header – Pins for “In-Circuit Serial Programming” which is another method
of programming.
Lab No. 4: I/O Ports Programming & LED Interfacing with Arduino Page 21
Lab Manual: Microprocessor and Microcontroller
ON indicator – LED that lights up when the board is connected to a power source.
Power Pins – pins that can be used to supply a circuit with values VIN (voltage
from DC Jack), 3.3V and 5V.
Reset Button – a button that is pressed whenever you need to restart the sketch
programmed in the board.
USB port – allows the user to connect with a USB cable the board to a PC to
upload sketches or provide a voltage supply to the board. This is also used for
serial communication through the serial monitor from the Arduino software.
Lab No. 4: I/O Ports Programming & LED Interfacing with Arduino Page 22
Lab Manual: Microprocessor and Microcontroller
void setup ( )
{
The setup() function is called when a sketch starts. Use it to initialize the variables,
pin modes, start using libraries, etc. The setup function will only run once, after
each power up or reset of the Arduino board.
void loop ( )
{
After creating a setup() function, which initializes and sets the initial values, the
loop() function does precisely what its name suggests, and loops consecutively,
allowing your program to change and respond. Use it to actively control the Arduino
board
Solution:
#define LED 1
void setup( )
{
DDRD = DDRD | (1<<LED); // Set PD1 as output pin
}
void loop( )
{
PORTD = PORTD & ~(1<<LED); // Turn OFF LED
delay(500); // keep it OFF for 500 ms
Lab No. 4: I/O Ports Programming & LED Interfacing with Arduino Page 23
Lab Manual: Microprocessor and Microcontroller
Lab Task:
Write a program to blink built-in LED (Pin No.13, PB5) on UNO board at a frequency
of 4Hz with 50% duty cycle.
Lab No. 4: I/O Ports Programming & LED Interfacing with Arduino Page 24
Lab Manual: Microprocessor and Microcontroller
Objectives:
7 segment display interfacing and programming.
To understand the multiplexing technique.
Introduction:
A seven segment display, as its name indicates, is composed of seven elements.
Individually on or off, they can be combined to produce simplified representations of the
numerals. A single LED is used inside one segment to radiate light through it. If cathodes
of all the LEDs are common, this type of display is called common cathode and for
common anode type display, anode of all LEDs are common and connected to the
common pin.
Multiplexing:
Multiplexing is required when we want to interface more than one displays with
microcontroller. If we interface them normally, they will require lots of I/O ports. In
multiplexing, only one display is kept active at a time but we see all of them active. For
multiplexing all the displays are connected in parallel such that if you activate any
segment, say ‘a’ the ‘a’ segment of all displays glows up. But we can switch ON and OFF
the “common” line of the displays with the Microcontroller pins. So if we wish to light
up the ‘a’ segment of display 1 we simply switch on display 1 first by applying ground
level (for common cathode display) at the common pin of the display and then send a
high signal on the I/O pin connected to segment ‘a’ to lit it.
No. . g f e d c b a Hex
0 0 0 1 1 1 1 1 1 0x3F
1 0 0 0 0 0 1 1 0 0x06
2 0 1 0 1 1 0 1 1 0x5B
3 0 1 0 0 1 1 1 1 0x4F
4 0 1 1 0 0 1 1 0 0x66
5 0 1 1 0 1 1 0 1 0x6D
6 0 1 1 1 1 1 0 1 0x7D
7 0 0 0 0 0 1 1 1 0x07
8 0 1 1 1 1 1 1 1 0x7F
9 0 1 1 0 1 1 1 1 0x6F
Schematic:
a a
g g
PORTD Pins PD7 PD6 PD5 PD4 PD3 PD2 PD1 PD0
Arduino Pins 7 6 5 4 3 2 1 0
Seven Segment Pins DP G F E D C B A
#define SEG0_PIN 8
#define SEG1_PIN 9
byte Count;
byte Seven_Segment[] = {
0x3F, 0x06, 0x5B, 0x4F, 0x66,
0x6D, 0x7D, 0x07, 0x7F, 0x6F
};
void Display(byte No)
{
byte units, tens;
tens = No / 10; // Separate tens from a number
units = No % 10; // Separate units from a number
void setup(){
DDRD = 0xFF; // OUPTPUT PORTS FOR SEVEN SEGMENT DISPLAYS
pinMode(SEG0_PIN,OUTPUT); // SELECT LINE(pin# 08) FOR SEG0
pinMode(SEG1_PIN,OUTPUT); // SELECT LINE(pin# 09) FOR SEG1
}
void loop(){
Display(Count++); // Displays two digit value on 7 segments
if(Count > 99)
Count = 0;
}
Lab Task:
Show hexadecimal numbers from 00 to FF on two seven segment displays
Objectives:
To interface the keypad with Arduino board
To write the program for communication between Arduino and keypad.
Keypad Overview:
Keypad is input device which is used to give commands to other devices, from
calculator to computer; input is given through keypad. It is an equipment used in the
different projects where we need to send different commands to perform anything. In
embedded devices one of the essential part is keypad and it is used to interact with the
embedded devices. It is a low cost equipment and easily available in the market. Keypad
has several applications in real life based projects e.g. calculators, mobile phones, ATM
machine, Digital Locks etc. A 4x4 Keypad is shown in the figure given below.
The connections between keypad and Arduino are provided in the figure given below.
void loop(){
char Key_Pressed = MyKeypad.getKey();
if (Key_Pressed){
Serial.println(Key_Pressed);
}
}
Objectives:
To interface the LCD and program Arduino UNO to show the characters on 16x2
LCD.
Introduction:
A 16 × 2 LCD display is commonly used as a display device in various circuits. This
module is preferred over seven segments as they are economical, easily programmable,
and have no limitation of displaying special and even custom characters. A 16 × 2 LCD
means that it can display 16 characters per row and there are two rows. In this LCD, each
character is displayed in a 5 × 7 pixel matrix. This LCD has two registers: (1) Command
register and (2) Data register.
The command register stores the instructions that are given to the LCD. An
instruction is given to the LCD to do a predefined task such as initializing it, clearing its
screen, setting the cursor position, and controlling the display, and so on. The data
register stores the data to be displayed on the LCD. A 20 × 4 LCD means that it can
display 20 characters per row and there are 4 rows. In this LCD, each character is
displayed in a 5×7 pixel matrix. The pin description 16x2 LCD is shown in Table 7.1.
Schematic:
LCD Functions:
1. LiquidCrystal()
Description
It creates a variable or object of type LiquidCrystal. The display can be controlled using
4 or 8 data lines. For 4 data lines we omit the pin numbers for D0 to D3 and leave those
lines unconnected. The RW pin can be tied to ground instead of connected to a pin on
the Arduino; if so, omit it from this function's parameters.
Syntax
Parameters
RS: The number of the Arduino pin that is connected to the RS pin on the LCD
RW: The number of the Arduino pin that is connected to the RW pin on the LCD (optional)
E: The number of the Arduino pin that is connected to the enable pin on the LCD
D0, D1, D2, D3, D4, D5, D6, D7: The numbers of the Arduino pins which are connected
to the corresponding data pins on the LCD. D0, D1, D2, and D3 are optional; if omitted,
the LCD will be controlled using only the four data lines (D4, D5, D6, D7).
#include <LiquidCrystal.h>
const int RS = 13, E = 12, D4 = 11, D5 = 10, D6 = 9, D7 = 8;
LiquidCrystal lcd(RS, E, D4, D5, D6, D7);
byte k=0;
byte Shape0[7]={
0b01110,
0b01110,
0b00100,
0b01110,
0b10101,
0b00100,
0b01010, };
byte Shape1[7]={ 0x0E,0x0E,0x15,0xE,0x04,0x04,0x0A};
void setup(){
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
lcd.createChar(0, Shape0); // create a new character
lcd.createChar(1, Shape1); // create a new character
lcd.setCursor(0, 0); // Go to Column 0, Row 0
lcd.print("hello, world!"); // Print a message to the LCD.
}
void loop(){
// set the cursor to column 0, line 1
// note: line 1 is the second row,
// since counting begins with 0
lcd.setCursor(0, 1);
// print the number of seconds since reset:
lcd.print(millis() / 1000);
lcd.write(byte(k++%2)); // Show Custom Character 0 and 1
delay(500);
}
Lab Task:
Write a sketch to display your registration number in first line and your name in
Urdu language using 4 custom characters in second line of LCD.
Experiment No. 8:Timer and Counter Mode Programming with Arduino Page 38
Lab Manual: Microprocessor and Microcontroller
Objectives:
To understand the modes and functionality of timers of ATmega328.
To program Timer for event counting.
Introduction:
There are counter registers in microcontrollers,
to generate time delays
to count an event.
for waveform generation
for input capture.
When we connect the external event source to the clock pin of the counter register. This
is counter mode. When we connect the oscillator to the clock pin of the counter. This is
timer mode.
Timers/Counters are essential part of any modern MCU. They are an independent unit
inside a micro-controller. They basically run independently of what instruction CPU is
executing. They are primarily used for the following:
Internal Timer: As an internal timer the unit, ticks on the oscillator frequency. The
oscillator frequency can be directly feed to the timer or it can be pre-scaled. In this
mode it used generate precise delays. Or as precise time counting machine.
External Counter: In this mode the unit is used to count events on a specific external
pin on a MCU.
Pulse width Modulation (PWM) Generator: PWM is used in speed control of motors
and various other applications.
Input Capture Mode: Input capture mode is used to measure time period and pulse
width of an external frequency.
Arduino UNO has 3 timers and these times count at some frequency derived from the
16MHz system clock:
Timer0 is an 8-bit timer:
It is used by millis(), delay() and analogWrite() on pins 5 and 6.
Timer1 is a 16-bit timer:
It is used by analogWrite() functions on pins 9 and 10;
It is also used for driving servos using the Servo library so you can’t use
analogWrite with these pins when using the Servo library.
Timer2 is an 8-bit timer.
It is used by analogWrite() functions on pins 3 and 11 and the Tone() library
Clock Divisor: configured to alter the frequency and various counting modes
Timers can be configured to generate interrupts when they overflow or reach a
specific count
Important Registers and Flags Associated with Timers:
Each timer has following registers associated with it, we can change the Timer behavior
through the timer register:
TCNTn (Timer/Counter Reg): Upon reset, it has zero value and counts with
each timer clock. We can load/read a value into the TCNT0 register
Lab No. 8: Timer and Counter Mode Programming with Arduino Page 39
Lab Manual: Microprocessor and Microcontroller
7 6 5 4 3 2 1 0
WGM WGM TCCR0
COM0A1 COM0A0 COM0B1 COM0B0 - -
01 00 A
R/W R/W R/W R/W R R R/W R/W
0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
WGM CS TCCR0
FOC0A FOC0B - - CS01 CS00
02 02 B
W W R R R/W R/ R/W R/W
W
0 0 0 0 0 0 0 0
Lab No. 8: Timer and Counter Mode Programming with Arduino Page 40
Lab Manual: Microprocessor and Microcontroller
7 6 5 4 3 2 1 0
- - - - - OCF0B OCF0A TOV0 TIFR0
R R R R R R/W R/W R/W
0 0 0 0 0 0 0 0
Timer Modes:
Normal mode:
In this mode, the content of the timer/counter increments with each clock. It counts
up until it reaches its max of 0xFF. When it rolls over from 0xFF to 0x00, it sets high a
flag bit called TOV0 (Timer0 Overflow).
Steps to program Timer0 in Normal mode:
1. Load the TCNT0 register with the initial count value.
2. Load the value into the TCCR0A and TCCR0B register, indicating which mode is to
be used and the pre-scaler option.
3. When you select the clock source, the timer/counter starts to count, and each tick
causes the content of the timer/counter to increment by 1.
4. Keep monitoring the timer overflow flag (TOV0) to see if it is raised. Get out of the
loop when TOV0 becomes high.
5. Stop the timer by disconnecting the clock source
6. Clear the TOV0 flag for the next round.
7. Go back to Step 1 to load TCNT0 again.
CTC mode:
The OCR0A register is used with CTC mode. In CTC mode timer is incremented
with a clock and it counts until the contents of TCNT0 register becomes equal to the
contents of OCR0A register (compare match occurs); then the timer will be cleared and
the OCF0A flag will be set when the next clock occurs. OCF0A flag is in TIFR register.
The difference between Timer0 and Timer2:
Last two combinations of CS02-00 bits select the rising and falling edge of external
event counter in Timer0. Whereas in Timer2 these two combinations of CS22-20 bits
used to select different options of pre-scaler.
Timer1
Timer 1 is 16-bit timer and following is the register’s details
7 6 5 4 3 2 1 0
COM1A COM1A COM1B COM1B WGM1 WGM1 TCCR1
- -
1 0 1 0 1 0 A
R/W R/W R/W R/W R R R/W R/W
Lab No. 8: Timer and Counter Mode Programming with Arduino Page 41
Lab Manual: Microprocessor and Microcontroller
0 0 0 0 0 0 0 0
7 6 5 4 3 2 1 0
WGM1 CS1 TCCR1
ICNC1 ICES1 - WGM13 CS11 CS10
2 2 B
R/W R/W R R R/W R/W R/W R/W
0 0 0 0 0 0 0 0
Schematic Diagram:
Lab No. 8: Timer and Counter Mode Programming with Arduino Page 42
Lab Manual: Microprocessor and Microcontroller
void setup() {
Serial.begin(9600);
pinMode(5,INPUT_PULLUP); // Set Pin No.5 (T1 Pin) as input
}
void loop(){
TCNT1 = 0x0000; // Start counting from 0
TCCR1A = 0x00; // 16-bit counter, Normal Mode
TCCR1B = 0x06; // Start Counting at
// Falling Edge using T1 pin
// For Rising Edge put 0x07
delay(1000); // delay of One Second
TCCR1B = 0x00; // Stop Counting
Serial.print("Input Frequency = ");
Serial.print(TCNT1);
Serial.print(" Hz ");
Serial.print("Time Period = ");
float tp = 1000.0F / TCNT1;
Serial.print(tp);
Serial.println(" ms");
}
Lab Task:
Heart pulses of a patient, in the form of square wave are reaching at Pin T5 (PD5)
(Arduino PIN 5) of Arduino UNO Board. Write a program to measure the current pulse
rate per minute of that patient after each 20 seconds and send this answer via serial port
to Computer.
Lab No. 8: Timer and Counter Mode Programming with Arduino Page 43
International Islamic University Islamabad
Faculty of Engineering & Technology
Department of Electrical Engineering
Objectives:
What is PWM and how you can get the PWM output from the digital pins of Arduino
To program and use the PWM feature of AVR
To generate a square wave of different duty cycles using PWM feature of AVR
To control the brightness of LED through programming and then we will control it
manually by adding the potentiometer.
Introduction:
PWM stands for Pulse Width Modulation and it is a technique used in controlling
the brightness of LED, speed control of DC motor, controlling a servo motor or where you
have to get analog output with digital means. The Arduino digital pins either gives us 5V
(when turned HIGH) or 0V (when turned LOW) and the output is a square wave signal.
So if we want to dim a LED, we cannot get the voltage between 0 and 5V from the digital
pin but we can change the ON and OFF time of the signal. If we will change the ON and
OFF time fast enough then the brightness of the led will be changed. Before going further,
let’s discuss some terms associated with PWM.
TON (On Time): It is the time when the signal is high.
TOFF (Off Time): It is the time when the signal is low.
Time Period: It is the sum of on time and off time.
Duty Cycle: It is the percentage of time when the signal was high during the time of
period.
So at 50% duty cycle and 1Hz frequency, the led will be high for half a second and will be
low for the other half second. If we increase the frequency to 50Hz (50 times ON and OFF
per second), then the led will be seen glowing at half brightness by the human eye.
Now write the following code to change the brightness of the LED using PWM.
Arduino Code: PWD Generation
int led_pin = 11; // Initializing LED Pin
int i;
void setup() {
pinMode(led_pin, OUTPUT); // Declare LED pin as output
}
void loop()
{
for( i=0; i<255; i++) // Fading the LED
{
analogWrite(led_pin, i);
delay(10);
}
for( i=255; i>0; i--)
{
analogWrite(led_pin, i);
delay(10);
}
}
Arduino Code to manually control the Brightness of LED:
An addition to Figure 1, take a 10KΩ potentiometer and connect its left pin to GND
and right pin to 5V of Arduino. and then connect the center pin of potentiometer to the A0
Pin of Arduino as shown in figure 2.
Sketch:
Upload the code in the Arduino IDE and on moving the knob of the potentiometer, the
brightness of the LED will change.
int led_pin = 11; // Initializing LED Pin
int pot_pin = A0; // Initializing LED Pin
int data_10_bit, data_8_bit;
void setup() {
pinMode(led_pin, OUTPUT); // Declare LED pin as output
}
void loop()
{
data_10_bit = analogRead(pot_pin); // Reading from potentiometer
// Mapping the Values between 0 to 255 because we can give
// output from 0-255 using the analogwrite() funtion
data_8_bit = data_10_bit >> 2;
// data_8_bit = map(data_10_bit, 0, 1023, 0, 255);
analogWrite(led_pin, data_8_bit);
delay(10);
}
Lab Task:
Generate a PWM Signal of frequency 490 Hz on Pin No.9 of Arduino UNO Board.
Place an LED with 220 Ω resistor on Pin No.9.
Connect Two Push Buttons on Pin No.2 and Pin No.4. and join their other ends
to Ground.
o Label one button as Up and Other button as Down.
o When we press the Up Button, it should increase the Duty Cycle of PWD
Signal
o When we press the Down Button, it should decrease the Duty Cycle of
PWD Signal.
Objectives:
To learn the difference between polling and interrupt based programming.
To use the timer interrupt.
To use external hardware interrupt.
Introduction:
There are two methods by which a microcontroller can serve a device.
Interrupt: In interrupt method, a device sends an interrupt signal to microcontroller.
Upon reception of interrupt, microcontroller stops its working and serves the device.
Program executed after receiving an interrupt is called Interrupt Service Routine
(ISR).
Polling: In polling, microcontroller continuously monitors the status of device, if the
status is met, microcontroller serves the device. In polling method, microcontroller
can only check single device at a time.
Interrupt Vector Table in ATmega328P:
Schematic:
We can set external interrupt as Edge Triggered or Level Triggered using External Interrupt
Control Register A (EICRA).
INT1 INT0
ISCx1 ISCx0
0 0 Low Level Triggered
0 1 Rising and Falling Edge
Triggered
1 0 Falling Edge Triggered
1 0 Rising Edge Triggered
void loop(){ }
Lab Task:
Two IR Sensors at distance of 1 meter are placed on a road. Sensor0 is connected to
INT0 interrupt pin and Sensor1 is connected to INT1 interrupt pin. A moving car crosses
the Sensor0 first and then Sensor1. Calculate the time difference between two sensors
detection and then the speed of that Car in Kilometer per Hour Units. Send these two
answers via serial port to PC.
Objectives:
To interface the serial port of PC with USART of AVR
To learn that how to program the USART (Universal Synchronous Asynchronous
Receiver / Transmitter) of AVR to transmit & receive asynchronously
Introduction:
AVR has a built in USART (Universal Synchronous Asynchronous Receiver and
Transmitter). We are using asynchronous communication for serial data transfer.
Baud Rate is the data transfer rate, normally we prefer to use 9600 baud rate. So
USART sends Start Bit first then 8 Data bits and then a Stop Bit as shown below.
Serial Functions:
i. Serial is a serial port object. It is used to access first serial port of Arduino.
ii. Serial.begin(baud) Sets the data rate in bits per second (baud) for serial data
transmission. An optional second argument configures the data, parity, and stop
bits. The default is 8 data bits, no parity and one stop bit. It returns nothing.
Serial.begin(9600); // opens serial port,
// sets data rate to 9600 bps
Serial.begin(9600,SERIAL_8N1); // 9600 baud rate, 8-bit data,
// No Parity, 1 Stop Bit
iii. Serial.available()Gets the number of bytes (characters) available for reading from
the serial port. This is data that’s already arrived and stored in the serial receive
buffer (which holds 64 bytes). So it returns the number of bytes available to read.
if (Serial.available()){
int inByte = Serial.read();
} // if receive buffer has some data then read first byte.
iv. Serial.read()Reads data from serial receive buffer and returns the first byte of
incoming serial data available (or -1 if no data is available)
v. Serial.println(val) Prints data to the serial port as human-readable ASCII text
followed by a carriage return character (ASCII 13, or '\r') and a newline character
(ASCII 10, or '\n'). This command takes the same forms as Serial.print()
Input Argument: val is any data type as input argument.
Return Type: It returns the number of byes written to serial port
int analogValue = 100;
Serial.println(analogValue); // print as an ASCII-encoded decimal
Serial.println(analogValue, DEC); // print as an ASCII-encoded decimal
Sketch:
void setup() {
DDRB = 0xFF; // Set Port B as Output Port
PORTB = 0xFF; // Turn OFF all Switches
Serial.begin(9600, SERIAL_8N1); // 9600 baud rate, 8 data bit
// No Parity, 1 Stop Bit
}
void loop(){
if (Serial.available()) { // if some bytes have received
int inByte = Serial.read(); // read first byte
switch(inByte) {
case'0': // if received byte is '1' = 0x31
PORTB |= (1<<5); // Turn OFF FAN
Serial.println("0 - Fan is OFF Now");
break;
case'1': // if received byte is '0' = 0x30
PORTB &= ~(1<<5); // Turn ON FAN
Serial.println("1 - Fan is ON Now");
break;
case'2': // if received byte is '2' = 0x32
if(PORTB &(1<<5))
Serial.println("2 - Fan Status = OFF");
else
Serial.println("2 - Fan Status = ON");
break;
default: // if received byte is defferent
Serial.write(inByte);
Serial.println(" - is Unrecognized Command");
}
}
}
Lab Task:
An LED is connected to Arduino Pin No.13(PB5). Write a Program that that receives a
byte serially and acts according to following table.
Received Byte Action to Perform
'0' Turn OFF LED and send back message
'1' Turn ON LED and send back message
'2' Turn ON LED 2 times with some delay and send back message
'3' Turn ON LED 3 times with some delay and send back message
'4' Turn ON LED 4 times with some delay and send back message
'9' Send back message about the (ON/OFF) status of LED
Any other byte Send back message that this byte is not a valid command
Objectives:
To program and use the ADC feature of ATmega328
Show 10 bit value of ADC on Serial Port.
Introduction:
ADC is used to convert the analog voltages into digital value. ADC is widely used in
data acquisition so most of the modern microcontrollers have on-chip ADC peripheral.
Arduino UNO has on-chip ADC of 10-bit resolution. It has 6 analog input channels. As
the ADC is 10-bit, so the converted digital output is stored in two 8-bit registers ADCL and
ADCH. Reference voltages for ADC can be connected to AVCC (Analog Vcc), internal
1.1V reference or external AREF pin. Minimum 0V and maximum Vcc can be converted
to a digital value. In ADC, Successive approximation method is used to convert analog
voltage into digital value. This circuitry requires a clock frequency between 50 kHz to 100
kHz.
Important Registers Associated with ADC:
Following registers are associated with the ADC of AVR:
ADCL Has 8 LSBs of converted digital result
ADCH Has 2 MSBs of converted digital result
ADMUX For left / right adjusted result, reference voltage and channel
selection
ADCSRA ADC control and status register
ADMUX Register:
Bit # 7 6 5 4 3 2 1 0
Bit Name REFS1 REFS0 ADLAR MUX4 MUX3 MUX2 MUX1 MUX0
Bit # 7 6 5 4 3 2 1 0
Bit Name ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128
Schematic:
Sketch:
void setup() {
Serial.begin(9600); // use 9600 bits per second
}
void loop() {
int A0 = ADC_Read(0); // Read Channel 0
Serial.print("ADC = ");
Serial.print(A0); // Send ADC Value Serially
Serial.print(" Vin = ");
Serial.println(float(ADC) * STEP_SIZE); // Show input Volts
delay(1000);
}
Lab Task:
An LM35 temperature sensor is connected to ADC A0 Pin. Write a Program to read
analog value of LM35 convert it to Centigrade and Send it to serial port. Use 1.1V Vref
and CLK/128 Prescalar.
Objective:
To set up and use the on-chip Serial Peripheral Interface (SPI) of the Arduino Board.
Serial Peripheral Interface (SPI) Overview:
A Serial Peripheral Interface (SPI) bus is a system for serial communication, which
uses up to four conductors, commonly three. One conductor is used for data receiving,
one for data sending, one for synchronization and one alternatively for selecting a device
to communicate with. It is a full duplex connection, which means that the data is sent and
received simultaneously. The maximum baud rate is higher than that in the I2C
communication system.
The SPI allows high-speed synchronous data transfer between the AVR and
peripheral devices or between several AVR devices. On most parts the SPI has a second
purpose where it is used for In System Programming (ISP).
The interconnection between two SPI devices always happens between a master
device and a slave device. Compared to some peripheral devices like sensors, which can
only run in slave mode, the SPI of the AVR can be configured for both master and slave
mode. The mode the AVR is running in is specified by the settings of the master bit
(MSTR) in the SPI control register (SPCR). Special considerations about the SS pin must
be considered for Multi Slave Systems. The master is the active part in this system and
must provide the clock signal a serial data transmission is based on. The slave is not
capable of generating the clock signal and thus cannot get active on its own. The slave
just sends and receives data, if the master generates the necessary clock signal. The
master, however, generates the clock signal only while sending data. That means the
master must send data to the slave to read data from the slave.
SPI uses the following four wires −
1. SCK − This is the serial clock driven by the master.
2. MOSI − This is the master output / slave input driven by the master.
3. MISO − This is the master input / slave output driven by the master.
4. SS − This is the slave-selection wire.
The following functions are used. You have to include the SPI.h.
i. SPI.begin() − Initializes the SPI bus by setting SCK, MOSI, and SS to outputs,
pulling SCK and MOSI low, and SS high.
ii. SPI.setClockDivider(divider) − To set the SPI clock divider relative to the system
clock. On AVR based boards, the dividers available are 2, 4, 8, 16, 32, 64 or 128.
The default setting is SPI_CLOCK_DIV4, which sets the SPI clock to one-quarter
of the frequency of the system clock (5 Mhz for the boards at 20 MHz).
iii. Divider − It could be (SPI_CLOCK_DIV2, SPI_CLOCK_DIV4, SPI_CLOCK_DIV8,
SPI_CLOCK_DIV16, SPI_CLOCK_DIV32, SPI_CLOCK_DIV64,
SPI_CLOCK_DIV128).
iv. SPI.transfer(val) − SPI transfer is based on a simultaneous send and receive: the
received data is returned in receivedVal.
v. SPI.beginTransaction(SPISettings(speedMaximum, dataOrder, dataMode)) −
speedMaximum is the clock, dataOrder(MSBFIRST or LSBFIRST),
dataMode(SPI_MODE0, SPI_MODE1, SPI_MODE2, or SPI_MODE3).
vi. SPI.attachInterrupt(handler) − Function to be called when a slave device receives
data from the master.
a. Mode 0 (the default) − Clock is normally low (CPOL = 0), and the data is sampled on
the transition from low to high (leading edge) (CPHA = 0).
b. Mode 1 − Clock is normally low (CPOL = 0), and the data is sampled on the transition
from high to low (trailing edge) (CPHA = 1).
c. Mode 2 − Clock is normally high (CPOL = 1), and the data is sampled on the transition
from high to low (leading edge) (CPHA = 0).
d. Mode 3 − Clock is normally high (CPOL = 1), and the data is sampled on the transition
from low to high (trailing edge) (CPHA = 1).
AVR Registers
Control register:
SPCR (SPI Control Register)
Status Register:
SPSR (SPI Status Register)
Data Register:
SPDR (SPI Data Register)
SPSR Register:
SPCR Register:
SPCR: SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0
Now, we will connect two Arduino UNO boards together; one as a master and the other
as a slave.
(SS) : pin 10
(MOSI) : pin 11
(MISO) : pin 12
(SCK) : pin 13
void SPI_Begin_Slave(){
DDRB |= (1<<MISO); // Set MISO as an Output Pin
// Set MOSI, SCK and SS as Input Pins
DDRB &= ~(1<<MOSI) & ~(1<<SCK) & ~(1<<SS) ;
SPCR = (1<<SPE); // Enable SPI as a Slave Device
}
byte SPI_Transfer(byte data){
SPDR = data;
while(!(SPSR & (1<<SPIF))); // Wait for Reception complete
return SPDR; // return the received data
}
void setup(){
Serial.begin(9600);
SPI_Begin_Slave();
Serial.println ("SPI Slave");
}
void loop(){
static byte R,S = 100;
R = SPI_Transfer(S);
Schematic Diagram:
Lab Task:
SPI Master unit sends string “SPI is working” to slave unit.
SPI Slave waits for data. SPI Slave receives the string and sends it to the serial terminal.
Objective:
To design an application using Arduino.