0% found this document useful (0 votes)
44 views106 pages

MC&A Unit 4,5,6-5

The document provides an overview of serial communication in the 8051 microcontroller, highlighting the importance of serial communication due to limited GPIO pins and the need for fewer wires compared to parallel communication. It covers various serial communication protocols supported by the 8051, including UART, I2C, and SPI, along with key terminologies and configurations for setting up UART communication. Additionally, it explains the relevant registers and steps for configuring baud rates and enabling serial interrupts.

Uploaded by

sarthakvshukla6
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views106 pages

MC&A Unit 4,5,6-5

The document provides an overview of serial communication in the 8051 microcontroller, highlighting the importance of serial communication due to limited GPIO pins and the need for fewer wires compared to parallel communication. It covers various serial communication protocols supported by the 8051, including UART, I2C, and SPI, along with key terminologies and configurations for setting up UART communication. Additionally, it explains the relevant registers and steps for configuring baud rates and enabling serial interrupts.

Uploaded by

sarthakvshukla6
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 106

UNIT 4, 5 AND

6
Overview of Serial Communication in 8051
Why is serial communication important in microcontrollers?
Parallel vs Serial Communication
Types of Serial Communication in 8051
UART (Universal Asynchronous Receiver-Transmitter)
I2C (Inter-Integrated Circuit)
SPI (Serial Peripheral Interface)
Understanding Parallel vs. Serial Communication
Parallel Communication
Multiple data lines transmit data simultaneously.
Faster but requires more wires
Serial Communication in 8051 Microcontroller
Serial Communication
Data sent one bit at a time over a single wire.
Slower but longer distance and fewer connections.
Understanding Parallel vs. Serial Communication
Why do we need serial communication?
8051 uses limited GPIO pins.
Parallel communication needs too many wires.
Serial communication saves pins and allows long-distance transmission.
8051 supports multiple serial protocols.
UART (for PC interfaces, Bluetooth, GPS).
I2C (for sensors, EEPROMs, LCDs).
SPI (for high-speed devices like Flash memory and TFT displays).
Understanding Parallel vs. Serial Communication
Feature Serial Communication Parallel Communication

Definition Data is transmitted bit-by-bit over a single wire or pair of wires. Data is transmitted byte-by-byte using multiple wires.

Faster because multiple bits are transferred


Speed Slower than parallel due to sequential bit transfer.
simultaneously.

Requires more wires (typically 8, 16, or more data


Number of Wires Requires fewer wires (e.g., 2 wires in UART, I2C).
lines).

Transmission Distance Can be used for long-distance communication. Limited to short distances due to signal degradation.

Data Transfer Mode Bit-by-bit transfer (one bit at a time). Multiple bits transferred simultaneously.

Synchronization Requires clock synchronization in some cases (e.g., SPI, I2C). No need for additional clock synchronization.

Used in communication between microcontrollers, sensors, memory Used inside computers for CPU-RAM communication,
Applications
devices (UART, I2C, SPI, CAN, USB, RS-232). LCD interfacing, and buses like PCI, PCIe.

More prone to signal distortion and crosstalk due to


Data Integrity Less prone to crosstalk and interference.
multiple lines.

Cost & Complexity Lower cost due to fewer wires and simpler circuits. Higher cost due to multiple wires and complex wiring.

RAM, Address/Data Bus in Microprocessors, LCD


Examples UART, I2C, SPI, RS-232, USB, CAN
interface
Important Terminologies
Before diving into UART, I2C, and SPI, it's important to understand key terminologies used
in serial communication.
Baud Rate
Definition: The speed at which data is transmitted, measured in bits per second (bps).
Example: 9600 baud rate means 9600 bits are transmitted per second.
Higher baud rates = Faster communication but more chance of errors.
Bit vs. Byte vs. Frame
Bit: The smallest unit of data (0 or 1).
Byte: A group of 8 bits.
Frame: A complete unit of communication (Includes Start Bit, Data, Parity, Stop Bit).
Important Terminologies
Full Duplex, Half Duplex, and Simplex Communication

Type Description Example

Data flows both ways


Full Duplex UART, SPI, USB
simultaneously.

Data flows both ways but one at a


Half Duplex RS-485, some I2C cases
time.

Simplex Data flows in one direction only. Broadcasting (Radio, TV)


Important Terminologies
Asynchronous vs. Synchronous Communication

Type Description Example

No shared clock. Uses start/stop bits for


Asynchronous UART, RS-232
synchronization.

Shared clock signal synchronizes data


Synchronous I2C, SPI
transmission.

Example:
UART is asynchronous (data is framed with start and stop bits).
I2C and SPI are synchronous (clock signal ensures synchronized data transfer).
Important Terminologies
Parity Bit (Error Detection)
Definition: A single bit used for error detection.
Types:
Even Parity: The number of 1s in data + parity bit is even.
Odd Parity: The number of 1s in data + parity bit is odd.
Example:
Data = 1010 0001
Even Parity Bit = 1
Transmitted Data = 1010 0001 1
Important Terminologies
Stop & Start Bits
Start Bit: Indicates the beginning of a data frame (Always 0).
Stop Bit: Marks the end of a frame (1 or 2 bits long).
Used in: UART communication.
Example: Start (0) + Data (10101010) + Stop (1)
Important Terminologies
Acknowledgment (ACK/NACK)
Definition: A signal sent by the receiver to confirm data reception.
Used in: I2C protocol.
ACK (Acknowledge) → Receiver successfully received data (pulls SDA LOW).
NACK (Not Acknowledge) → Receiver did not receive data correctly (pulls SDA HIGH).
Important Terminologies
Master & Slave Devices
Master: Controls the communication (sends commands & clock signal).
Slave: Responds to the master.
Used in: I2C and SPI protocols.
Example:
I2C RTC Module (DS1307) as Slave, 8051 as Master.
SPI Flash Memory (Slave) controlled by 8051 (Master).
Important Terminologies
Transmission Modes: LSB vs. MSB First
LSB (Least Significant Bit) First: Transmits the lowest bit first. - Little Endian
MSB (Most Significant Bit) First: Transmits the highest bit first - Big Endian
Used in: SPI, I2C, UART depending on settings.
Example:
Data: 11010110
MSB First: 11010110
LSB First: 01101011
Two competing kingdoms, Lilliput and Blefuscu, have different customs for breaking eggs. The inhabitants of Lilliput break their eggs at the little
end and hence are known as little endians, while the inhabitants of Blefuscu break their eggs at the big end, and hence are known as big endians.
The novel is a parody reflecting the absurdity of war over meaningless issues. The terminology is fitting, as whether a CPU is big-endian or little-
endian is of little fundamental importance."
Important Terminologies
Pull-up and Pull-down Resistors
Definition: Resistors used to keep signals at a defined logic level.
Used in: I2C (SDA, SCL lines need pull-up resistors to work correctly).
Example: 4.7kΩ resistors used in I2C communication.
Important Terminologies
Buffer & FIFO (First In, First Out)
Buffer: A temporary storage for data before processing.
FIFO: A queue-based system where the first data received is the first processed.
Used in: UART for handling multiple incoming bytes.
Signal Integrity (Crosstalk & Noise)
Crosstalk: Unwanted signals caused by electromagnetic interference.
Noise: Random electrical disturbances affecting communication.
How to Reduce: Use shielded cables, proper grounding, pull-up resistors.
UART in 8051
Universal Asynchronous Receiver-Transmitter (UART)
Asynchronous Communication → No clock signal is shared.
Uses start and stop bits to frame the data.
Common in RS-232, GPS, Bluetooth.
8051 has one built-in UART module.
UART Communication Frame Format
UART Data Frame Structure:
Start Bit (1 bit)
Data Bits (5-8 bits)
Parity Bit (Optional)
Stop Bit (1-2 bits)
Example: 9600 baud rate, 8-N-1 format
8-bit data, No parity, 1 stop bit
8051 Serial Communication Registers
Registers in 8051 for Serial Communication:
SCON (Serial Control Register): Configures UART mode.
TMOD (Timer Mode Register): Configures Timer1 for baud rate generation.
TH1 (Timer 1 High Byte): Defines baud rate settings.
SCON (Serial Control Register) – Configures UART Mode
SCON (Serial Control Register) is an 8-bit register that controls the serial communication
mode, baud rate, and interrupt flags.

Bit Bit Name Description

7 SM0 Serial mode selection bit (Mode 0 to 3)

6 SM1 Serial mode selection bit (Used with SM0)

5 SM2 Enables multiprocessor communication

4 REN Receiver enable (1 = Enable, 0 = Disable)

3 TB8 Transmit 9th data bit (Only used in Mode 2 & 3)

2 RB8 Received 9th data bit (Only used in Mode 2 & 3)

1 TI Transmit interrupt flag (Set when transmission completes)

0 RI Receive interrupt flag (Set when data is received)


Understanding Each Bit in Detail
SM0 & SM1 (Serial Mode Selection Bits)
These two bits define the serial communication mode for UART in 8051.

Mode SM0 SM1 Baud Rate Data Format Application

Parallel communication
Mode 0 0 0 Fixed (Oscillator/12) 8-bit Shift Register
(Rarely used)

8-bit UART (Start & Stop


Mode 1 0 1 Variable (Set by Timer1) Standard UART mode
Bit)

Multiprocessor
Mode 2 1 0 Fixed (Oscillator/32 or /64) 9-bit UART
Communication

Mode 3 1 1 Variable (Set by Timer1) 9-bit UART Similar to Mode 2

Most common mode in 8051 UART is Mode 1 (SM0 = 0, SM1 = 1), which allows standard UART communication.
SM2 (Multiprocessor Mode Enable)
Used in Modes 2 & 3 only.
If SM2 = 1, the microcontroller will only receive data if the 9th bit (RB8) is 1.
This is useful in multiprocessor communication, where one device sends a special address byte to multiple
receivers.

If you're using simple UART communication, SM2 should be set to 0.


REN (Receiver Enable)
REN = 1 → Enables the UART receiver to receive data.
REN = 0 → Disables the receiver (Used to block unwanted data).
📌 If you want the 8051 to receive data, you must set REN = 1.
SCON = 0x50; // UART Mode 1, Receiver Enabled

TB8 (9th Data Bit for Transmission)

Used in Modes 2 & 3 for 9-bit data transfer.


In 8-bit UART (Mode 1), this bit is not used and should be ignored.
RB8 (9th Data Bit for Reception)
Used in Modes 2 & 3 for receiving 9-bit data.
In 8-bit UART (Mode 1), this bit is used to store the parity bit.

TI (Transmit Interrupt Flag)

This flag is set (TI = 1) when transmission is complete.


The microcontroller must clear TI manually after sending data.
void UART_Send(unsigned char data) {
SBUF = data; // Load data into UART buffer
while (TI == 0); // Wait for transmission to complete
TI = 0; // Clear the Transmit Interrupt flag
}
RI (Receive Interrupt Flag)
This flag is set (RI = 1) when data is received.
The microcontroller must clear RI manually after reading data.

unsigned char UART_Receive() {


while (RI == 0); // Wait until data is received
RI = 0; // Clear the Receive Interrupt flag
return SBUF; // Return the received byte
}
Example: Configuring UART for 9600 Baud Rate (Mode 1)
void UART_Init() {
SCON = 0x50; // Mode 1 (8-bit UART), Receiver Enabled
TMOD = 0x20; // Timer1 Mode 2 (8-bit auto-reload)
TH1 = 0xFD; // 9600 Baud Rate (for 11.0592 MHz crystal)
TR1 = 1; // Start Timer1
}
TMOD (Timer Mode Register) – Configures Timer1 for Baud Rate

In Mode 1 and Mode 3, the baud rate is generated using Timer1.


The Timer Mode Register (TMOD) is used to configure Timer1 in 8-bit auto-reload mode.
TMOD Register Format
Bit Position Bit Name Description

Bit 7 GATE1 1 → Timer1 starts only if INT1 (external pin) is HIGH. 0 → Timer1 starts when TR1 = 1 (software start).

Bit 6 C/T1 0 → Timer1 counts machine cycles (Timer mode). 1 → Timer1 counts external events from T1 pin (Counter mode).

Bit 5 M11 Used with M10 to select Timer1 mode.(See Timer Mode Selection Table Below).

Bit 4 M10 Used with M11 to select Timer1 mode.

Bit 3 GATE0 1 → Timer0 starts only if INT0 (external pin) is HIGH. 0 → Timer0 starts when TR0 = 1 (software start).

Bit 2 C/T0 0 → Timer0 counts machine cycles (Timer mode). 1 → Timer0 counts external events from T0 pin (Counter mode).

Bit 1 M01 Used with M00 to select Timer0 mode.(See Timer Mode Selection Table Below).

Bit 0 M00 Used with M01 to select Timer0 mode.


TH1 (Timer 1 High Byte) – Defines Baud Rate Settings

The TH1 register controls the baud rate in Mode 1 and Mode 3.Formula for Baud Rate
Calculation
The baud rate is determined using the following formula:

For 11.0592 MHz Crystal, the common baud rate settings are:

Baud Rate TH1 Value

9600 bps 0xFD

4800 bps 0xFA

2400 bps 0xF4

1200 bps 0xE8


Steps to Set Up UART in 8051
To configure serial communication (UART) in 8051, we follow four main steps:

Step Action Explanation

Timer1 is set in Mode 2 (Auto-reload) to generate a stable


1 Configure baud rate using Timer1
baud rate.

Defines the UART mode, enables receiver, and sets data


2 Set up the SCON (Serial Control) Register
format (8-bit, start/stop bits).

Allows automatic handling of UART events using the RI


3 Enable serial interrupts (Optional)
(Receive Interrupt) and TI (Transmit Interrupt) flags.

TI = 1 when transmission is complete, RI = 1 when data is


4 Use TI & RI flags for sending and receiving data
received.
Step 1: Configuring Baud Rate Using Timer1
The 8051 microcontroller does not have a dedicated baud rate generator.
Instead, it uses Timer1 in Mode 2 (Auto-reload Mode) to generate a stable baud rate for
UART.
For an 8051 running at 11.0592 MHz, we calculate TH1 values for common baud rates:

aud Rate TH1 Value

9600 bps 0xFD

4800 bps 0xFA

TMOD = 0x20; // Timer1 in Mode 2 (8-bit auto-reload)


TH1 = 0xFD; // Load Timer1 High Byte for 9600 baud rate
2400 bps 0xF4
TR1 = 1; // Start Timer1
Step 2: Configuring the SCON Register
Once the baud rate is set, we must configure the SCON (Serial Control Register) for UART
operation.

SCON = 0x50; // 8-bit UART Mode, Receiver Enabled

SM0 = 0, SM1 = 1 → UART Mode 1 (8-bit data, start & stop bit).
REN = 1 → Enables the receiver.
TI & RI → Flags for transmission & reception.
Step 3: Enabling Serial Interrupts (Optional)
If you want automatic UART handling, enable serial interrupts.

IE = 0x90; // Enable Serial Interrupt (ES = 1)

When data is received, the 8051 automatically triggers an interrupt.


You don’t need to manually check the RI flag.
Step 4: Sending and Receiving Data Using UART
Transmitting Data (Using TI Flag)
Steps:
1. Load data into the SBUF (Serial Buffer Register).
2. Wait for TI flag to become 1 (indicating data is sent).
3. Clear TI and send the next byte.

void UART_Send(unsigned char data) {


SBUF = data; // Load data into UART buffer
while (TI == 0); // Wait until transmission is complete
TI = 0; // Clear the Transmit Interrupt flag
}
TI (Transmit Interrupt Flag) is set when the byte is fully transmitted.
It must be cleared manually before sending the next byte.
Step 4: Sending and Receiving Data Using UART
Receiving Data (Using RI Flag)
Steps:
1. Wait for RI flag to become 1 (indicating data is received).
2. Read the data from SBUF.
3. Clear RI to receive the next byte.

unsigned char UART_Receive() {


while (RI == 0); // Wait until data is received
RI = 0; // Clear the Receive Interrupt flag
return SBUF; // Return the received byte
}
RI (Receive Interrupt Flag) is set when a byte is fully received.
It must be cleared manually before receiving the next byte.
Full Example: UART Communication in 8051
Here’s a complete 8051 UART program that:
1. Initializes UART for 9600 baud rate.
2. Sends and receives data continuously.
Full Example: UART Communication in 8051
#include <reg51.h> unsigned char UART_Receive() {
while (RI == 0); // Wait for data to be received
void UART_Init() { RI = 0; // Clear RI flag
TMOD = 0x20; // Timer1 in Mode 2 (Auto-reload)
return SBUF; // Return received byte
TH1 = 0xFD; // Load Timer1 High Byte for 9600 baud rate
}
TR1 = 1; // Start Timer1
SCON = 0x50; // 8-bit UART Mode, Receiver Enabled
void main() {
}
UART_Init(); // Initialize UART
while (1) {
void UART_Send(unsigned char data) {
UART_Send(UART_Receive()); // Echo
SBUF = data; // Load data into UART buffer
while (TI == 0); // Wait for transmission to complete received data back

TI = 0; // Clear TI flag }

} }

UART is initialized at 9600 baud.


Data received is immediately sent back (Echo program).
Works with PC HyperTerminal or PuTTY connected to 8051.
Full Example: UART Communication in 8051
TMOD

Bit 7 6 5 4 3 2 1 0

Name GATE1 C/T1 M1 (T1) M0 (T1) GATE0 C/T0 M1 (T0) M0 (T0)

Value 0 0 1 0 0 0 0 0

Bits 7-4 (0010) → Controls Timer1


GATE1 = 0 → Timer1 starts when TR1 = 1 (Software-controlled).
C/T1 = 0 → Timer1 runs in Timer Mode (Counts machine cycles, NOT external pulses).
M1 (T1) = 1, M0 (T1) = 0 → Mode 2 (8-bit Auto-reload Mode) for Timer1.
Bits 3-0 (0000) → Controls Timer0
GATE0 = 0, C/T0 = 0, M1 (T0) = 0, M0 (T0) = 0 → Timer0 remains in Mode 0 (13-bit Timer, not commonly used)

The value 0xFD (Hexadecimal) is chosen specifically to generate a 9600 baud rate when using an 11.0592 MHz crystal oscillator..

SCON Value Binary Representation Effect on UART

0x50 0101 0000 8-bit UART Mode, Receiver Enabled


Full Example: UART Communication in 8051
SCON Value Binary Representation Effect on UART

0x50 0101 0000 8-bit UART Mode, Receiver Enabled

8-bit UART (Standard


Bit Bit Name Value Effect Serial Communication)
1 Start Bit, 1 Stop Bit
Works with SM1 to select Mode
7 (SM0) Serial Mode Select Bit 0 0 Variable Baud Rate (Set
1
using Timer1)
6 (SM1) Serial Mode Select Bit 1 1 Mode 1 selected (8-bit UART)

Normal UART Mode


5 (SM2) Multiprocessor Mode Enable 0
(Multiprocessor Mode Disabled)

4 (REN) Receiver Enable 1 Enables Serial Data Reception

3 (TB8) 9th Bit for Transmission 0 Not used in 8-bit UART Mode

2 (RB8) 9th Bit for Reception 0 Not used in 8-bit UART Mode

1 (TI) Transmit Interrupt Flag 0 Cleared before transmission

0 (RI) Receive Interrupt Flag 0 Cleared before reception


Full Example: UART Communication in 8051

Step-by-step process showing the UART communication


process in 8051:
1. CPU loads data into SBUF (Serial Buffer Register).
2. UART transmits data byte-by-byte.
3. TI flag is set, indicating that transmission is complete.
4. CPU clears the TI flag before sending the next byte.
5. UART receives incoming data from an external device.
6. RI flag is set, signaling that new data has arrived.
7. CPU reads the received data from SBUF.
8. CPU clears the RI flag, preparing for the next byte.
Example 1: Sending a Single Character via UART (Assembly)

ORG 0000H ; Start program at address 0000H Sets up UART for 9600 baud.
Sends the letter 'A' continuously over the serial port.
SJMP MAIN ; Jump to main program

MAIN:
MOV TMOD, #20H ; Timer1 Mode 2 (Auto-reload)
MOV TH1, #0FDH ; Load TH1 for 9600 baud rate
MOV SCON, #50H ; Mode 1, 8-bit UART, Receiver Enabled
SETB TR1 ; Start Timer1

LOOP:
MOV SBUF, #'A' ; Load character 'A' into SBUF (Transmit)
JNB TI, $ ; Wait for TI flag (Transmission complete)
CLR TI ; Clear TI flag
SJMP LOOP ; Repeat forever

END
Example 2: Receiving a Single Character via UART (Assembly)

ORG 0000H Waits for data to be received.


Stores the received byte in register R0.
SJMP MAIN

MAIN:
MOV TMOD, #20H ; Timer1 Mode 2 (Auto-reload)
MOV TH1, #0FDH ; Load TH1 for 9600 baud rate
MOV SCON, #50H ; Mode 1, 8-bit UART, Receiver Enabled
SETB TR1 ; Start Timer1

LOOP:
JNB RI, LOOP ; Wait for RI flag (Data received)
CLR RI ; Clear RI flag
MOV R0, SBUF ; Store received data in R0
SJMP LOOP ; Keep waiting for new data

END
Example 3: UART Echo Program (Receives and Sends Back the Same Character)

#include <reg51.h>
unsigned char UART_ReceiveChar() {
while (RI == 0); // Wait until data is received
void UART_Init() {
RI = 0; // Clear RI flag
TMOD = 0x20; // Timer1 Mode 2 (Auto-reload)
return SBUF; // Return received byte
TH1 = 0xFD; // Load TH1 for 9600 baud rate
}
SCON = 0x50; // 8-bit UART Mode, Receiver Enabled
TR1 = 1; // Start Timer1
void UART_SendString(char *str) {
}
while (*str) { // Loop until end of string
UART_SendChar(*str);
void UART_SendChar(unsigned char data) { str++; // Move to next character
SBUF = data; // Load data into SBUF }
while (TI == 0); // Wait until transmission complete }
TI = 0; // Clear TI flag
} void main() {
UART_Init();

while (1) {
UART_SendString("Hello, UART!\r\n"); // Send a message
for (int i = 0; i < 30000; i++); // Simple delay
}
Introduction to I2C (Inter-Integrated Circuit)

I2C
Developed by Philips Electronics NV in the 80’s
Two-wire bus
Facilitates easy interconnection of ICs on boards
Reduces IC pin count and hence footprint
Reduces PCB trace count
Reduces EMI/RFI issues
Reduces cost
Simple to use
Introduction to I2C (Inter-Integrated Circuit)

Features
Single Master
Multiple Slaves
Devices can be added or removed without affecting any other
circuit in the system
Software addressable unique address for individual devices in
the network
Two wire system
System Clock (SCL) controlled by Master
System Data (SDA) transfer initiated by Master,
Bidirectional
Introduction to I2C (Inter-Integrated Circuit)

Features
Multiple Masters possible with Collision Detection and
Arbitration
Modular hardware architecture results in
Simpler fault diagnosis and debugging
Modular software development with reusable libraries
Extremely low power consumption
High noise immunity
Wide power supply range
Wide temperature range
Introduction to I2C (Inter-Integrated Circuit)
Terminology
Transmitter: Device that sends data to the bus
Receiver: Device that receives data from the bus
Master: Device that initiates a transfer, generates clock signals and terminates a transfer
Slave: Device addressed by a master
Multi-Master: More than one masters can attempt to control the bus at the same time
without corrupting the message
Arbitration: Procedure to ensure that, if more than one masters simultaneously try to
control the bus, only one is allowed to do so and the winning message is not corrupted
Synchronization: Procedure to synchronize the clock signals of two or more devices
Introduction to I2C (Inter-Integrated Circuit)
Technical Specifications
8-bit data transfer
Four modes of data transfer
Standard ( upto 10 Kbps)
Fast ( upto 1 Mbps)
Fast Plus (upto 3.4 Mbps)
High Speed
Bus Capacitive Load 400pF max
Rise Time
1000 nsec (Standard mode)
300 nsec (Fast mode)
Introduction to I2C (Inter-Integrated Circuit)
I2C is a two-wire, synchronous serial communication protocol used to connect multiple devices (slaves) to a single
microcontroller (master).

Key Features of I2C:


Uses only 2 wires:
SDA (Serial Data) → Transfers data.
SCL (Serial Clock) → Synchronizes data transfer.
Supports multiple masters and multiple slaves.
Each slave has a unique address (7-bit or 10-bit).
Speed:
Standard Mode → 100 kbps.
Fast Mode → 400 kbps.
High-Speed Mode → 3.4 Mbps.
Common I2C Devices:
EEPROM (24C02, 24C256)
Temperature Sensors (LM75, BMP280)
Real-Time Clocks (DS1307, DS3231)
OLED & LCD Displays
Introduction to I2C (Inter-Integrated Circuit)
Protocol
Both SCL and SDA are bidirectional
Both lines connected to positive power supply by current source or pull-up resistors
Both lines are HIGH when the bus is free
Data is valid on SDA when SCL is HIGH
Data can change when SCL is LOW
One Clock pulse generated for each data bit transferred
START CONDITION
STOP CONDITION
How I2C Works in 8051
Communication Structure
Master initiates communication by generating a Start Condition.
Sends Slave Address and Read/Write bit.
Slave Acknowledges by pulling SDA LOW (ACK).
Data is transferred (8 bits at a time).
Stop Condition is generated to end communication.

Step Action

1 Master sends Start Condition

2 Master sends Slave Address

3 Master sends Read/Write Bit

4 Slave Acknowledges (ACK)

5 Master sends/receives Data (8 bits)

6 Slave ACKs after each byte

7 Master sends Stop Condition


PROTOCOL
Master Transmitter Slave Receiver
Master Transmitter Slave Receiver
COMBINED
I2C in 8051

Since 8051 does not have hardware I2C support, we use bit-banging to manually control SDA (Serial Data) and SCL (Serial
Clock) lines.

//Start Condition
void I2C_Start() {
SDA = 1; // Ensure SDA is HIGH
SCL = 1; // Ensure SCL is HIGH
SDA = 0; // SDA goes LOW while SCL is HIGH (Start Condition)
SCL = 0; // Pull SCL LOW to begin communication
}
Generates the Start Condition required before sending data.
SDA transitions LOW while SCL remains HIGH.
I2C in 8051

//Stop Condition
void I2C_Stop() {
SDA = 0; // SDA goes LOW
SCL = 1; // SCL goes HIGH
SDA = 1; // SDA goes HIGH while SCL is HIGH (Stop Condition)
}
Ends the I2C communication session.
SDA transitions HIGH while SCL remains HIGH.
I2C in 8051

//Sending a Byte Over I2C


void I2C_Write(unsigned char data) {
for (int i = 0; i < 8; i++) {
SDA = (data & 0x80) >> 7; // Send MSB first
SCL = 1; // Generate clock pulse
SCL = 0;
data <<= 1; // Shift to the next bit
}
}

Sends data one bit at a time (MSB first).


SCL is toggled HIGH and LOW to synchronize data transfer.
I2C in 8051

//Receiving a Byte Over I2C


unsigned char I2C_Read() {
unsigned char data = 0;
SDA = 1; // Release SDA (Set as input)

for (int i = 0; i < 8; i++) {


SCL = 1; // Generate clock pulse
data = (data << 1) | SDA; // Read data bit
SCL = 0;
}
return data;
}

Reads data one bit at a time (MSB first).


SCL toggling ensures data is synchronized.
I2C in 8051

Sending Acknowledge (ACK)


void I2C_Ack() {
SDA = 0; // ACK (SDA LOW)
SCL = 1; // Generate clock pulse
SCL = 0;
}
Acknowledge (ACK) tells the slave that data was received successfully.
I2C in 8051

//Sending No Acknowledge (NACK)


void I2C_Nack() {
SDA = 1; // NACK (SDA HIGH)
SCL = 1; // Generate clock pulse
SCL = 0;
}
NACK tells the slave that no more data is expected.
Full SPI Master Code for 8051 in C (Bit-Banging)

#include <reg51.h> unsigned char I2C_Read() {


sbit SDA = P3^2; // I2C Data Line unsigned char data = 0;
sbit SCL = P3^3; // I2C Clock Line SDA = 1; // Set SDA as input
void I2C_Start() { for (int i = 0; i < 8; i++) {
SDA = 1; SCL = 1; SCL = 1;
SDA = 0; SCL = 0; // Start Condition data = (data << 1) | SDA; // Read bit
} SCL = 0;
void I2C_Stop() { }
SDA = 0; SCL = 1; return data;
SDA = 1; // Stop Condition }
} void main() {
void I2C_Write(unsigned char data) { I2C_Start(); // Generate Start Condition
for (int i = 0; i < 8; i++) { I2C_Write(0xA0); // Send EEPROM Address (Write Mode)
SDA = (data & 0x80) >> 7; // Send MSB first I2C_Write(0x00); // Send memory address
SCL = 1; // Clock pulse I2C_Write(0x55); // Write data (0x55)
SCL = 0; I2C_Stop(); // Generate Stop Condition
data <<= 1; while (1); // Infinite loop
}} }
This program writes a byte (0x55) to an EEPROM (24C02) at memory address 0x00.

Step 1: Sending the EEPROM Device Address (0xA0) Step 3: Sending the Data Byte (0x55)
I2C_Write(0xA0); I2C_Write(0x55);
EEPROM (e.g., 24C02) has a 7-bit address. 0x55 is the actual data being stored in the EEPROM.
The last bit (LSB) in 0xA0 is 0, meaning it is a "Write" The EEPROM writes this byte into the specified memory
operation. location (0x00).
The EEPROM listens for this address on the I2C bus.
If we wanted to READ from EEPROM, we would send 0xA1
(last bit set to 1).
Step 2: Sending the Memory Address (0x00)
I2C_Write(0x00);
EEPROM has many memory locations.
The master must tell the EEPROM which memory address it
wants to write to.
Here, 0x00 means "store the data in memory location 0x00".

Some EEPROMs (like 24C256) have 16-bit memory addressing,


meaning you must send two bytes (High Byte + Low Byte).
This program reads one byte from an EEPROM (e.g., 24C02, 24C256) at a specific
memory address (0x00) using bit-banging I2C on the 8051 microcontroller.

#include <reg51.h> void main() {


sbit SDA = P3^2; // SDA (I2C Data Line) unsigned char received_data;
sbit SCL = P3^3; // SCL (I2C Clock Line)
EEPROM_Write(0x00, 0xA0); // Write 0xA0 to memory
// Function Declarations address 0x00
void I2C_Start(); received_data = EEPROM_Read(0x00); // Read from memory
void I2C_Stop(); address 0x00
void I2C_Write(unsigned char);
unsigned char I2C_Read(); while (1); // Infinite loop
void I2C_Ack(); }
void I2C_Nack();
void EEPROM_Write(unsigned char, unsigned char);
unsigned char EEPROM_Read(unsigned char);
This program reads one byte from an EEPROM (e.g., 24C02, 24C256) at a specific
memory address (0x00) using bit-banging I2C on the 8051 microcontroller.

// ========================== // Send a Byte Over I2C


void I2C_Write(unsigned char data) {
// I2C Functions
for (int i = 0; i < 8; i++) {
// ========================== SDA = (data & 0x80) >> 7; // Extract MSB and send
SCL = 1; // Clock HIGH

// Generate I2C Start Condition SCL = 0; // Clock LOW


data <<= 1; // Shift left for next bit
void I2C_Start() {
}
SDA = 1; SCL = 1; }
SDA = 0; SCL = 0; // Start Condition
// Read a Byte Over I2C
}
unsigned char I2C_Read() {
unsigned char data = 0;
// Generate I2C Stop Condition SDA = 1; // Set SDA as input

void I2C_Stop() {
for (int i = 0; i < 8; i++) {
SDA = 0; SCL = 1;
SCL = 1; // Clock HIGH
SDA = 1; // Stop Condition data = (data << 1) | SDA; // Read SDA bit
} SCL = 0; // Clock LOW
}
return data;
}
Example: Sending 0xA5 = 10100101

Iteration data (binary) data & 0x80 SDA data <<= 1

1 10100101 10000000 1 01001010

2 01001010 00000000 0 10010100

3 10010100 10000000 1 00101000

4 00101000 00000000 0 01010000

5 01010000 00000000 0 10100000

6 10100000 10000000 1 01000000

7 01000000 00000000 0 10000000

8 10000000 10000000 1 Done


This program reads one byte from an EEPROM (e.g., 24C02, 24C256) at a specific
memory address (0x00) using bit-banging I2C on the 8051 microcontroller.

// Send Acknowledge (ACK) // ==========================


void I2C_Ack() { // EEPROM Read Function
SDA = 0; // ACK (SDA LOW)
// ==========================
SCL = 1; // Clock HIGH
unsigned char EEPROM_Read(unsigned char address) {
SCL = 0; // Clock LOW
unsigned char data;
}

// Send No Acknowledge (NACK) I2C_Start(); // Start Condition

void I2C_Nack() { I2C_Write(0xA0); // Send EEPROM Address (Write Mode)


SDA = 1; // NACK (SDA HIGH) I2C_Write(address); // Send Memory Address
SCL = 1; // Clock HIGH I2C_Start(); // Repeated Start Condition
SCL = 0; // Clock LOW
I2C_Write(0xA1); // Send EEPROM Address (Read Mode)
}
data = I2C_Read(); // Read Data from EEPROM
// ==========================
I2C_Nack(); // Send NACK (End of Read)
// EEPROM Write Function
I2C_Stop(); // Stop Condition
// ==========================
void EEPROM_Write(unsigned char address, unsigned char data) {
return data;
I2C_Start(); // Start Condition
}
I2C_Write(0xA0); // Send EEPROM Address (Write Mode)
I2C_Write(address); // Send Memory Address
I2C_Write(data); // Send Data Byte
I2C_Stop(); // Stop Condition
}
Serial Peripheral Interface (SPI)

Overview
Synchronous serial data link
Two data transfer lines
Master Out Slave In (MOSI)
Master In Slave Out (MISO)
Clock line synchronizes master as well as slave
Slave Chip Select line eliminates address transfer cycle
Serial Peripheral Interface (SPI)

Features
High speed data transfer (1 Mbps upto 50Mbps)
Full Duplex Communication
Each device on the bus acts simultaneously as a Transmitter
and a Receiver
Single Master and multiple slaves possible using multiple Chip
Select signals
Master device initiates data transfer
Master device generates clock and device select control
lines
Serial Peripheral Interface (SPI)
Serial Peripheral Interface (SPI)

Specifications
Eight or Sixteen bit data transfer
Date rates upto 1 Mbps for Master and 2 Mbps for Slave
Each transaction initiated by Master
Full Duplex data transfer possible
Clock Polarity (CPOL) configurable
CPOL = 0 → Clock is LOW when idle
CPOL = 1 → Clock is HIGH when idle
Idle means the state of the clock when the bus is not actively communicating.
Clock Phase (CPHA) configurable
CPHA = 0 → Data is sampled on first clock edge (after CS goes low)
CPHA = 1 → Data is sampled on second clock edge
This determines when the receiver reads the bit: Before or after the sender changes the
bit
Serial Peripheral Interface (SPI)

Protocol
Data transfer initiated by falling edge of SS
Data is only output during the rising or falling edge of SCK
Data is latched during the opposite edge of SCK
Opposite edge is used to ensure data is valid at the time of reading
Data is shifted MSB first
Data is transferred simultaneously on MOSI and MISO
Data transfer ended by rising edge of SS

Mode CPOL CPHA Data Sampled On

Mode 0 0 0 Rising edge

Mode 1 0 1 Falling edge

Mode 2 1 0 Falling edge

Mode 3 1 1 Rising edge


Serial Peripheral Interface (SPI)

Protocol
Data transfer for CPHA=0
Serial Peripheral Interface (SPI)

Protocol
•Data transfer for CPHA=1
Serial Peripheral Interface (SPI)

Application
Interfacing Peripherals such as
Analog to Digital Converters
Digital to Analog Converters
Real Time Clocks
LCD Modules
Sensors
Interfacing Memory such as
EEPROM
Flash Memory
Serial Peripheral Interface (SPI)

#include <reg51.h> data_in <<= 1;


if (MISO)
// Define SPI pins data_in |= 0x01; // Read MISO
sbit MOSI = P1^0; // Master Out Slave In
sbit MISO = P1^1; // Master In Slave Out SCK = 0; // Falling edge: slave changes data
sbit SCK = P1^2; // Serial Clock }
sbit SS = P1^3; // Slave Select (Active LOW) return data_in;
}
void SPI_Init() {
SS = 1; // Deselect slave void main() {
SCK = 0; // Idle state of clock (Mode 0) unsigned char received;
}
SPI_Init(); // Initialize SPI
// Send one byte via SPI and receive one byte in return SS = 0; // Select slave
unsigned char SPI_Transfer(unsigned char data_out) {
unsigned char i, data_in = 0; received = SPI_Transfer(0xA5); // Send 0xA5 and receive
response
for (i = 0; i < 8; i++) {
// Send MSB first SS = 1; // Deselect slave
MOSI = (data_out & 0x80) >> 7;
data_out <<= 1; while (1);
}
SCK = 1; // Rising edge: slave samples data
I2C based RTC

This program uses bit-banged I2C on 8051 to interface with


DS1307 RTC and:
Set time to a fixed value (e.g., 12:30:45)
Continuously read time (HH:MM:SS)

DS1307 Pin 8051 Pin Function

SDA P3.2 Data Line

SCL P3.3 Clock Line

VCC, GND 5V, GND Power supply

As per RTC module, e.g., battery backup pin connected


Others
to coin cell
RTC Internal Registers (all in BCD):

Address Function

0x00 Seconds

0x01 Minutes

0x02 Hours

0x03 Day (1–7)

0x04 Date (1–31)

0x05 Month (1–12)

0x06 Year (00–99)


8051 + DS1307 RTC Interface Code (I2C Bit-Banged)

#include <reg51.h> // I2C Stop Condition // Send NACK after Read


void I2C_Stop() {
SDA = 0; SCL = 1;
void I2C_Nack() {
// I2C Pin Definitions I2C_Delay(); SDA = 1; SCL = 1; I2C_Delay(); SCL = 0;
SDA = 1; }
sbit SDA = P3^2; // Data Line I2C_Delay();
sbit SCL = P3^3; // Clock Line }
// Convert decimal to BCD
// I2C Write Byte unsigned char DecimalToBCD(unsigned char dec) {
// Delay for I2C timing (adjust if needed) void I2C_Write(unsigned char dat) {
return ((dec / 10) << 4) | (dec % 10);
for (int i = 0; i < 8; i++) {
void I2C_Delay() { SDA = (dat & 0x80) >> 7; }
unsigned int i; SCL = 1; I2C_Delay();
SCL = 0; I2C_Delay();
for (i = 0; i < 200; i++); dat <<= 1; // Convert BCD to decimal
} } unsigned char BCDToDecimal(unsigned char bcd) {
return ((bcd >> 4) * 10) + (bcd & 0x0F);
// Skip ACK check for simplicity
}
// I2C Start Condition SDA = 1; SCL = 1; I2C_Delay(); SCL = 0;
}
void I2C_Start() {
// Write to RTC Register
SDA = 1; SCL = 1; // I2C Read Byte
void RTC_Write(unsigned char reg, unsigned char value) {
unsigned char I2C_Read() {
I2C_Delay(); unsigned char i, dat = 0; I2C_Start();
SDA = 0; SDA = 1; // Release SDA for input
I2C_Write(0xD0); // DS1307 I2C address (Write)
I2C_Delay(); for (i = 0; i < 8; i++) { I2C_Write(reg); // Register address
SCL = 0; dat <<= 1; I2C_Write(value); // Data
SCL = 1; I2C_Delay();
} I2C_Stop();
if (SDA) dat |= 1;
SCL = 0; I2C_Delay(); }
}
return dat;
}
8051 + DS1307 RTC Interface Code (I2C Bit-Banged)

// Read from RTC Register void main() {


unsigned char RTC_Read(unsigned char reg) { unsigned char h, m, s;
unsigned char value;
// Set initial time: 12:30:45 (in BCD)
I2C_Start();
RTC_Write(0x00, DecimalToBCD(45)); // Seconds
I2C_Write(0xD0); // Write mode
RTC_Write(0x01, DecimalToBCD(30)); // Minutes
I2C_Write(reg); RTC_Write(0x02, DecimalToBCD(12)); // Hours (24-hour
I2C_Start(); format)
I2C_Write(0xD1); // Read mode
value = I2C_Read(); while (1) {
I2C_Nack(); s = BCDToDecimal(RTC_Read(0x00));
I2C_Stop(); m = BCDToDecimal(RTC_Read(0x01));
return value; h = BCDToDecimal(RTC_Read(0x02));

}
// At this point, h, m, s contain current time in decimal
// You can send to UART or display on LCD
I2C_Delay(); // Wait before next read
}
}
Explanation

Section 1: I2C Pin Setup

sbit SDA = P3^2; // SDA = Serial Data Line


sbit SCL = P3^3; // SCL = Serial Clock Line

We choose Port 3.2 for SDA and Port 3.3 for SCL because 8051 doesn’t have built-in I2C. So we simulate I2C using these GPIO pins.

Section 2: Delay Function

void I2C_Delay() {
unsigned int i;
for (i = 0; i < 200; i++);
}

This is a simple delay loop to control the speed of the I2C communication. It gives time for the devices to set or read signals properly.
Explanation

Section 3: Basic I2C Signal Functions Section 4: Sending and Receiving Bytes on I2C

void I2C_Start() { void I2C_Write(unsigned char dat) {


SDA = 1; SCL = 1; for (int i = 0; i < 8; i++) {
I2C_Delay(); SDA = (dat & 0x80) >> 7;
SDA = 0; SCL = 1; I2C_Delay();
I2C_Delay(); SCL = 0; I2C_Delay();
SCL = 0; dat <<= 1;
} }

Tells the RTC, "Hey, I’m starting communication!" SDA = 1; SCL = 1; I2C_Delay(); SCL = 0;
This is how I2C always begins a message. }

void I2C_Stop() {
SDA = 0; SCL = 1; Explanation:
I2C_Delay(); Sends 8 bits of data, one bit at a time
SDA = 1; MSB is sent first
I2C_Delay(); Clock is pulsed to sync the data with RTC
} After sending, we release SDA for the RTC to acknowledge

Tells the RTC, "I’m done sending data. You can rest now."
Explanation

Read a Byte Send NACK


unsigned char I2C_Read() { void I2C_Nack() {
unsigned char i, dat = 0; SDA = 1; SCL = 1; I2C_Delay(); SCL = 0;
SDA = 1; }

for (i = 0; i < 8; i++) { }


dat <<= 1;
SCL = 1; I2C_Delay(); Tells RTC, "I’m done reading, no more data needed."
if (SDA) dat |= 1;
SCL = 0; I2C_Delay();
}
return dat;
}

Explanation:
Receives 8 bits from RTC
Bits are stored one by one into a byte
Used to read time registers (seconds, minutes, etc.)
Explanation

What is BCD? bcd = 0x29;

BCD stands for Binary Coded Decimal.


It is a way of storing decimal numbers in binary form, where each (bcd >> 4) = 0x2 = 2
digit of a decimal number is stored separately using 4 bits. (bcd & 0x0F) = 0x9 = 9

Decimal 45 → stored in BCD as: 0x45


(that means: 4 is 0100, 5 is 0101)
Decimal = 2 * 10 + 9 = 29
Why Do We Use BCD?
Many devices like the DS1307 RTC store time data in BCD format,
not regular binary.
This makes it easier to display digits directly on LCDs or 7-
segment displays. Operation What it does
But to use it in calculations or print it as decimal, we need to
convert BCD → Decimal. bcd >> 4 Gets the upper nibble (tens digit)

* 10 Converts tens to proper value

bcd & 0x0F Gets the lower nibble (units digit)

+ Adds tens + units = final decimal number


Explanation

Section 5: BCD Conversions Section 6: RTC Read/Write Functions


DS1307 stores data in BCD (Binary Coded Decimal), not in Write to the RTC Register
normal decimal or binary. void RTC_Write(unsigned char reg, unsigned char value) {
I2C_Start();
Convert Decimal to BCD I2C_Write(0xD0); // DS1307 Write Address
I2C_Write(reg); // Target Register
unsigned char DecimalToBCD(unsigned char dec) { I2C_Write(value); // Data to store
return ((dec / 10) << 4) | (dec % 10); I2C_Stop();
} }

Convert BCD to Decimal This is the slave address of the DS1307 RTC in write mode.
unsigned char BCDToDecimal(unsigned char bcd) { The 7-bit base address of DS1307 is 0x68 → binary 1101000
return ((bcd >> 4) * 10) + (bcd & 0x0F); Adding the write bit (0) at the end → becomes 11010000 = 0xD0
} You are telling DS1307:
"I'm going to start writing at register 0x00 (which is seconds
Example: register)"
Decimal 45 → BCD = 0x45
BCD 0x45 → Decimal = 45
Explanation

Read from RTC Register Section 7: Main Program Logic


unsigned char RTC_Read(unsigned char reg) {
unsigned char value; void main() {
I2C_Start(); unsigned char h, m, s;
I2C_Write(0xD0); // Write to set address
I2C_Write(reg); // Set initial time
I2C_Start(); RTC_Write(0x00, DecimalToBCD(45)); // seconds
I2C_Write(0xD1); // Read mode RTC_Write(0x01, DecimalToBCD(30)); // minutes
value = I2C_Read(); RTC_Write(0x02, DecimalToBCD(12)); // hours
I2C_Nack();
I2C_Stop(); while (1) {
return value; s = BCDToDecimal(RTC_Read(0x00));
} m = BCDToDecimal(RTC_Read(0x01));
h = BCDToDecimal(RTC_Read(0x02));

// Now h, m, s have the real time in decimal


// You can display them on LCD or send via UART

I2C_Delay(); // Small delay between reads


}
}
Keypad 4x4

Project Overview 2. Inside main()


Hardware: 8051 Microcontroller, 4x4 Keypad, 7-Segment P0 = 0x00; // 7-segment data lines (not focused now)
Display P1 = 0xFF; // Transistor lines for display
Goal: When a key is pressed, display the corresponding value P2 = 0x0F; // Rows = outputs (low), Columns = inputs (high)
(0–9, A–F) on the 7-segment display.
P0 = 0x00: This port sends data to the 7-segment display.
P1 = 0xFF: Activates the transistor to enable the display.
sbit R1 = P2^0; P2 = 0x0F: the rows (R1–R4) are acting as inputs, and the
sbit R2 = P2^1; columns (C1–C4) are acting as outputs
sbit R3 = P2^2;
sbit R4 = P2^3;
sbit C1 = P2^4;
sbit C2 = P2^5;
sbit C3 = P2^6;
sbit C4 = P2^7;

Port 2 (P2) is connected to the keypad.


R1–R4 (P2.0–P2.3): Rows of keypad (outputs)
C1–C4 (P2.4–P2.7): Columns of keypad (inputs)
Keypad 4x4

3. Infinite Loop to Continuously Check for Key Presses 4. Column Scanning + Row Checking
while (1) { Now the program scans each column one by one and checks
while(P2 == 0x0F) { which row went LOW.
P1 = 0xFF; // Wait here if no key is pressed (all columns HIGH)
} Scanning Column 1

The inner while loop waits until a key press is detected.


P2 == 0x0F means all columns are HIGH → no key pressed. C1 = 0; C2 = C3 = C4 = 1;
if(R1 == 0){P0=0x8E;} // F
if(R2 == 0){P0=0x83;} // E
if(R3 == 0){P0=0xF8;} // D
if(R4 == 0){P0=0xB0;} // C

Makes only C1 LOW and checks all rows.


If R3 == 0, then key ‘D’ (Row 3, Col 1) was pressed.
Sends 0xF8 to P0, which lights up the display to show ‘D’.
Keypad 4x4

Column 2

C2 = 0; C1 = C3 = C4 = 1;
if(R1 == 0){P0=0x86;} // B
if(R2 == 0){P0=0x88;} // A
if(R3 == 0){P0=0x82;} // 9
if(R4 == 0){P0=0xA4;} // 8

Column 3

C3 = 0; C1 = C2 = C4 = 1;
if(R1 == 0){P0=0xA1;} // 7
if(R2 == 0){P0=0x90;} // 6
if(R3 == 0){P0=0x92;} // 5
if(R4 == 0){P0=0xF9;} // 4

Column 4

C4 = 0; C1 = C2 = C3 = 1;
if(R1 == 0){P0=0xC6;} // 3
if(R2 == 0){P0=0x80;} // 2
if(R3 == 0){P0=0x99;} // 1
if(R4 == 0){P0=0xC0;} // 0
Keypad 4x4

5. What Happens Internally When a Key is Pressed?

Let’s say key "9" is pressed:


It's at R3, C2
When C2 is pulled LOW, and R3 reads LOW, the program
detects key '9'
It sends P0 = 0x82 → this value lights up the 7-segment
display to show “9”
Watchdog Timer

A Watchdog Timer is like a digital supervisor for your microcontroller. Its main
job is to reset the system if the program gets stuck or doesn’t behave as
expected.

Why is it needed?
Sometimes, due to bugs, unexpected inputs, or hardware glitches, the
microcontroller might get stuck in a loop or crash. The WDT helps recover by
automatically resetting the system and starting fresh.
Watchdog Timer

How it works:

The Watchdog Timer is like a countdown timer.


Your program must regularly reset (“kick” or “feed”) the timer to show it’s
running fine.
If the WDT is not reset within a specified time, it assumes something went
wrong and resets the microcontroller.
Example Scenario:

You enable the WDT with a timeout of 2 seconds.


In your main loop, you reset the WDT every second.
If the code hangs (maybe due to infinite loop or crash) and fails to reset the
WDT in time, the WDT will trigger a system reset.
Watchdog Timer

8051 and Watchdog Timer


The standard 8051 does not have a built-in Watchdog Timer.
But many 8051 derivatives (like Atmel AT89C51 or Dallas DS89C450) include a
WDT.
You enable it using a special function register (SFR) and control the timeout
and reset behavior.

void main() {
WDTCON = 0x01; // Enable Watchdog Timer
while (1) {
// Main code
WDT_reset(); // Reset the WDT regularly
}
}
DC Motor
A DC (Direct Current) motor converts electrical
energy into mechanical energy using direct
current. It works on the principle that a current-
carrying conductor placed in a magnetic field
experiences a force (Lorentz Force).
Working:
It consists of a stator (stationary part with
magnets) and a rotor (rotating coil/armature).
When DC voltage is applied, current flows
through the armature winding.
Magnetic interaction between the stator field
and the armature current creates torque,
causing the rotor to rotate.
DC Motor
Controlling a DC Motor
1. Using Relay (ON/OFF control): P2 = 0x0A; // Motor rotates forward (IN1=1, IN2=0, EN=1)

A simple relay circuit can switch the motor


ON or OFF using a microcontroller.
Used for unidirectional control only.
2. Using Transistor/MOSFET:
Acts as a switch controlled by a
microcontroller GPIO.
PWM (Pulse Width Modulation) can control
speed.
3. Using H-Bridge (like L293D or L298N):
Enables forward and reverse rotation.
PWM input to the EN (enable) pin controls
speed.
Direction controlled by logic on input pins.
Interface a DC motor with the 8051 microcontroller
Components Needed:
8051 Microcontroller
L293D Motor Driver IC (or L298N)
DC Motor
Power supply (e.g. 5V or 12V for motor)
Wires, breadboard

8051 Pin L293D Pin Purpose Connection Description

HIGH = forward, LOW = reverse (with IN2 =


P2.0 IN1 (pin 2) Control motor direction (input 1)
LOW)

HIGH = reverse, LOW = forward (with IN1 =


P2.1 IN2 (pin 7) Control motor direction (input 2)
LOW)

Connect to Vcc for always ON, or to PWM pin


(optional PWM pin) EN1 (pin 1) Enable motor & speed control
for speed

– OUT1 (pin 3) Output to Motor Terminal A Connect to one motor terminal

– OUT2 (pin 6) Output to Motor Terminal B Connect to the other motor terminal

– Vcc1 (pin 16) L293D logic power (5V) Connect to 5V supply

– Vcc2 (pin 8) Motor supply (9–12V) Connect to external power for motor

Common ground with microcontroller and


– GND (pins 4, 5, 12, 13) Ground
motor supply
Interface a DC motor with the 8051 microcontroller
Interface a DC motor with the 8051 microcontroller
#include <reg51.h>
void main() {
while(1) {
// Define control pins
// Rotate motor forward
sbit IN1 = P2^0; // Motor control input 1
IN1 = 1;
sbit IN2 = P2^1; // Motor control input 2
IN2 = 0;
delay_ms(3000); // Run motor for 3 seconds
void delay_ms(unsigned int ms) {
unsigned int i, j;
// Stop
for(i = 0; i < ms; i++)
IN1 = 0;
for(j = 0; j < 1275; j++); // Roughly 1ms delay
IN2 = 0;
}
delay_ms(1000);

// Rotate motor reverse


IN1 = 0;
IN2 = 1;
delay_ms(3000);
You can use PWM on the
Enable pin (EN1) to control // Stop
speed. IN1 = 0;
Always connect a flyback IN2 = 0;
delay_ms(1000);
diode across motor terminals
}
if not using L293D, to protect }
from back EMF.
Interface a DC motor with the 8051 microcontroller
Motor rotates forward for 3 seconds, void main() {
Then stops for 1 second, while (1) {
// Forward rotation
Then reverses for 3 seconds,
IN1 = 1;
And repeats... IN2 = 0;
delay_ms(3000);

// Stop
IN1 = 0;
IN2 = 0;
#include <reg51.h> delay_ms(1000);

// Define motor control pins // Reverse rotation


sbit IN1 = P1^0; // Connected to L293D IN1 IN1 = 0;
sbit IN2 = P1^1; // Connected to L293D IN2 IN2 = 1;
delay_ms(3000);
// Delay function (approx 1 ms per unit)
void delay_ms(unsigned int ms) { // Stop
unsigned int i, j; IN1 = 0;
for (i = 0; i < ms; i++) IN2 = 0;
for (j = 0; j < 1275; j++); // calibrated for delay_ms(1000);
11.0592MHz }
} }
Stepper Motor
What is a Stepper Motor?
A stepper motor is an electromechanical device that converts electrical pulses
into discrete mechanical movements. Unlike a DC motor that spins
continuously, a stepper motor rotates in fixed angular steps, hence the name.

Basic Principle:
A magnetic rotor (shaft) moves when electromagnets (stator coils) are
energized in a specific sequence.
Each pulse sent to the motor causes the rotor to move by one step.
Stepper motors don’t need feedback for position — they are open-loop
controlled.
Working of a Stepper Motor (Unipolar Example):
Let’s take a 4-phase unipolar stepper motor with 4 windings: A, B, C, D.

Step A B C D Direction

1 1 0 0 0 Step 1

2 0 1 0 0 Step 2

Apply this sequence in a loop,


and the motor shaft rotates
3 0 0 1 0 Step 3
step-by-step.

Energize two adjacent coils at once


between steps. This gives double the
4 0 0 0 1 Step 4 resolution and smoother rotation.
Working of a Stepper Motor (Unipolar Example):
Step Angle Formula:

For a 1.8° step angle → 200 steps/rev.

Applications:
Printers
CNC machines
3D printers
Robotics
Cameras (pan/tilt)
Interfacing with 8051:
You can use ULN2003 or L293D as driver IC to interface a stepper motor with 8051.

Microcontroller Driver IC Motor Windings

P1.0 IN1 A

P1.1 IN2 B

P1.2 IN3 C

P1.3 IN4 D
Interfacing with 8051:
#include <reg51.h> while(1) {
// Rotate 50 steps clockwise
void delay_ms(unsigned int ms) { for(i = 0; i < 50; i++) {
unsigned int i, j; P1 = step_sequence[i % 4]; // output step pattern to motor
for(i = 0; i < ms; i++) delay_ms(20); // delay between steps
for(j = 0; j < 1275; j++); // ~1ms delay }
} // Stop for 1 second
P1 = 0x00;
void main() { delay_ms(1000);
// Full-step sequence for clockwise // Rotate 50 steps counter-clockwise
rotation for(i = 0; i < 50; i++) {
unsigned char step_sequence[] = {0x01, P1 = step_sequence[3 - (i % 4)];
0x02, 0x04, 0x08}; // A, B, C, D delay_ms(20);
unsigned int i; }
// Stop for 1 second
P1 = 0x00;
delay_ms(1000);
}
}
Explanation
unsigned char step_sequence[] = {0x01, 0x02, 0x04, 0x08}; // A, B, C, D // Rotate 50 steps counter-clockwise
for(i = 0; i < 50; i++) {
Each value represents which coil to energize: P1 = step_sequence[3 - (i % 4)];
0x01 = 00000001 → Coil A (P1.0 ON) delay_ms(20);
0x02 = 00000010 → Coil B (P1.1 ON) }
0x04 = 00000100 → Coil C (P1.2 ON)
0x08 = 00001000 → Coil D (P1.3 ON) Same loop as before but in reverse by using 3 - (i % 4):
This is for full-step drive (one coil at a time). Outputs sequence in this order: D → C → B → A
(opposite of before).
This makes the motor rotate in reverse direction.
i i%4 Meaning (step index)

0 0 step 0

1 1 step 1

2 2 step 2

3 3 step 3

4 0 step 0 (repeats)

You might also like