EE 354 ES Consolidated Lab Manual Sp23 (Lab1-9)
EE 354 ES Consolidated Lab Manual Sp23 (Lab1-9)
LAB MANUAL
EMBEDDED SYSTEMS
(EE-354) For T.E.(EE)
Instructor name:
Student name:
Roll # Batch:
Semester: Year:
LAB MANUAL
For the course
EMBEDDED SYSTEMS
(EE-354) For T.E.(EE)
Developed by:
Mr. Hassan-ul-Haq, Mr. Hafiz Muhammad Furqan & Ms. Aiman
Spring, 2023
Approved By
____________________ ____________________
____________________ ___________________
____________________ ____________________
To be filled by lab technician
Attendance: Present out of ___ Lab Sessions
Attendance Percentage ________
=======================================================================
To be filled by lab instructor
Lab Score Sheet
Final Final Weighted Score
Rubric Rubric Rubric OEL
Rubric Rubric Rubric Lab for MIS System
Roll Based Based Based Rubric Attendance
Based Based Based Rubric [10(A)+10(B)+5(C)]/25
No. Lab Lab Lab Score Percentage
Lab I Lab II Lab V Score Round to next higher
III IV VI A
B multiple of 5.
LAB SESSION 01
OBJECTIVE:
To set-up the Code::Blocks IDE with AVR toolchain and test an AVR project on the ATmega328P
microcontroller
LAB OUTCOMES:
By the end of the lab, you would be able to:
1) Install the Code::Blocks IDE with an AVR toolchain using (WinAVR)
2) Create an AVR project with the required compiler settings
3) Test the created project on ATmega328P microcontroller using AVRDUDE
BACKGROUND:
The ATmega328P is an 8-bit microcontroller based on the AVR RISC architecture. It is produced by
Microchip Technology. The ATmega328P has 32 KB of flash memory, 2 KB of RAM, and 1 KB of
EEPROM. It has 23 general-purpose I/O pins, a 16-bit timer/counter, a 8-bit timer/counter, a real-time
clock, a pulse-width modulation (PWM) unit, a serial communication interface (USART), a two-wire
interface (TWI), and an analog-to-digital converter (ADC).
The ATmega328P is a popular microcontroller for a variety of projects, including robotics, home
automation, and wearables. It is also used in the Arduino Uno, Arduino Pro Mini, and Arduino Nano
microcontroller development boards. The ATmega328P is a powerful and versatile microcontroller that can
be used in a wide variety of applications. It is a popular choice for hobbyists and professionals alike.
We will be utilizing ATmega328P (Arduino UNO DIP R3) throughout Embedded Systems Lab work and
will program it in C-language. To program the microcontroller, we will use the following:
• Avrdude is a command-line utility for programming AVR microcontrollers. It can be used to write
firmware to the microcontroller's flash memory, erase the flash memory, and read the contents of the
flash memory.
• WinAVR is a software package that includes avrdude, as well as a compiler, assembler, and a number
of other tools for developing applications for AVR microcontrollers.
• Code::Blocks is an integrated development environment (IDE) that can be used to develop applications
for AVR microcontrollers. It includes a graphical user interface for editing and compiling code, as well
as a debugger for stepping through and debugging code.
Avrdude and Winavr are essential tools for developing applications for AVR microcontrollers.
Code::Blocks is a powerful IDE that can make the development process easier.
LAB TASKS
The first two lab tasks guide you to installation of the required IDE and toolchain. The setup files can be
easily found and downloaded from the internet. However, these setup files are available on this shared
folder too.
1) To download the required setup files from the internet, search CodeBlocks and go to
https://www.codeblocks.org/downloads/. Select Download the binary releases. Select the setup
package depending upon your platform like Microsoft Windows in our case. From the given setup files,
select codeblocks-20.03-setup.exe as shown in Figure 1. Click on one of the Download From options
for example Sourceforge.net. For a 32-bit operating system type, you can select codeblocks-20.03-
32bit-setup.exe.
2) Once the setup file is downloaded, click on it to begin the installation process. Select the default option
and follow the installation steps as suggested by the wizard. After a few minutes of decompressing and
install files, click YES when prompted to start Code::Blocks. This should yield the IDE shown in
Figure. For now, select OK if it fails to auto-detect the compiler.
2
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
3
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
3) The Code::Blocks IDE is now ready and would allow you to create projects. Since our aim is to develop
AVR Projects, therefore, we first need to install AVR Toolchain. For this we will make use of WinAVR.
4) Search for WinAVR and go to https://sourceforge.net/projects/winavr/files/latest/download. Click on
Download. It will start downloading the latest WinAVR package.
5) Click on the downloaded file to start the setup wizard. Follow the steps shown in figures and select the
correct features to be installed. The WinAVR package has the required avrdude as well as GNU GCC
Compilers.
Figure 11: Source to Download WinAVR Figure 12: Run Dwonloaded Application File
Figure 15: Destination Folder Figure 16: Choose Components for Installation
4
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
6) Before you create and start working on a project, verify that directories are correctly added to the system
path. To do this, open the command prompt by searching cmd in the Windows search option. In the
command prompt, simply write avrdude. You will see the message shown in Figure if it is correctly
added else you will see the error message shown in Figure.
5
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
7) After this write path to verify that the required directories shown in the figure are added to the system
path.
1) Open the Code::Blocks. Go to File> Create >Project…. Select AVR Project and click Go. Select
Next.
2) At this step, you are asked to give project title and select folder to create project files. Give any
suitable name to your project for example here, we have called it Project1. A new folder ES Labs is
created on the desktop and is chosen as project folder. After this, click Next.
3) Now, make sure the selected compiler is GNU GCC for AVR and keep the remaining settings as
shown in the figure. Then click Next.
4) The processor we have selected for ES labs is ATmega328P. Select it from the dropdown menu
carefully and keep the rest of the settings as shown in the Figure. Then click Finish
5) You will see your created project Project1 folder created in the Projects tab workspace. Click on the
Project Name > Sources. This folder will show 2 files; main.c and fuse.c, double click on the main.c
file to open it. It is a blank file template created for the AVR project. This is where you will write a
code.
6
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
7
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
b) Compiler Settings:
Before we write instructions for our first test project, let’s first complete the required compiler settings
that will be needed for all AVR projects.
6) Now, go to Settings > Compiler.
8
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
Figure 28: Specifying the Compiler and Installation Directory in Toolchain Executables
This will update a number of things for these settings. Verify each as shown in the following figures.
Figure 29: Specifying the Program Files in the Compiler’s Installation Directory
The Program Files and Additional Paths tabs under the Toolchain executables will be updated as
shown.
9
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
Go to Search directories tab and check that C:WinAVR\avr\include is added in the Compiler tab.
10
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
#include <avr/io.h>
#define BLINK_DELAY_MS 1000
#include <util/delay.h>
int main (void)
{
// Arduino digital pin 13 (pin 5 of PORTB) for output
DDRB |= 0B100000; // PORTB5
while(1) {
// turn LED on
PORTB |= 0B100000; // PORTB5
_delay_ms(BLINK_DELAY_MS);
// turn LED off
PORTB &= ~ 0B100000; // PORTB5
_delay_ms(BLINK_DELAY_MS);
}
}
11
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
12
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
There are 2 approaches to upload the generated code on ATmega328P flash memory. First we will
use AVRDUDE through Command Prompt instructions. Through this, you will be able to understand
the working of AVRDUDE for uploading the file to our microcontroller. Later, we will integrate this tool
to our Code::Blocks to eliminate the manual Command Prompt steps for our ease. Let’s begin the
interesting part of this lab.
a) Uploading code to ATmega328P microcontroller using AVRDUDE through Command
Prompt
13
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
3) Now, type avrdude to verify that it is recognized (as has already been done). It display a list
of options available for usage with avrdude command. Read the description written with
each.
4) For now, we will use only the required ones and the details of which are given below. Note
that these are case sensitive.
Table 1: avrdude Usage Options and Description
Options Description Example as applicable to the test case
-p Part No. (To specify the AVR device) In our case, it is m328p (Atmega 328p)
-U Memory operation specification. In our case, flash is the memory type where
Required format is: we want to write the code saved in the
<memory type>:w:<file name> generated Project1.hex file
Where, w shows
read the specified file and write it to the
specified device memory
5) Based on the above, write (type, don’t copy-paste) the following command in the Command
Prompt.
avrdude –p m328p –P com3 –c arduino –U flash:w:Project1.hex
It will display some messages shown in Figure below. For successful upload of the hex file,
you will see the LED blinking at the specified rate.
Figure 40: Uploading the .hex File to ATmega328P through Command Prompt avrdude
b) Uploading code to ATmega328P microcontroller using Code::Blocks tool
14
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
To avoid the time-consuming and intimidating Command Prompt interface, we will now add the
AVRDUDE tool to Code::Blocks. Follow the following steps:
1) In your Code:Blocks IDE, click on Tools > Configure Tools > Add. In the Edit Tool
window, set the Name, Executable, Parameters and Working Directory as shown in Figure.
To set the executable browse the specified path of WinAVR folder, and select avrdude.exe.
Note, that in the parameters option, we have written the same avrdude command used earlier.
The working directory is set to be the one containing the .hex file. Click OK and close the
Tools Window.
15
Embedded Systems Lab Lab 01 Setting-up the Code::Blocks IDE with AVR Toolchain
NED University of Engineering & Technology Electrical Engineering Department
4) Go to Tools> Configure Tools. Either Edit the previous tool or use Add to add another
one. This time set the Parameters and Working Directory in terms of macros replacing
project name and path. Click OK.
Congratulations! You have successfully created, built and tested your first AVR project on
ATmega328P using Code::Blocks with AVR Toolchain.
16
Embedded Systems Lab Lab 02 AVR Port Programming for Digital Input & Output
NED University of Engineering & Technology Electrical Engineering Department
LAB SESSION 02
OBJECTIVE:
To program the AVR ATmega328P I/O (Input/Output) ports for digital input and output
LAB OUTCOMES:
By the end of the lab, you would be able to:
1) Identify the AVR ATmega328P I/O ports
2) Utilize DDR (Direct Data Registers) for setting direction of ports
3) Take digital input and set digital output through I/O ports
4) Build required logics for digital inputs and outputs in pure C-language codes and test them on
ATmega328P microcontroller
5) Utilize logical operations for bit-wise manipulation of ports
BACKGROUND:
ATmega328P Pin Diagram and I/O Ports
Figure 1 shows ATmega328P pin diagram. Here, we can see total 28 pins (14 at each side). Throughout the
labs, we will be exploring functions of these pins and their utilization. Most port pins are multiplexed with
alternate functions for the peripheral features on the device i.e. they have dual roles. Note that enabling the
alternate function of some of the port pins does not affect the use of the other pins in the port as general
digital I/O. However, in this lab, we will focus on the pins that can be utilized for digital input and
output i.e. simple I/O function, so don’t get intimidated by the pin diagram shown in Figure 1.
17
Embedded Systems Lab Lab 02 AVR Port Programming for Digital Input & Output
NED University of Engineering & Technology Electrical Engineering Department
Figure 2: Pins on the ATmega328P with the corresponding locations on the Arduino Uno board.
18
Embedded Systems Lab Lab 02 AVR Port Programming for Digital Input & Output
NED University of Engineering & Technology Electrical Engineering Department
19
Embedded Systems Lab Lab 02 AVR Port Programming for Digital Input & Output
NED University of Engineering & Technology Electrical Engineering Department
Header files:
The #include is a preprocessor directive that instructs the compiler to find the file in the < > brackets and
tack it on at the head of the file you are about to compile. The io.h provides appropriate I/O definitions for
the device we are using, and the delay.h provides the definitions for the delay function.
Statements control the program flow and consist of keywords, expressions, and other statements. A
semicolon ends a statement.
main ( ): All C programs contain the main( ) function that contains the code and is first run when the
program begins. main (void) means the function doesn’t take any input. ‘int main’ means that the function
needs to return some integer at the end of the execution and we do so by returning 0 at the end of the
program.
While Loop: It is a control flow statement that allows code to be executed repeatedly based on a given
Boolean condition. The while loop can be thought of as a repeating if statement. The while(1) will run the
loop forever because ‘1’ is the definition of true (false is defined as 0).
Data Types: A good understanding of C data types for the AVR can help programmers to create smaller
hex files. In declaring variables, we must pay careful attention to the size of the data type and data range,
refer to the Table 1.
Remember that C compilers use the signed char as the default unless we put the keyword unsigned in front
of the char. In many situations, such as setting a counter value, where there is no need for signed data, we
should use the unsigned char instead of the signed char. Using the int instead of the unsigned char leads to
the need for more memory space.
21
Embedded Systems Lab Lab 02 AVR Port Programming for Digital Input & Output
NED University of Engineering & Technology Electrical Engineering Department
22
Embedded Systems Lab Lab 02 AVR Port Programming for Digital Input & Output
NED University of Engineering & Technology Electrical Engineering Department
Similarly, the OR operation of a bit with 1, results in setting the bit high. However, OR operation with 0
leaves the bit unchanged.
Table 2: Bit-wise Logical Operators in C
To invert all bits, the bit-wise NOT (~) operator can be used.
PORTD = ~PORTD;
Example 3 – Using logical operators for bit-wise I/O from ATmega328P ports
The following examples get the status of bit 3 of Port D and send it to the bit 0 of port D continuously.
24
Embedded Systems Lab Lab 02 AVR Port Programming for Digital Input & Output
NED University of Engineering & Technology Electrical Engineering Department
Example 4 – Using compound assignment operators for bit-wise I/O from ATmega328P ports
The Example 3 is re-written using the compound bit-wise operators. Observe the difference. Note that the
compound assignment operators ‘|=’ don’t have a space ‘| =’ in between.
LAB TASKS
From Task 2 to 5, create AVR projects and test them on ATmega328P. Feel free to use different conditional
statements, loops, switch-case structure to complete the C-programming related tasks.
TASK 1: Explain what makes the Blinky.c blink?
The code we tested in Lab 01 is given below. Explain what makes this Blinky.c blink?
25
Embedded Systems Lab Lab 02 AVR Port Programming for Digital Input & Output
NED University of Engineering & Technology Electrical Engineering Department
TASK 2: To check and indicate the status of a sensor using the specified ports and bits of
ATmega328P
A door sensor (here, assume the switch) is connected to pin 1 of Port B, and an LED is connected to pin 5
of Port C. Write an AVR C program to monitor the door sensor and, when it opens, turn on the LED.
TASK 3: To use the general I/O pins of ATmega328P as input or output pin based on the
given condition
Write an AVR C program to monitor bit 7 of Port B. If it is 1, make bit 4 of Port B input; otherwise, change
pin 4 of Port B to output.
TASK 4: To control the specified pins of a given port without disturbing the rest of the pins
Write an AVR C program to control a set of 8 LEDs connected to port D such that the first 4 LED glow
when input from a switch is high, and remain off when the input from switch is low. The remaining 4 LED
toggle continuously without disturbing the rest of the pins of port D.
TASK 5: To control the output based on combination of 2 input pins
Write an AVR C program to read pins 0 and 1 of Port B and update the LEDs at pin 0, 1 & 2 of Port D
according to the following logic. You can use switch-case structure.
Input Port B [1:0] Status Output Port D [2:0] Status
0b 00 0b 000
0b 01 0b 011
0b 10 0b 101
0b 11 0b 111
26
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
LAB SESSION 03
OBJECTIVE:
To program the ATmega328P for reading analog input through its Analog-to-Digital Converter ADC
module
LAB OUTCOMES:
By the end of the lab, you would be able to:
1) Identify the AVR ATmega328P pins associated with the ADC module
2) Identify the purpose of different bits of ADC registers and utilize them for their set purposes like
setting reference voltage, selecting source of analog input, and indicating start / end of conversion
3) Take analog input through the ADC pins and indicate its digital equivalent
4) Build required logics for reading analog input in pure C-language codes and test them on
ATmega328P microcontroller
5) Verify the analog to digital conversion ADC of microcontroller pins by testing the digital output
through external DAC (digital-to-analog) R-2R circuit / DAC0808 IC
BACKGROUND:
Digital computers use binary (discrete) values, but in the physical world the signals are analog (continuous).
Most physical variables are analog in nature and can take on any value within a continuous range of values.
Temperature, pressure, humidity, and velocity are a few examples of physical quantities that we deal with
every day. For acquisition of analog signals, we need Analog-to-Digital (ADC) module for conversion.
Microcontrollers are therefore generally featured with ADC module. In this lab, we will explore
ATmega328P ADC input channels that enable us to capture analog signals.
Basics of Analog-to-Digital Conversion (ADC)
An analog-to-digital converter takes an analog input voltage and after a certain amount of time produces a
digital output code which represents the analog input. ADC involves the following steps:
● Sampling: Sampling is the processes of converting
continuous- time analog signal into a discrete-time
signal by taking the “samples” at discrete-time
intervals. Sampling analog signals makes them
discrete in time but still continuous valued.
Sampling frequency determines the intervals at
which samples are taken. Nyquist criterion requires
that the sampling frequency be at least twice the
highest frequency contained in the signal.
● Quantization: Quantization is the process of
mapping continuous infinite values to a smaller set
of discrete finite values. The quantization step size
is the smallest possible difference in amplitude
between samples.
● Encoding: After quantization, each quantization
Figure 1: Analog-to-Digital Conversion
level is assigned a unique binary code.
27
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
𝑉𝑖𝑛
𝐷𝑜𝑢𝑡 =
𝑆𝑡𝑒𝑝 − 𝑠𝑖𝑧𝑒 Figure 2: 8-bit ADC Representation
28
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
29
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
The name of register is written in capital letters. Each register is 8-bit wide. Indexing is done to show
different bits, for example XYZ [2:0] means the least significant 3 bits of the register XYZ (XYZ2, XYZ1
& XYZ0). XYZ[2:0] = 5 would mean (XYZ2 =1, XYZ1= 0 and XYZ0 =1 since 5 = 0b101).
1) ADC Data Register Low and High Byte
After the A/D conversion is complete, the result is stored in registers ADCL (A/D Result Low Byte) and
ACDH (A/D Result High Byte). For 10-bit ADC result, the eight bits sit in one 8-bit register and the
remaining two bits are provided in the other register, with six bits being unused. The result can be left or
right adjusted as shown below. If only eight bits of resolution are needed, the ADC value is left-justified
and the high-order byte are read through ADCH.
● Reference Selector Bits (REFS [1:0]) The ADMUX [7:6] bits select the voltage reference for the
ADC.
Table 3: Function of the reference selector bits
ADMUX[7:6] Reference High
Description
= REFS[1:0] Voltage Selection
00 AREF Voltage provided at AREF pin externally (Internal Vref turned OFF)
AVCC with external capacitor at AREF pin. Note: Arduino already has
01 AVCC
capacitor placed on line
Internal 1.1 V reference fixed regardless of VCC. Note: Arduino already
11 Internal 1.1V
has capacitor placed on line
30
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
● Analog Channel Selection (MUX[3:0]) The 4 bits ADMUX[3:0] serve as selector for the
multiplexer that selects one of the 6 analog input channels to be connected to ADC.
Table 5: Input Channel Selection for ADC
MUX [3:0] Input Channel
0000 ADC0
0001 ADC1
0010 ADC2
0011 ADC3
0100 ADC4
0101 ADC5
1000 Temperature Measurement
Interesting Fact: The Atmega328P has an internal temperature sensor. Refer to the datasheet and read
about it. The output of the temperature sensor can be selected as one of the inputs for ADC module as
shown in the description of ADMUX Channel Selection bits.
3) ADCSRA (ADC Control and Status Register A)
31
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
5) ADCSRB
This is not needed for now. It has 2 important fields: (ACME-Analog Comparator Multiplexer Enable
and ADTS[2:0]- Auto Trigger Source Selection).
6. Wait for the conversion to be completed by checking the (ADSCRA & (0b00010000))
ADIF bit in the ADCSRA register. Equal to 0 as long as conversion takes place
due to ADIF bit (0)
(ADSCRA & (0b00010000))
NOT equal to 0 when conversion is
7. After the ADIF bit has gone HIGH, read the ADCL and complete due to ADIF bit (1)
ADCH registers to get the digital data output. Read:
For 8-bit result only, x=ADCH;
Notice that you have to read ADCL before ADCH; Where, x is unsigned char
Or to forward at output, PORTB=ADCH
otherwise, the result will not be valid.
For 10-bit result, x=ADC
Where, x is unsigned int
Or, PORTB=ADCL; PORTD=ADCH
8. If you want to read the selected channel again, go back to step 5.
If you want to select another Vref source or input channel, go back to step 4
NOTE: The ADC has two different operating modes. In single conversion mode, each conversion will
be initiated by the user. In free running mode, the ADC is constantly sampling and updating the ADC
Data Registers. When a conversion is complete, the result is written to the ADC data registers, and ADIF
is set. In single conversion mode, ADSC is cleared simultaneously. The software may then set ADSC
again to start a new conversion. In free running mode, a new conversion will be started immediately after
32
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
the conversion completes while ADSC remains high. For further description, refer to the ATmega328P
datasheet section Analog to Digital Converter.
Example # 1: Reading an Analog Voltage Set by a Potentiometer
In this example, we are taking analog input through a potentiometer. The analog input voltage can vary
from 0 to 5V. This is given at ADC0 input channel. The digital 8-bit output is taken through PORTD pins
by reading the ADCH register. An LED is used to indicate each bit of the digital output. For a reference
voltage of 5V, using 8-bit ADC, each level corresponds to 19.53 mV.
Figure 6: Code for Example 1- Reading Analog Input from ADC0 Channel
33
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
LAB TASKS
TASK 1: To test the Example 1 on ATmega328P and verify working of ADC using an
external D/A Converter
1. Create a new AVR project and build the code given in the Example 1. Test the obtained digital output
by varying the output from potentiometer. Observe the on / off status of LEDs (used as indicators for
digital output) and verify the digital voltage by calculation for 8-bit ADC at given reference voltage.
Note that the ATmega328P has an ADC module but not a built-in DAC module so it cannot provide an
analog output through any of its pins.
2. Now, remove the LEDs and provide the 8-bit digital output to an external DAC circuit i.e., convert
the digital output to analog for verification. You can use a simple R-2R circuit of Figure 8 or use
DAC0808 IC. For DAC0808 IC, refer to its datasheet for more information. The pin diagram and
DAC circuit using this is shown in Figure 9 and 10.
3. Measure the analog input given through potentiometer and the analog output reproduced by the DAC.
Compare both and verify the ADC and DAC. This is shown in Figure 11 using R-2R circuit.
34
Embedded Systems Lab Lab 03 ADC Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
Note: Pay attention to the data type of variables when you calculate the input analog voltage using
the step-size and ADC result.
35
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
LAB SESSION 04
OBJECTIVE:
To utilize the USART (Universal Synchronous / Asynchronous Receiver /Transmitter) of ATmega328P for
transmitting and receiving data though asynchronous serial communication with PC
LAB OUTCOMES:
By the end of this lab, you should be able to:
1) Recognize the basics of serial communication protocol; baud-rate, stop bit, data bits, parity etc. and
the importance of required connectors (RS-232)
2) Identify the AVR ATmega328P pins associated with the USART
3) Identify the purpose of different fields of USART registers
4) Program ATmega328P for initializing the USART with given baud-rate
5) Program ATmega328P in C-language to establish serial communication with PC
6) Test and verify data (character, string, integer and float) transmission and reception for given
conditions using a Serial Terminal Emulator like TeraTerm
“The single biggest problem in communication is the illusion that it has taken place.”
– George Bernard Shaw
BACKGROUND:
Microcontrollers are provided with ability to communicate with external devices like computer, other
micro-controllers and peripherals. This communication is done through different protocols to allow
microcontrollers to send and receive data. ATmega328P is provided with USART (Universal
Synchronous/Asynchronous Transmitter/Receiver). In this lab, we will be exploring Asynchronous
Transmitter and Receiver (UART). It is not only used as a communications link to external device but
also as a debugging port to send status messages. This is one of the 3 communication options that can be
established with ATmga328P. The other two are SPI and I2C which will be explored later. Before
discussing the working of relevant pins and registers, we first need to understand the different types and
basics of communication protocols.
36
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
Figure 3: Framing ASCII ‘A’ (41H) with a stop-bit (1) and a start bit (0)
37
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
Parity Bit: UART chips allow programming of the parity bit for odd-, even-, and no-parity options. It is a
single bit added to the data frame to maintain data integrity.
Figure 4: Connection of ATmega328P RXD and TXD pins with Arduino UNO for UART
Figure 5: Placement of RX and TX pins and corresponding LEDs with ATmega328P and ATmega16 on
Arduino UNO board
To establish communication between microcontroller (USART pins) with PC, the PC must have a
communication port to support serial data transfer. These are called COM ports. A COM port is simply an
I/O interface that enables the connection of a serial device to a computer. COM ports are also referred to as
serial ports. They are asynchronous interfaces that can transmit one bit of data at a time when connected to
a serial device.
38
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
data transmission. In the absence of a COM port, a COM-to-USB converter module is needed. You can
read more about it here.
Luckily, the Atmega16U2 incorporated on the UNO (R3) board acts as a USB-to-serial converter for serial
communication using USB com drivers. On PC, a software applications is used with it to send data to or
display the received data from the board.
39
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
40
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
UBRR[15:12] The 4 bits, reserved, are set to 0. The remaining 12 bits UBRR[11:0] contain the USART0
baud rate (pre-scalar). The UBRR0H contains the four most significant bits, and the UBRR0L contains the
eight least significant bits of the USART0 baud rate.
For required baud rate ‘BAUD’, and oscillator frequency fosc, the value for UBRR0 is calculated by;
𝑓𝑂𝑆𝐶
𝑈𝐵𝑅𝑅0 = −1
16 × 𝐵𝐴𝑈𝐷
For a 16MHz clock, the required values of UBRR0 register are given in the Table below for different baud-
rates. Note: U2X0 is set 0 here. The baud-rates can be doubled by setting U2X0 high for same UBRR0
values. The formula can be applied for verification.
Table 1: UBRR0 Values for Different Baud Rates
Baud Rate (bps) UBRR0
2400 416 = 0x01A0
4800 207 = 0x00CF
9600 103= 0x0067
14400 68 = 0x0044
19200 51 =0x0033
Serial Terminal Emulator – TeraTerm
COM Port (communication port) is the original, yet still common, name of the serial port interface on PC-
compatible computers. It can refer not only to physical ports, but also to emulated ports.
Serial terminal emulators are software applications that replicate physical COM ports. The virtual serial
ports are fully compatible with operating systems and applications and are treated in the same way as a real
port. These are used for the serial communication between the host computer and an embedded system
41
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
(Target). It is mainly used as a user interface for debugging embedded system. It is also used for sending
commands, displaying result, loading firmware, logging result, etc.
Tera Term and PuTTY are famous terminal emulator applications. In this lab, we can use Tera Term. It is
an open-source, free, software implemented terminal emulator (communications) program.
1) Download Tera-Term using: https://filehippo.com/download_tera-term/
2) Type Tera Term in Windows search to open it. You will be able to select Serial once you connect
your device to PC USB port (connect Arduino UNO). The Serial and Port options will be enabled.
42
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
The initialization process consists of the following steps. Relevant Register Values (example) & C-Code
To program the USART as Transmitter, follow the steps: Relevant Register Values or C-Code
To program the USART as Receiver, follow the steps: Relevant Register Values or C-Code
EXAMPLES
The tested asynchronous communication is polling based and not interrupt based.
Example # 1: Transmitting a Character from ATmega328P to PC through UART
The following code transmits ‘A’ repeatedly with a delay of 1 sec. Note that only one character is sent at a
time. The following example uses usart_init( ) and usart_putChar( ) from the listed 3 sub-routines therefore,
these sub-routines must be defined in the main.c file.
44
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
The example code given here shows transmission of strings, float and integers by utilizing the subroutines
and functions discussed above. You can observe that a string is received from PC to AVR too.
45
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
Figure 11: Code for Example 2-Transmitting Strings, Float and Integer Data Types
Header File usart.h
For ease, you can include the header and source files (usart.h and usart.c) provided with the manual. Utilize
its simple functions for transmitting and receiving data or use the sub-routines discussed above in your code
to complete the given lab tasks.
LAB TASKS
TASK 1: To test Example 1 for transmitting a character serially at baud-rate of 9600 with 1
stop bit using ATmega328P USART
Test the Example 1 code using Arduino UNO. After building the given code, program the ATmega328P.
Now, disconnect and reconnect Arduino UNO with PC port. Open Serial Terminal Emulator (Tera Term).
Make connection with the required settings and observe the serial terminal. You should see the data
transmitted by AVR (received by the PC) on serial terminal.
• Is there any impact if you select a different baud rate in Tera Term without changing the baud rate
initialized in the ATmega328P code? Are you able to correctly transmit the characters when
microcontroller and PC work at different baud rate?
________________________________________
• Add two more lines to the code and comment on the result.
usart_putChar(65)
usart_putChar(‘65’)
46
Embedded Systems Lab Lab 04 Serial Port Programming of AVR
NED University of Engineering & Technology Electrical Engineering Department
TASK 2: To program ATmega328P for controlling the status of LED based on the received
character
Modify the previous code to make the microcontroller receive a character sent by PC. If the received
character is ‘A’, turn on the on board LED otherwise turn it off. The data should be received at baud-rate
of 14400 with 1 stop bit.
TASK 3: To transmit the analog voltage across a potentiometer read by the ATmega328P
ADC to PC
Extend the Task 2 of Lab 03 where you used ADC module to measure the voltage across potentiometer.
Send (transmit) the following through USART of the microcontroller to the PC serial terminal.
1) The 10-bit ADC output (in range of 0 to 1023)
2) The analog voltage across potentiometer in Volts
Pay attention to the data-type. You may use any suitable baud rate of your choice.
Vary the voltage and observe the values. Verify the analog voltage reading by ADC module and
transmission through the USART by comparing voltmeter reading and values displayed by Tera Term.
Sample Output:
**********10-bit ADC************
**********5V Reference Voltage****
*****Voltage across Potentiometer***
47
Embedded Systems Lab Lab 05 LCD Interfacing
NED University of Engineering & Technology Electrical Engineering Department
LAB SESSION 05
OBJECTIVE:
To interface an LCD (Liquid Crystal Display) screen with ATmega328P by sending required commands
and data
LAB OUTCOMES:
By the end of this lab, you would be able to:
1) Identify the pins and commands for controlling a 16x2 LCD
2) Interface a 16x2 LCD screen with ATmega328P and display different messages
“I don't care what it is, when it has an LCD screen, it makes it better.” — Kevin Rose
INTRODUCTION:
Display units like LEDs, 7-segment LED displays, LCD screens etc. play an important part in establishing
a good communication between the users and machines, and therefore, are vital for embedded systems.
Through display screens, the user gets a feeling of knowing the system’s working status. Consider the
examples of ATM machine, automatic washing machine or microwave ovens. They allow us to give input
through keypad or knobs or touch screens, and display useful messages on screens which guide us or show
the status of process. LCD screens are now seen everywhere due to their declining prices, ease of
programming due to an internal controller, and ability to display characters and graphics.
For learning purpose, we are interfacing our ATmega32P microcontroller with a standard 16x2 LCD screen.
16×2 LCD is named so because; it has 16 Columns and 2 Rows. Such dot-matrix LCDs are available in
different packages like 8x1, 8x2, 16x1, and 20x4.
48
Embedded Systems Lab Lab 05 LCD Interfacing
NED University of Engineering & Technology Electrical Engineering Department
LCD Pinout
Figure 1 shows the 16 pins of a 16x2 LCD and their names. Most of the LCDs have these 16 pins that are
used for connection according to their functionality. Let’s discuss the function of each pin one-by-one.
49
Embedded Systems Lab Lab 05 LCD Interfacing
NED University of Engineering & Technology Electrical Engineering Department
In this lab, we are interfacing the LCD with ATmega328P directly (parallel interface) and sending data
in 8-bit mode. Note that the 8-bit data interfacing is easier to program but uses 4 more pins.
LCD Commands
The following table hex code for the commands that are sent to LCD instruction register for the specified
functions.
Table 1: Hex code for Commands
Hex Code for
Function
Command to LCD
0E Display on, cursor on
01 Clear display screen
02 Return home
04 Decrement cursor (shift cursor to left
06 Increment cursor (shift cursor to right)
05 Shift display right
07 Shift display left
0F Display on, cursor blinking
80 Force cursor to beginning of first line
C0 Force cursor to beginning of 2nd line
38 Function Set: 2 lines and 5 × 8 matrix (D0–D7, 8-bit mode)
08 Display off, cursor off
18 Shift the entire display to the left
1C Shift the entire display to the right
Interfacing LCD with ATmega328P and C-Programming
The Figure 2 shows required connections for LCD 16 pins with ATmega328P in 8-bit data mode. The
R/W pin can be directly connected to ground instead of utilizing an I/O pin (as we are performing write
operation only).
50
Embedded Systems Lab Lab 05 LCD Interfacing
NED University of Engineering & Technology Electrical Engineering Department
For controlling the LCD and sending commands and data, the following steps are needed. Remember, the
digital I/O pins connected with the LCD must be configured as output pins using DDRx registers as per
your connections.
To initialize the LCD for 2-line and 8-bit operation, the following sequence of commands should be sent
to the LCD. Next we will show how to send a command to the LCD. After power-up you should wait
about 15ms before sending initializing commands to the LCD. If the LCD initializer function is not the
first function in your code you can omit this delay.
4) lcd_print: This takes a complete string to be printed and passes one character at a time by lcdData.
52
Embedded Systems Lab Lab 05 LCD Interfacing
NED University of Engineering & Technology Electrical Engineering Department
Figure 4: Sample Code for Example 1 - LCD Interfacing (8-bit Mode) with ATmega328P
LAB TASKS
TASK 1: To test Example 1 using ATmega328P and 16x2 LCD
Program ATmega328P with the given code. Make connections to interface the LCD and test the results.
TASK 2: To test different commands for modifying LCD display
Modify the code and test different commands to make the display interesting.
• On line 1, display: <Your Name> (You can have more than 16 characters in the string).
• On line 2, display: <Roll # …… >
• Make the text moving (scrolling) continuously from left to right by using shift display commands.
53
Embedded Systems Lab Lab 05 LCD Interfacing
NED University of Engineering & Technology Electrical Engineering Department
Go-to Subroutine
Following is an interesting subroutine that allows you to move cursor at any specified location (y, x).
Where x is the line number (1 or 2) and y is character position (1 to 16).
54
Embedded Systems Lab Lab 06 SPI Protocol and Max6675 Interfacing
NED University of Engineering & Technology Electrical Engineering Department
LAB SESSION 06
OBJECTIVE:
To utilize SPI (Serial Peripheral Interface) protocol for interfacing the max6675 module with ATmega328P
and develop temperature measurement system based on the K-type thermocouple
LAB OUTCOMES:
By the end of this lab, you will be able to:
1) Recognize the difference between synchronous and asynchronous transmission
2) Identify the AVR ATmega328P pins associated with SPI communication
3) Identify the purpose of different fields of SPI registers
4) Program ATmega328P for SPI communication in master and slave modes for single-byte and
multiple-byte burst read/write
5) Interface SPI protocol-based module (Max6675) as slave with ATmega328P in master mode
6) Develop the complete system for temperature measurement and transmit result through USART to
PC
INTRODUCTION:
In Lab 04, we discussed briefly about serial and parallel data transmission. USART was utilized for
asynchronous transmission and reception, which is one of the types of serial communication. In this lab,
we will explore Serial Peripheral Interface communication protocol which is synchronous. The SPI (serial
peripheral interface) is a bus interface connection incorporated into many devices. The SPI bus was
originally started by Motorola Corp. (now Freescale), but in recent years has become a widely used standard
adapted by many semiconductor chip companies as it’s faster, compact and results in reduced power
consumption. Let’s first understand the features of Serial Peripheral Protocol.
Serial Peripheral Interface Bus Protocol
SPI has a Master/Slave configuration. It has only one master device but can have multiple slaves. A master,
that initiates communication, is usually a microcontroller and the slaves can be a microcontroller, sensors,
ADC, DAC, LCD etc.
SPI is 4-wire protocol.
• SPI devices use only 2 pins for data transfer that are; SDI and SDO,
also called MISO (Master-In Slave-Out) and MOSI (Master-Out
Slave-In).
• The SPI bus has the SCLK or SCK (shift clock) pin to synchronize the
data transfer between two chips.
• The last pin is CE chip enable, also called SS Slave Select, which is
used to initiate and terminate the data transfer. It determines which
Figure 1: 4-wire SPI Bus
device the master is currently communicating with. Representation
55
Embedded Systems Lab Lab 06 SPI Protocol and Max6675 Interfacing
NED University of Engineering & Technology Electrical Engineering Department
Working of SPI
The system consists of two 8-bit wide shift registers, and a master clock generator. The SPI master initiates
the communication cycle when pulling low the slave select 𝑆𝑆 ̅̅̅. Master and slave prepare the data to be sent
in their respective shift registers, and the master generates the required clock pulses on the SCK line to
interchange data (one-bit at a time in each clock cycle). In SPI, the shift registers are 8 bits long. It means
that after 8 clock pulses, the contents of the two shift registers are interchanged. Data is always shifted from
master to slave on the MOSI, line, and from slave to master on the master MISO, line. After each data
packet, the master will synchronize the Slave by pulling high the slave select, ̅̅̅𝑆𝑆 line. It must be noted that
SPI is full duplex, meaning that it sends and receives data at the same time.
Figure 4: Pin Configuration of ATmega328P for SPI Interface and Associated Arduino UNO
pinout
Master-In MISO For sending data from Slave devices to Master device. Input – For Master
Slave-Out Output – For Slave
Master-Out MOSI For sending data from Master device to Slave devices. Input – For Slave
Slave-In Output – For Master
Serial SCK For clock pulses to synchronize data transmission from Input – For Slave
Clock Master devices. Output – For Master
57
Embedded Systems Lab Lab 06 SPI Protocol and Max6675 Interfacing
NED University of Engineering & Technology Electrical Engineering Department
The SPI Data Register is a read/write register. To write into SPI shift register, data must be written to SPDR.
To read from the SPI shift register, you should read from SPDR. Writing to the SPDR register initiates data
transmission.
58
Embedded Systems Lab Lab 06 SPI Protocol and Max6675 Interfacing
NED University of Engineering & Technology Electrical Engineering Department
59
Embedded Systems Lab Lab 06 SPI Protocol and Max6675 Interfacing
NED University of Engineering & Technology Electrical Engineering Department
codes or subroutines are given here as sample for reference. In this lab, we will be operating our
microcontroller in the master mode only.
60
Embedded Systems Lab Lab 06 SPI Protocol and Max6675 Interfacing
NED University of Engineering & Technology Electrical Engineering Department
2. Wait till transmission is complete i.e., poll SPIF flag to become high.
3. Make SS high to deselect slave.
61
Embedded Systems Lab Lab 06 SPI Protocol and Max6675 Interfacing
NED University of Engineering & Technology Electrical Engineering Department
junction diode measurement with the amplified thermocouple voltage and reads out the 12-bit result onto
the SO pin. A sequence of all zeros means the thermocouple reading is 0°C. A sequence of all ones means
the thermocouple reading is +1023.75°C.
65
Embedded Systems Lab Lab 07 PWM Generation using AVR Timers
NED University of Engineering & Technology Electrical Engineering Department
LAB SESSION 07
OBJECTIVE:
To configure the Timer/Counter registers of AVR ATmega328P for generation of PWM (Pulse-Width
Modulation) signals
LAB OUTCOMES:
By the end of this lab, you will be able to:
1) Understand the timers/counters of an AVR microcontroller and their different modes of operation.
2) Identify the AVR ATmega328P pins associated with the timer ports.
3) Identify the purpose of different fields of timer / counter registers.
4) Configure the timer/counter registers for generation of PWM signal in Fast PWM mode.
5) Program ATmgea328P for PWM signal generation and verify the pulse-width and duty cycle of
the generated signals.
6) Control the position of a servo motor using PWM signal generated by ATmega328P.
“Getting into the habit of switching a timer on will, I promise, save you from any number of kitchen
disasters.” — Delia Smith
INTRODUCTION:
Microcontrollers have counter registers which can store the count of pulses from oscillator (clock) or any
external signal. Such registers can be used as Counter or Timer. To count an event, the external event
source can be connected to the pin of the counter register. The content of the counter is incremented
whenever the external event occurs. The content of the counter represents how many times an event has
occurred. To generate time delays, we connect the oscillator to the clock pin of the counter. The content of
the counter is incremented when the oscillator ticks. Since the frequency of the oscillator in a
microcontroller is known, and multiplying the time period with the count in the counter register, one can
calculate the time elapsed. The flag is set when the counter overflows.
Figure 2: A General Representation of the Registers and Signals Associated with AVR times
In each timer module, there is a waveform generator. The waveform generator can generate waves on the
OCn pin.
We will look into the details of each of these for the three timers and their use to program timers.
PWM mode well suited for power regulation, rectification, and DAC applications. High frequency allows
physically small sized external components (coils, capacitors), hence reduces total system cost.
Figure 5: The two PWM configuration output waveforms with TOP = 255
The final two output modes shown in Figure 6 represent the fast and phase-correct PWM waveforms when
the TOP value is set to the 8-bit value stored in OCRA. Both of these modes effectively disable the OCA
pin functionality at the benefit of increasing the PWM frequency dramatically. In both cases, the TCNT
register will count up to the OCRA value, and then either reset to 0 or start counting down toward 0. The
only comparison that matters is that to OCRB, which will affect the OCB pin as in the previous cases. The
two most significant results are that for a value loaded into OCRA, the total number of analog output levels
available is reduced from 256 to OCRA + 1.
Figure 6: The two PWM configuration output waveforms with TOP = 255
69
Embedded Systems Lab Lab 07 PWM Generation using AVR Timers
NED University of Engineering & Technology Electrical Engineering Department
For COM bits in the other modes, refer to the datasheet of ATmega328P.
70
Embedded Systems Lab Lab 07 PWM Generation using AVR Timers
NED University of Engineering & Technology Electrical Engineering Department
71
Embedded Systems Lab Lab 07 PWM Generation using AVR Timers
NED University of Engineering & Technology Electrical Engineering Department
WGM13:0
set to Fast
PWM
Modes
72
Embedded Systems Lab Lab 07 PWM Generation using AVR Timers
NED University of Engineering & Technology Electrical Engineering Department
Figure 7: Representation of 16-bit Timer Module and Associated Signals and Pins
Programming 8-Bit Timers (Timer0/2) in Fast PWM Mode for PWM Signal
Generation
1) Select modes using COM and WGM bits, for example; fast PWM (mode 3 or 7) and non-inverting
(COM0x10= 0b10).
2) Select a pre-scalar by CS bits.
3) In Fast PWM mode, use the pins associated with the timer. Configure them as output pins.
73
Embedded Systems Lab Lab 07 PWM Generation using AVR Timers
NED University of Engineering & Technology Electrical Engineering Department
74
Embedded Systems Lab Lab 07 PWM Generation using AVR Timers
NED University of Engineering & Technology Electrical Engineering Department
PWM Signals for DC Motor Speed Control and Servo Motor Position Control
Pulse-width modulation (PWM) is a technique for controlling the speed of a DC motor by varying the width
of the pulses that are applied to the motor's power supply. The duty cycle determines the average voltage
that is applied to the motor. A higher duty cycle results in a higher average voltage, which in turn results in
a higher motor speed.
A servo motor is a motor whose shaft position can be controlled precisely. The motor has an internal
servomechanism that provides feedback about the position of shaft. SG90 is a small “Servo Motor” whose
position can be controlled by a PWM signal. The required duty-cycle for different positions of this servo
motor are given in Table below. The power requiements of SG90 can be met by Arduino Uno board.
Utilizing the timers of ATmega328P, you can easily generate the required PWM signals for controlling the
position of SG90.
• Required
Frequency=50 Hz
• At Duty cylce ~ 5 %,
Shaft Position = 0 ͦ
LAB TASKS
TASK 1: To verify PWM signal generation by 8-bit Timers using Example 1
1) Create an AVR project and build the code given in Example 1. Program the microcontroller with it and
test the PWM signal generated at PD3 using an Oscilloscope.
2) Measure the frequency, time-period and duty-cycle of the generated waveform for verification.
3) Modify the code to generate a waveform at 2k Hz frequency with duty-cycle of 50% using Timer0.
Show the modified code and results.
TASK 2: To test Example 2 for servo-motor position control using Timer1 PWM signal
1) Create an AVR project and build the code given in Example 2. Program the microcontroller with it.
2) Make appropriate connections to power up the SG90 servo-motor and to provide PWM signal for
control.
3) Observe the position of motor-shaft. Does it rotate by 90 degrees after every 1 second?
4) Can you control the SG90 servo motor using Timer0 or Timer2? What is the minimum frequency
achievable by Timer0, 1 and 2 in Fast PWM Modes? Consider the higher pre-scalar.
76
Embedded Systems Lab Lab 08 OEL: Voltage Measurement using ZMPT101 Module
NED University of Engineering & Technology Electrical Engineering Department
LAB SESSION 08
OEL (Open Ended Lab)
OBJECTIVE:
To interface analog voltage sensor ZMPT101B for measurement of phase voltage and display its true RMS
(Root Mean Square) value on LCD (Liquid Crystal Display) screen.
DELIVERABLES:
• Report
• C-Code
• Complete hardware setup (ZMPT101B module and LCD interfaced with Microprocessor)
77
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
LAB SESSION 09
OBJECTIVE:
To set up Inter-Integrated Circuit (I2C) communication on Atmega328P micro-controller for controlling a
16x2 LCD screen through PCF8574 I2C I/O (Input/Output) expander
LAB OUTCOMES:
By the end of this lab, you will be able to:
1) Explain the Inter-Integrated Communication (I2C) protocol
2) Identify the AVR ATmega328P pins associated with I2C interface (Two-Wire Interface TWI)
3) Identify the purpose of different fields of TWI registers
4) Program ATmega328P TWI in master and slave modes for single-byte and multiple-byte burst
read/write
5) Operate a 16x2 LCD in 4-bit mode
6) Identify the pins of PCF8574 I2C I/O expander module
7) Program ATmega328P TWI for controlling 16x2 LCD screen through PCF8574 expander
“A lack of communication breeds assumptions of what the other is thinking or feeling; and assumptions
are, more often than not incorrect” — Misty Lynn Walker
INTRODUCTION:
The Inter-Integrated Circuit (I2C or I2C or IIC) serial communication protocol was created by Philips to
attach low-speed peripherals to an embedded micro-processor for reliable short-distance communication.
I2C is a multi-point protocol in which more than two devices are able to communicate along the serial
interface. It uses only 2 pins for data transfer. They are called:
• SCL (Serial Clock), which synchronizes the data transfer between two chips
• SDA (Serial Data), which carries the data.
These two pins, SDA and SCK, make the I2C a 2-wire interface. In many application notes, including AVR
datasheets, I2C is referred to as Two-Wire Serial Interface (TWI). We will be using I2C and TWI
interchangeably.
The 2 pins are bidirectional open-drain pins which means that a 4.7 kilo Ohm pull-up resistor for each of
line is needed as shown in Figure 1. If one or more devices pull the line to low (zero) level, the line state is
zero and otherwise the line state remains high (one).
Each of the devices connected with I2C multipoint bus interface is called a node. Each node can operate as
either master or slave.
• Master is a device that generates the clock for the system; it also initiates and terminates a transmission.
• Slave is the node that receives the clock and is addressed by the master.
In I2C, both master and slave can receive or transmit data, so there are four modes of operation.
• Master transmitter
• Master receiver
• Slave transmitter
• Slave receiver.
Notice that each node can have more than one mode of operation at different times, but it has only one
mode of operation at a given time.
Working of I2C Protocol
I2C is a synchronous serial protocol; each data bit transferred on the SDA line is synchronized by a high-
to-low pulse of clock on the SCL line. The data line cannot change when the clock line is high; it can change
only when the clock line is low. The START and STOP conditions are the only exceptions to this rule.
Figure 2: I2C Bit Format Figure 3: I2C Start and Stop Conditions
Each transmission is initiated by a START condition and is terminated by a STOP condition. The START
and STOP conditions are generated by the master. START and STOP conditions are generated by keeping
the level of the SCL line high and then changing the level of the SDA line. The START condition is
generated by a high-to-low change in the SDA line when SCL is high. The STOP condition is generated by
a low-to-high change in the SDA line when SCL is low. The bus is considered busy between each pair of
START and STOP conditions, and no other master tries to take control of the bus when it is busy.
Figure 4: I2C Typical Transmission (Start + Address Packet + Data Packet(s) + Stop)
• In I2C, normally, a transmission is started by a START condition.
79
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
• This is followed by an address packet (SLA + R/W). Address packet consists 8 or 9 bits. The first 7-
bits are slave address (which allows connection of 128 devices). The 8th bit shows operation (1 for read,
0 for write). The 9th bit is an ACK (acknowledge - 0) or NACK (not acknowledge - 1) by the receiver.
ACK means that it is ready to receive the data byte.
Operation Address Bits + Control (SLA+R/W)
SLA +W
Master writes data to SDA (sent to slave)
A6 A5 A4 A3 A2 A1 A0 0
SLA + R
Master reads from data from SDA (sent by slave)
A6 A5 A4 A3 A2 A1 A0 1
• The address packet is followed by one or more data packets which are also 9 bits long. The first 8 bits
are a byte of data to be transmitted, and the 9th bit is ACK/NACK.
• The transmission is finished by a STOP condition.
80
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
Other Registers
There are 2 other registers; TWAR (TWI Slave Address Register) and TWAMR – TWI (Slave) Address
Mask Register. These are used for programming ATmega328P as I2C slave. Since, we will be operating
out microcontroller in master mode, so these two will not be used. Refer to the datasheet for further
description.
void i2c_init(void)
{
TWSR=0x00; //set pre-scaler bits to zero
TWBR=0x62; // 75 kHz for XTAL=16MHz
TWCR=0x04; //enable the TWI module
}
82
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
void i2c_start(void)
{
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
while ((TWCR & (1 << TWINT)) == 0);
}
Receive Data
After transmitting SLA+R, the following steps are followed to receive data byte
1) Set the TWEN and TWINT bits of the TWCR register to one to start receiving a byte. To return ACK
after receiving data, the TWEA bit of the TWCR register is also set to one.
2) Poll the TWINT flag in the TWCR register to see whether a byte has been received completely.
3) Copy the received byte from the TWDR to another register to save it.
83
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
84
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
The slave address with control bit is sent after calling i2c_init( ) and i2c_start( ) sub-routines. After sending
the address byte, data byte is sent (0b00110011). This is received by the PCF8574 IC and given at output
through its output port (P7 to P0). The output drives 8 LEDs. Simulate the circuit to verify output and
understand connections. Note that the pull-up resistors are connected with SDA and SCL pins (as needed
for I2C interface). The resistors with LEDs are simply current limiting resistors.
With this module, pull-up resistors for SDA and SCL are not needed externally. The rest of the pins of
LCD for power supply and backlight LEDs are connected with PCF8574 power pins. The contrast control
pin is connected with on-board potentiometer. Some LCDs have this module already connected to them as
backpack since it is compatible with HD44780.
3. Toggle enable signal (send a pulse at enable to latch the data sent)
4. Mask higher 4-bits
5. Send to LCD port
6. Toggle enable signal (send a pulse at enable to latch the data sent)
Subroutines for LCD Control in 4-bit Mode through the I2C Interface
A few subroutines are created for initializing the LCD, sending data and commands, sending a pulse at
Enable pin, and for printing message strings on LCD in 4-bit mode. These sub-routines utilize the earlier
mentioned i2c_write( ) function repeatedly, since we are interfacing the LCD through I2C expander
module.
PCF8574 P7 P6 P5 P4 P3 P2 P1 P0
LCD D7 D6 D5 D4 - E R/W RS
Functions Data or command bits (4-bits at a time) - After 0: Write 0: Command
placing data, Mode Mode
a pulse is 1:Read 1: Data
sent to latch Mode Mode
The power pins of LCD and backlight are powered through expander module.
86
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
LAB TASKS
TASK 1: To interface LCD in 4-Bit Mode with ATmega328P through I2C Expander
1) Program Atmega328P for controlling 16x2 LCD screen in 4-bit mode using I2C interface. A sample
program is given at the end of this lab. This code uses the functions given in previous sections.
2) Make appropriate hardware connections of ATmega328P (TWI) with PCF8574 module. Connect the
module with 16x2 LCD screen.
3) Test your setup and observe output at LCD.
4) Modify the code to make the display blink with a certain delay. You can refer to the Lab 05 manual for
LCD related commands.
88
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
//I2C write (for sending address and data) void lcd_msg(char *c)
void i2c_write(char x) {
{ while(*c != 0) //Wait till all String are passed
TWDR = x; //Move value to I2C lcd_dwr(*c++); //----Send the String to LCD
TWCR = (1<<TWINT) | (1<<TWEN); }
//Enable I2C and clear interrupt
while (!(TWCR &(1<<TWINT))); int main (void)
}
{
//-----LCD 4-bit Mode functions using I2C-------//
i2c_init(); //initialize i2c
i2c_start(); // start i2c
void toggle() i2c_write(0x4E);
{ //01001110=4E
i2c_write((TWDR |= 0x04)); //(Device Address)
_delay_us(1); //Enable pulse lcd_init(); //initialize LCD
i2c_write((TWDR &= ~0x04));
float Percentage=75.5; //Message %
_delay_us(100); //make pulse longer or wait
char buffer_str[10]; //buffer
//for at least 100usec after sending each command
dtostrf(Percentage,5,1, buffer_str);
}
// converting float to string
void lcd_cmd(char v2)
{ lcd_cmd(0x80); //Cursor start of Line 1
i2c_write((TWDR&=~0x03)); lcd_msg("Expected ES Lab"); //Message
i2c_write((TWDR &= 0x0F)); lcd_cmd(0xC0); //Move cursor to Line 2
i2c_write((TWDR |= (v2 & 0xF0))); lcd_msg("Result ");
toggle(); lcd_msg(buffer_str);
lcd_msg("% :)");
i2c_write((TWDR &= 0x0F));
i2c_write((TWDR |= ((v2 & 0x0F)<<4))); while(1)
toggle(); {}
} }
89
Embedded Systems Lab Lab 09 AVR I2C Interface (TWI)
NED University of Engineering & Technology Electrical Engineering Department
90