8051
I/O Port programming
Unit II
Microcontroller Peripheral Modules: Programming 8051 I/O port, I/O
interfacing examples using C programs (LED, Switch and Seven segment LED
using multiplexing technique), 8051 Timers/Counters in Mode1 & Mode 2, Timer
Programming examples using C, Serial Communication, Example C programs on
serial communication and External Interrupts, timer interrupts and serial
communication interrupts with example programs. I2C and SPI communication
protocols 12 Hours
Port 0
• It can be used for input or output, each pin must be
connected externally to a 10K ohm pull-up resistor
• This is due to the fact that P0 is an open drain, unlike
P1, P2, and P3.
• The four 8-bit I/O ports P0, P1, P2 and P3 each uses 8
pins.
• All the ports upon RESET are configured as input,
ready to be used as input ports.
• When the first 0 is written to a port, it becomes an
output.
• To reconfigure it as an input, a 1 must be sent to the
port.
• To use any of these ports as an input port, it must be
programmed.
• Port 0 is configured first as an input port by writing 1s
to it, and then data is received from that port and sent
to P1.
• MOV A,#0FFH ;A=FF hex
• MOV P0,A ;make P0 an i/p port by writing it all 1s
• BACK: MOV A,P0 ;get data from P0
• MOV P1,A ;send it to port 1
• SJMP BACK
• Port 0 is also designated as AD0-AD7, allowing it to
be used for both address and data.
Port 1
• Port 1 can be used as input or output.
• In contrast to port 0, this port does not need any pull-
up resistors since it already has pull-up resistors
internally.
• Upon reset, port 1 is configured as an input port.
• To make port 1 an input port, it must be programmed
as such by writing 1 to all its bits.
Port 2
• Port 2 can be used as input or output Just like P1,
port 2 does not need any pullup resistors since it
already has pull-up resistors internally.
• Upon reset, port 2 is configured as an input port.
• To make port 2 an input port, it must be programmed
as such by writing 1 to all its bits.
• Port 2 is also designated as A8 – A15, indicating its
dual function.
Port 3
• Port 3 can be used as input or output.
• Port 3 does not need any pull-up resistors.
• Port 3 is configured as an input port upon reset.
• Port 3 has the additional function of providing some
extremely important signals.
• If you want to read in from a pin, you must first give a
logic ‘1’ to the port latch to turn off the FET otherwise
the data read in will always be logic ‘0’.
• When you write to the port you are actually writing to
the latch e.g. a logic 0 given to the latch will be
inverted and turn on the FET which cause the port pin
to be connected to ground (logic 0).
• If a logic 1 given to the latch will be inverted and
turns off the FET which cause the port pin to be float.
We require external pull up in case of port0, other
ports have internal pull up to make port written to
logic1.
I/O Port and bit addressability
• A powerful feature of 8051 I/O port is their capability
to access individual bit of the port without altering
rest of the bits.
• Eg:
• CPL P1.2
• SETB P1.2
Why Program 8051 in C
• Compilers produce hex files that is downloaded to ROM of
microcontroller
• The size of hex file is the main concern
• Microcontrollers have limited on-chip ROM
• Code space for 8051 is limited to 64K bytes
• C programming is less time consuming, but has larger hex file
size
The reasons for writing programs in C
• It is easier and less time consuming to write in C than
Assembly
• C is easier to modify and update
• You can use code available in function libraries
• C code is portable to other microcontroller with little of no
modification
• A good understanding of C data types for 8051 can help
programmers to create smaller hex files
• Unsigned char
• Signed char
• Unsigned int
• Signed int
• Sbit (single bit)
• Bit and sfr
Unsigned char
The character data type is the most natural choice
• 8051 is an 8-bit microcontroller
Unsigned char is an 8-bit data type in the range of 0 – 255
(00 – FFH)
• One of the most widely used data types for the 8051
Counter value
ASCII characters
• C compilers use the signed char as the default if we do
not put the keyword unsigned
Write an 8051 C program to send values 00 – FF to port P1.
Solution:
#include <reg51.h>
void main(void)
{
unsigned char z;
for (z=0;z<=255;z++)
P1=z;
}
Write an 8051 C program to send hex values for ASCII characters
of 0, 1, 2, 3, 4, 5, A, B, C, and D to port P1.
Solution:
#include <reg51.h>
void main(void)
{
unsigned char mynum[]=“012345ABCD”;
unsigned char z;
for (z=0;z<=10;z++)
P1=mynum[z];
}
Write an 8051 C program to toggle all the bits of P1 continuously.
Solution:
//Toggle P1 forever
#include <reg51.h>
void main(void)
{
for (;;)
{
P1=0x55;
P1=0xAA;
}
}
Unsigned int
The unsigned int is a 16-bit data type takes a value in the
range of 0 to 65535 (0000 – FFFFH)
• Define 16-bit variables such as memory addresses
• Set counter values of more than 256
• Since registers and memory accesses are in 8-bit chunks,
the misuse of int variables will result in a larger hex file
Write an 8051 C program to toggle bit D0 of the port P1 (P1.0)
50,000 times.
Solution:
#include <reg51.h>
sbit MYBIT=P1^0;
void main(void)
{
unsigned int z;
for (z=0;z<=50000;z++)
{
MYBIT=0;
MYBIT=1;
}
}
Bit and sfr
The bit data type allows access to single bits of bit-addressable
memory spaces 20 – 2FH.
To access the byte-size SFR registers, we use the sfr data type.
Time delay
There are two way s to create a time delay in 8051 C
• Using the 8051 timer
• Using a simple for loop
be mindful of three factors that can affect the accuracy of the delay
1) The 8051 design
– The number of machine cycle
– The number of clock periods per machine cycle
2) The crystal frequency connected to the X1 – X2 input pins
3) Compiler choice
– C compiler converts the C statements and functions to Assembly
language instructions
– Different compilers produce different code
Delay calculation
Cx12
Tinst =
frequency=11.0592 M HZ
Frequency/12=11.0592MHz/12 = 921.6KHz
• T = 1/f
• so time period of one machine cycle = 1/ 921.6KHz = 1.085us
now when u run loop of 1275..
• delay would be 1275×1.085us = 1.3ms
• 1275 times of “for” loop gives nearly 1ms of delay.
Write an 8051 C program to toggle bits of P1 continuously forever
with some delay.
Solution:
//Toggle P1 forever with some delay in between
//“on” and “off”
#include <reg51.h>
void main(void)
{
unsigned int x;
for (;;) //repeat forever
{
P1=0x55;
for (x=0;x<40000;x++); //delay size
//unknown
P1=0xAA;
for (x=0;x<40000;x++);
}
}
Write an 8051 C program to toggle bits of P1 ports continuously with
a 250 ms.
Solution:
#include <reg51.h>
void MSDelay(unsigned int);
void main(void)
{
while (1) //repeat forever
{
P1=0x55;
MSDelay(250);
P1=0xAA;
MSDelay(250);
}
}
void MSDelay(unsigned int itime)
{
unsigned int i,j;
for (i=0;i<itime;i++)
for (j=0;j<1275;j++);
}
Write an 8051 C program to toggle only bit P2.4 continuously
without disturbing the rest of the bits of P2.
Solution:
//Toggling an individual bit
#include <reg51.h>
sbit mybit=P2^4;
void main(void)
{
while (1)
{
mybit=1; //turn on P2.4
mybit=0; //turn off P2.4
}
}
Write an 8051 C program to monitor bit P1.5. If it is high, send 55H
to P0; otherwise, send AAH to P2.
Solution:
#include <reg51.h>
sbit mybit=P1^5;
void main(void)
{
mybit=1; //make mybit an input
while (1)
{
if (mybit==1)
P0=0x55;
else
P2=0xAA;
}
}
A door sensor is connected to the P1.1 pin, and a buzzer is connected to P1.7. Write an 8051 C
program to monitor the door sensor, and when it opens, sound the buzzer. You can sound the
buzzer by sending a square wave of a few hundred Hz.
Solution:
#include <reg51.h>
void MSDelay(unsigned int);
sbit Dsensor=P1^1;
sbit Buzzer=P1^7;
void main(void)
{
Dsensor=1; //make P1.1 an input
while (1)
{
while (Dsensor==1)//while it opens
{
Buzzer=0;
MSDelay(200);
Buzzer=1;
MSDelay(200);
}
}
}
void MSDelay(unsigned int itime)
{
unsigned int i,j;
for (i=0;i<itime;i++)
for (j=0;j<1275;j++);
}
I/O Port and bit addressability
• Write the following programs.
• Create a square wave of 50% duty cycle on bit 0 of
port 1.
• SOLUTION:
• The 50% duty cycle means that the “on” and “off” state (or the high and low portion of
the pulse) have the same length. Therefore, we toggle P1.0 with a time delay in
between each state.
#include <reg51.h>
void MSDelay(unsigned int);
sbit mybit=P1^1;
void main(void)
{
while (1)
{
mybit=0;
MSDelay(200);
mybit=1;
MSDelay(200);
}
}
void MSDelay(unsigned int itime)
{
unsigned int i,j;
for (i=0;i<itime;i++)
for (j=0;j<1275;j++);
}
• Create a square wave of 66% duty cycle on bit P1.3.
• Solution:
• 66% indicates Ton=2Toff
#include <reg51.h>
void MSDelay(unsigned int);
sbit mybit=P1^3;
void main(void)
{
while (1)
{
mybit=0;
MSDelay(200);
mybit=1;
MSDelay(200);
MSDelay(200);
}
}
void MSDelay(unsigned int itime)
{
unsigned int i,j;
for (i=0;i<itime;i++)
for (j=0;j<1275;j++);
}
• Write an 8051 C program to get a byte of data form P1, wait ½ second, and
then send it to P2.
• Solution:
#include <reg51.h>
void MSDelay(unsigned int);
void main(void)
{
unsigned char mybyte;
P1=0xFF; //make P1 input port
while (1)
{
mybyte=P1; //get a byte from P1
MSDelay(500);
P2=mybyte; //send it to P2
}
}
void MSDelay(unsigned int itime)
{
unsigned int i,j;
for (i=0;i<itime;i++)
for (j=0;j<1275;j++);
}
• Write an 8051 C program to get a byte of data form P0. If it is less than 100,
send it to P1; otherwise, send it to P2.
• Solution:
#include <reg51.h>
void main(void)
{
unsigned char mybyte;
P0=0xFF; //make P0 input port
while (1)
{
mybyte=P0; //get a byte from P0
if (mybyte<100)
P1=mybyte; //send it to P1
else
P2=mybyte; //send it to P2
}
}
• Write an 8051 C program to toggle all the bits of P0, P1, and P2 continuously
with a 250 ms delay. Use the sfr keyword to declare the port addresses.
• Solution:
#include<reg51.h>
//Accessing Ports as SFRs using sfr data type
sfr P0=0x80;
sfr P1=0x90;
sfr P2=0xA0;
void MSDelay(unsigned int);
void main(void)
{
while (1)
{
P0=0x55;
P1=0x55;
P2=0x55;
MSDelay(250);
P0=0xAA;
P1=0xAA;
P2=0xAA;
MSDelay(250);
}
}
void MSDelay(unsigned int itime)
{
unsigned int i,j;
for (i=0;i<itime;i++)
for (j=0;j<1275;j++);
}
• Write an 8051 C program to get the status of bit P1.0, save it, and send it to
P2.7 continuously.
• Solution:
#include <reg51.h>
sbit inbit=P1^0;
sbit outbit=P2^7;
bit membit; //use bit to declare
//bit- addressable memory
void main(void)
{
inbit=1; // make as input port
while (1)
{
membit=inbit; //get a bit from P1.0
outbit=membit; //send it to P2.7
}
}
Write an 8051 C program to get bit P1.0 and send it to P2.7 after
inverting it.
Solution:
#include <reg51.h>
sbit inbit=P1^0;
sbit outbit=P2^7;
bit membit;
void main(void)
{
while (1)
{
inbit=1; // make as input port
membit=inbit; //get a bit from P1.0
outbit=~membit; //invert it and send
//it to P2.7
}
}
Write a 8051 C program to read the P1.0 and P1.1 and
issue an ASCII character to P0 according the following
table
P1.1 P1.0
0 0 send ‘0’ to P0
0 0 send ‘1’ to P0
0 0 send ‘2’ to P0
0 0 send ‘3’ to P0
Solution:
#include <reg51.h>
void main(void)
{
unsigned char z
P1=0xff; case(2):
Z=P1 {
P0=‘2’
Z=z&0x3;
break;
switch (z) }
{ case(3):
case(0): {
{ P0=‘3’
P0=‘0’ break;
break; }
}
case(1): }
}
{
P0=‘1’
break;
}
Write an 8051 C program to convert packed BCD 0x29 to ASCII and display the bytes on
P1 and P2.
Solution:
#include <reg51.h>
void main(void)
{
unsigned char x,y,z;
unsigned char mybyte=0x29;
x=mybyte&0x0F;
P1=x|0x30;
y=mybyte&0xF0;
y=y>>4;
P2=y|0x30;
}
Write an 8051 C program to convert ASCII digits of ‘4’ and ‘7’ to packed BCD and
display them on P1.
Solution:
#include <reg51.h>
void main(void)
{
unsigned char bcdbyte;
unsigned char w=‘4’;
unsigned char z=‘7’;
w=w&0x0F;
w=w<<4;
z=z&0x0F;
bcdbyte=w|z;
P1=bcdbyte;
}
Write an 8051 C program to convert 11111101 (FD hex) to decimal and display the digits
on P0, P1 and P2.
Solution:
#include <reg51.h>
void main(void)
{
unsigned char x,binbyte,d1,d2,d3;
binbyte=0xFD;
x=binbyte/10;
d1=binbyte%10;
d2=x%10;
d3=x/10;
P0=d1;
P1=d2;
P2=d3;
}
Write a C program to send out the value 44H serially one bit at a time via P1.0. The LSB
should go out first.
Solution:
#include <reg51.h>
sbit P1b0=P1^0;
sbit regALSB=ACC^0;
void main(void)
{
unsigned char conbyte=0x44;
unsigned char x;
ACC=conbyte;
for (x=0;x<8;x++)
{
P1b0=regALSB;
ACC=ACC>>1;
}
}
Write a C program to send out the value 44H serially one bit at a time via P1.0. The MSB
should go out first.
Solution:
#include <reg51.h>
sbit P1b0=P1^0;
sbit regAMSB=ACC^7;
void main(void)
{
unsigned char conbyte=0x44;
unsigned char x;
ACC=conbyte;
for (x=0;x<8;x++)
{
P1b0=regAMSB;
ACC=ACC<<1;
}
}
Write a C program to bring in a byte of data serially one bit at a time via P1.0. The LSB
should come in first.
Solution:
#include <reg51.h>
sbit P1b0=P1^0;
sbit ACCMSB=ACC^7;
bit membit;
void main(void)
{
unsigned char x;
for (x=0;x<8;x++)
{
membit=P1b0;
ACC=ACC>>1;
ACCMSB=membit;
}
P2=ACC;
}
Write a C program to bring in a byte of data serially one bit at a time via P1.0. The LSB
should come in first.
Solution:
#include <reg51.h>
sbit P1b0=P1^0;
sbit ACCMSB=ACC^7;
bit membit;
void main(void)
{
unsigned char x;
for (x=0;x<8;x++)
{
membit=P1b0;
ACC=ACC>>1;
ACCMSB=membit;
}
P2=ACC;
}
Write a C program to bring in a byte of data serially one bit at a time via P1.0. The MSB
should come in first.
Solution:
#include <reg51.h>
sbit P1b0=P1^0;
sbit regALSB=ACC^0;
bit membit;
void main(void)
{
unsigned char x;
for (x=0;x<8;x++)
{
membit=P1b0;
ACC=ACC<<1;
regALSB=membit;
}
P2=ACC;
}
• Interfacing is one of the important concepts in
microcontroller 8051 because the microcontroller is a
CPU that can perform some operation on a data and
gives the output.
• However to perform the operation we need an input
device to enter the data and in turn output device
displays the results of the operation.
• Keyboards are the predominant means of interface to
human inputs and visible displays are the universal
means of human output.
Interfacing switch
LED Interfacing to 8051
• There are two ways which we can interface LED to the
Microcontroller 8051.
• Interface 1 will glow LED, only if the PIN value of the MC
is HIGH as current flows towards the ground.
• Interface 2 will glow LED, only if the PIN value of the MC
is LOW as current flows towards PIN due to its lower
potential.
• The resistor is important in LED interfacing to limit the
flowing current and avoid damaging the LED.
• Resistor in interface 2 is important.
• Interface 1 works without any resistor also.
• Microcontroller pin does not damage LED.
• Write a program to blink LEDs connected to Port0 with a
delay.
• Solution:
#include<reg51.h>
#define LED P0
void delay(unsigned int);
void main()
{
LED=0x00;/* initialize the port 0 as 00h(output port)*/
While (1)
{
LED=0x00;
delay(250); /* turn off the leds for a specific period using delay
function*/
LED=0xff;
delay(250); /* turn off the leds for a specific period using delay
function */
}
}
void delay(unsigned int d)
{
unsigned int i,j;
for(i=0;i<d;i++)
for(j=0;j<1275;j++); /*this for loop produces a delay of approx 1ms*/
}
DELAY CALCULATION
1 Machine cycle = 12 clock cycles , Clock frequency of 8051 = 11.0592MHz
Time Period = (1/11.0592M) = 0.09042us
1 machine cycle takes 0.09042us x 12 = 1.086us
Therefore, total delay produced by the for loop= 1275 x 1.086us
= 1.3 ms
• Write a program to display binary up counter on LEDs.
• Solution:
#include<reg51.h>
#define LED P0
void delay(unsigned int);
void main()
{
LED=0x00;
while(1)
{
unsigned char i;
for(i=0;i<=255;i++) /* upcount*/
{
LED=i;
delay(50);
}
void delay(unsigned int d) /*program for delay*/
{
unsigned int i,j;
for(i=0;i<d;i++)
for(j=0;j<1275;j++);
}
Seven segment LED display
• Displays may be grouped into three broad
categories.
1) single light
2) single character
3) Intelligent alphanumeric
• Single light displays include incandescent and more
likely LED indicators that are treated as single binary
points to be switched on/off by the program.
• Single character displays include numeric and
alphanumeric arrays. They may be simple as a seven
segment numeric display up to intelligent dot matrix
displays.
• Intelligent alphanumeric are equipped with a built in
microcontroller that has been optimized for the
application.
• Inexpensive displays are represented by multi character
LCD windows which are becoming popular.
Seven segment numeric display
• Seven segment displays commonly contain LED
segments arranged as an 8, with one common lead
(anode or cathode) and seven individual leads for each
segment.
•
• If more than one display is to be used then they can be
time multiplexed, the human eye can not detect blinking
of each display if each display relit every 10msec or so.
• 10msec divided by the number of displays is used to
find the interval between updating each display.
• To display a digit incase of common cathode individual
segments are illuminated by the application of logic 1
via current limiting resistor to forward bias the
individual anode terminal.
• Similarly in case of common anode display logic 0 via
current limiting resistor to forward bias the individual
cathode terminal is required.
• In general common anodes are more popular as many
logic circuits can sink more current than they can
source.
Driving 7 segment display
• Seven segment displays need protection from over
current.
• LEDs produce light only when it is forward biased with
the amount of light emitted being proportional to the
forward current.
• Forward current must be controlled and limited to a safe
value by an external resistor to prevent damage to LED
segments.
• The forward drop of LED is very low at about 2-2.2v(Red
LED).
• If each segment can draw about 15mA to be illuminated
correctly (5-30mA) then
• VR=5v 5-2/15m=220Ω std value.
•
Driving 7 segment display using BCD to 7
segment decoder
• Seven segments are usually driven by a special type of
IC called BCD to 7 segment decoder such as CMOS 4511
or TTL 7447.
• This takes a four bit BCD input labeled as ABCD and has
seven outputs that will pass current through appropriate
segments to display the decimal digit.
• Each digit require separate BCD to seven segment
decoder. The limiting resistor will be calculated using
ohms law as before.
Multiplexed segment displays
• The circuit discussed before works well for driving just
one or two LED digits.
• But there are several problems with this scheme.
• If we want to drive 8 digits for worst case calculations
we assume all are displaying digit ‘8’, so all 7 segments
are lit.
• Eg: 20mA/segment leads to 7x20=140mA/digit.
• For 8 digits 140x8=1120mA=1.12A
• If we are using 7474 decoder, suppose each decoder
require 13mA current.
• Current required by the LEDs and decoders might be
several times the current required by the rest of the
circuit.
• To solve this problem of static display approach we use
multiplexing method.
• This circuit requires only one decoder, segment outputs
are connected parallel to the segment inputs of digits.
• The trick of multiplexing displays is that only one
display digit is turned on at a time.
• The transistor series with each digit as an on/off switch
for that digit.
• Initially first digit is on and displays the digit required,
after 1 or 2msec digit2 turned on and digit 1 is turned off
and process is repeated for digit 3 and so on.
• This process is continued until all the digits have had a
turn. Then again digit1 and following digits are lit again
in turn.
• With 8 digits and 2msec/digit, you can get back to digit
every 16msec or about 60 times a second.
• This refresh rate is fast enough so that to our eyes the
digits will each appear to be lit all at a time.
• Multiplexing saves power.
• In multiplexing we increase the segment current to a
value equal to the number display positions times per
segment current to get required brightness.
• But should be less than the maximum current.
Multiplexing common cathode display
Multiplexing common anode display
• Write a program to interface seven segment 1 digit
display and display one digit up counter(0-9) with one
second delay.
#include<reg51.h>
#define LED P0
void delay(unsigned int);
void main()
{
unsigned char ch[ ] =
{0x3F,0x06,0x5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F};
int i;
LED=0x00; /* LED declared as output port */
while(1)
{
for(i=0;i<10;i++)
{
LED=ch[i];
delay(1000);
}
}
}
void delay(unsigned int d)
{
unsigned int i,j;
For(i=0;i<d;i++)
for(j=0;j<1275;j++);
}
• Interface two digit common cathode seven segment
display to 8051 microcontroller and display ’16’on the
digits.
• Solution: I= 20mA, VLED=1.5V then R=5-1.5/20m=150Ω(std)
#include<reg51.h>
#define LED P1
sbit SW1=P3^0;
sbit SW2=P3^1;
void delay(unsigned int);
void main()
{
while(1)
{
unsigned int i;
LED=0x00; /*Led declared as output port*/
SW1=1;
LED=0x06; /*characters sent to output port */
delay(2); /*delay of 1ms being called*/
SW1=0;
SW2=1;
LED=0x7D;
delay(2);
SW2=0;
}
void delay(unsigned int d) /*Delay program*/
{
unsigned int i,j;
for(i=0;i<d;i++)
for(j=0;j<1275;j++);
}
• Interface three digit common cathode seven segment
display to 8051 microcontroller and display ’ABC’ on the
digits. Use any 2 ports of microcontroller.
• Solution: I= 20mA, VLED=1.5V then R=5-1.5/20m=150Ω(std)
#include<reg51.h>
#define LED P1
sbit SW1=P3^0;
sbit SW2=P3^1;
sbit SW3=P3^2;
void delay(unsigned int);
void main()
{
while(1)
{
unsigned int i;
LED=0x00;
SW1=1;
LED=0x77; /*characters sent to output port */
delay(2); /*delay of 1ms being called*/
SW1=0;
SW2=1;
LED=0x7F
delay(2);
SW2=0;
SW3=1;
LED=0x39;
delay(2);
SW3=0;
}
void delay(unsigned int d) /*Delay program*/
{
unsigned int i,j;
for(i=0;i<d;i++)
for(j=0;j<1275;j++);
}
Timers and Counters
• The 8051 has two timers/counters, they can be used
either as
Timers to generate a time delay or as
Event counters to count events happening outside the
microcontroller.
• Both Timer 0 and Timer 1 are 16 bits wide.
• Since 8051 has an 8-bit architecture, each 16-bits timer
is accessed as two separate registers of low byte and
high byte.
• The low byte register is called TL0/TL1 and the high byte
register is called TH0/TH1.
• Both timers 0 and 1 use the same register, called TMOD
(timer mode), to set the various timer operation modes.
• The counter increments from the initial number to he
maximum and rolls over to 0 on the final pulse and
sets a timer flag(TF).
• If a counter is programmed to be a timer, it ill count
the internal clock frequency of 8051 oscillator divided
by 12.
• In order to make oscillator pulses reach timer
• C/T =0 in TMOD register.
• TRX=1 & GATE=0 in TMOD register OR INTX =1
• Counter action can be controlled by bit states in the
timer mode control register (TMOD), timer /counter
control register(TCON) and certain program
instructions.
TCON register
TMOD register
TMOD register
• GATE: When set, timer/counter x is enabled, if INTx pin
is high and TRx is set. When cleared, timer/counter x is
enabled, if TRx bit set.
• C/T: When set, counter operation (input from Tx input
pin). When cleared, timer operation (input from internal
clock)
Timer operation modes
• Timer mode 0
• 13 bit timer/counter mode.
• TL is 5 bits and TH is 8 bits.
• Pulse input is divided by 25=32d in TL so that TH counts
the original oscillator frequency reduced by a total of 384
(12*32).
• TF is set when TH rolls over from FF to 00H.
• Final frequency is f/(12*213).
• Timer mode 1
• 16 bit timer/counter mode
• It acts like 16 bit timer/counter.
• It counts from 0000-FFFFH.
• Timer mode 2
• 8 bit auto-reload mode
• Uses only TLX as an 8 bit counter.
• THX holds a value that is loaded into TLX every time.
• TLX overflows from FFH to 00H.
• Timer mode 3
• Two 8 bit timers using timer 0
• When timer 1 working in mode3, it simply holds the count
but does not run.
• When timer0 is in mode3 timer1 can be configured in one
of the mode 0, 1, 2.
• Timer 1 working in mode3, it simply holds the count
but does not run.
• Timer0 in mode3 becomes two completely separate 8
bit counters.
• When timer0 is in mode3, timer1 can be configured in
one of the mode 0, 1, 2 except that TF1 will not be set
by timer1.
Counting
• The only difference between counting and timing is
the source of the clock pulses to the counters.
• The C/T bit in the TMOD registers decides the source
of the clock for the timer.
• When C/T = 1, the timer is used as a counter and gets
its pulses from outside the 8051.
• The counter counts up as pulses are fed from pins
P3.4 and P3.5, these pins are called T0 (timer 0 input)
and T1 (timer 1 input).
• Example: Indicate which mode and which timer are
selected for each of the following.
• (a) MOV TMOD, #01H (b) MOV TMOD, #20H (c) MOV
TMOD, #12H
• Solution: We convert the value from hex to binary.
• (a) TMOD = 00000001, mode 1 of timer 0 is selected.
• (b) TMOD = 00100000, mode 2 of timer 1 is selected.
• (c) TMOD = 00010010, mode 2 of timer 0, and mode 1
of timer 1 are selected.
• Example: Indicate which mode and which timer are
selected for each of the following.
• (a) MOV TMOD, #01H (b) MOV TMOD, #20H (c) MOV
TMOD, #12H
• Solution: We convert the value from hex to binary.
• (a) TMOD = 00000001, mode 1 of timer 0 is selected.
• (b) TMOD = 00100000, mode 2 of timer 1 is selected.
• (c) TMOD = 00010010, mode 2 of timer 0, and mode 1
of timer 1 are selected.
Timer Mode1 programming
1. It is a 16-bit timer; therefore, it allows value of 0000 to
FFFFH to be loaded into the timer’s register TL and TH.
2. After TH and TL are loaded with a 16-bit initial value,
the timer must be started using SETB TR0 for timer 0
and SETB TR1 for timer 1.
3. After the timer is started, it starts to count up. It
counts up until it reaches its limit of FFFFH. When it rolls
over from FFFFH to 0000, it sets TF high. This timer flag
can be monitored. When this timer flag is raised, one
option would be to stop the timer with the instructions
CLR TR0 or CLR TR1, for timer 0 and timer 1,
respectively.
4. After the timer reaches its limit and rolls over, in order
to repeat the process TH and TL must be reloaded with
the original value, and TF must be reloaded to 0.
Steps to program Timer in Mode1
1. Load the TMOD value register indicating which timer
is to be used and which timer mode is selected.
2. Load registers TL and TH with initial count value.
3. Start the timer.
4. Keep monitoring the timer flag (TF) with the JNB TFx,
target instruction to see if it is raised. Get out of the loop
when TF becomes high.
5. Stop the timer.
6. Clear the TF flag for the next round.
7. Go back to Step 2 to load TH and TL again.
• Delay calculation: f=11.0592 MHz
• The timer works with a clock frequency of 1/12 of the
XTAL frequency.
• f/12=11.0592 MHz / 12 = 921.6 kHz
• T =1/921.6kHz = 1.085us.
• delay = number of counts × 1.085us.
• The number of counts FFFFH – FFF2H = 0DH (13d).
However, we add one to 13 because of the extra clock
needed when it rolls over from FFFF to 0 and raise the
TF flag.
• Ton=14 × 1.085us = 15.19us
• Time delay T = 2 × 15.19us = 30.38us
• Formula to calculate count
• Td= (FFFFH- THTL+1)*1.085 μsec --- for f=11.0592 MHz
• In decimal
• Td= (65536- THTL)*1.085 μsec --- for f=11.0592 MHz
Maximum time delay in mode1
Timer can count max from 0000-FFFFH
• For XTAL=11.0592 MHZ
• (65536-0000)* 1.085μsec = 71.106 msec
• For XTAL=22 MHZ
• (65536-0000)* 0.546μsec = 35.75 msec
• For larger time delays we have to use loops.
• Eg: for Ton=1sec=1000msec
• 35.75m*28=1001msec
• Write an 8051 C program to toggle all the bits of port P1 continuously with
some delay in between. Use Timer 0, 16-bit mode to generate the delay.
• Solution:
#include <reg51.h>
void T0Delay(void);
void main(void){
while (1) {
P1=0x55;
T0Delay();
P1=0xAA;
T0Delay();
}
}
void T0Delay(){
TMOD=0x01;
TL0=0x00;
TH0=0x35;
TR0=1;
while (TF0==0);
TR0=0;
TF0=0;
}
• Td= (FFFFH- THTL+1)*1.085 μsec
• FFFFH – 3500H = CAFFH
• = 51967 + 1 = 51968
• 51968 × 1.085 μs = 56.384 ms is the approximate delay
• Write an 8051 C program to toggle only bit P1.5 continuously
every 50 ms. Use Timer 0, mode 1 (16-bit) to create the delay. Test
the program on the AT89C51
Solution
(FFFFH- THTL+1)*1.085 μsec=50 msec
(65535- THTL+1) =46083
THTL= 65535 – 46083 + 1 = 19453 =4BFDH
46083 × 1.085 μs = 50 ms
#include <reg51.h>
void T0M1Delay(void);
sbit mybit=P1^5;
void main(void){
Mybit=1
while (1) {
mybit=~mybit;
T0M1Delay();
}
}
void T0M1Delay(void){
TMOD=0x01;
TL0=0xFD;
TH0=0x4B;
TR0=1;
while (TF0==0);
TR0=0;
TF0=0;
}
• Write an 8051 C program to toggle all bits of P2
continuously every 500 ms. Use Timer 1, mode 1 to
create the delay.
• Solution
(65536- THTL)*1.085 μsec = 25 msec
65536 – 42494 = 23042
A5FEH = 42494 in decimal
THTL=A5FE
23042 × 1.085 μs = 25 ms and
20 × 25 ms = 500 ms
#include <reg51.h>
void T1M1Delay(void);
void main(void){
unsigned char x;
P2=0x55;
while (1) {
P2=~P2;
for (x=0;x<20;x++)
T1M1Delay();
}
}
void T1M1Delay(void){
TMOD=0x10;
TL1=0xFE;
TH1=0xA5;
TR1=1;
while (TF1==0);
TR1=0;
TF1=0;
}
• A switch is connected to pin P1.2. Write an 8051 C program to monitor
SW and create the following frequencies on pin P1.7:
• SW=0: 500Hz
• SW=1: 750Hz, use Timer 0, mode 1 for both of them.
Solution:
F=500 Hz, T= 2 msec Ton=1msec
(65536- THTL)*1.085 μsec = 1 msec
65536 – THTL = 921
THTL= 64615 =FC67H
THTL= FC67H
921 × 1.085 μs = 999.285 μs
1 / (999.285 μs × 2) = 500 Hz
F=750 Hz, T= 1.3 msec Ton=1.3/2 msec
(65536- THTL)*1.085 μsec = 1.3/2 msec
65536 – THTL = 600
THTL= 64936 = FDA8H
600 × 1.085 μs = 666.19 μs
1 / (666.19 μs × 2) = 750 Hz
#include <reg51.h>
sbit mybit=P1^5;
sbit SW=P1^7;
void T0M1Delay(unsigned char);
void main(void){
SW=1;
while (1) {
mybit=0
mybit=~mybit;
if (SW==0)
T0M1Delay(0);
else
T0M1Delay(1);
}
}
void T0M1Delay(unsigned char c){
TMOD=0x01;
if (c==0) {
TL0=0x67;
TH0=0xFC;
}
else {
TL0=0xA8;
TH0=0xFD;
}
TR0=1;
while (TF0==0);
TR0=0;
TF0=0;
}
Timer Mode 0 programming
• Mode 0 is similar to mode1 except that it is a 13 bit
timer instead of 16 bit.
Timer Mode 2 Programming
1. It is an 8-bit timer; therefore, it allows only values of
00 to FFH to be loaded into the timer’s register TH.
2. After TH is loaded with the 8-bit value, the 8051 gives
a copy of it to TL. Then the timer must be started. This is
done by the instruction SETB TR0 for timer 0 and SETB
TR1 for timer 1.
3. After the timer is started, it starts to count up by
incrementing the TL register. It counts up until it
reaches its limit of FFH. When it rolls over from FFH to
00, it sets TF.
4. When the TL register rolls from FFH to 0 and TF is set
to 1, TL is reloaded automatically with the original value
kept by the TH register. To repeat the process, we must
simply clear TF and let it go without any need by the
programmer to reload the original value. This makes
mode 2 an auto-reload, in contrast with mode 1 in which
the programmer has to reload TH and TL.
1. Load the TMOD value register indicating which timer
is to be used, and the timer mode is selected
2. Load the TH registers with the initial count value.
3. Start timer
4. Keep monitoring the timer flag (TF) with the JNB TFx,
target instruction to see whether it is raised. Get out of
the loop when TF goes high.
5. Clear the TF flag.
6. Go back to Step4, since mode 2 is autoreload.
Delay calculation;
Td= (256-TH)*1.085 μsec ------ for 11.0592M HZ
Td= (256-TH)*0.546 μsec ------ for 22M HZ
Max delay
(256-00)*1.085 μsec =0.277msec
(256-00)*0.546 μsec =0.1397msec
Negative count
• Decimal 2’s complement
• -3 FDH
• -12 F4H
• -48 D0H
• -60 C4H
• -150 6AH
• Delay:
• Eg: -150(6Ah)
• (256-6A)*1.085μsec=162μsec
• Or
• 150* 1.085μsec=162μsec
• MOV TH1,#-150 = MOV TH1,#6AH
• Write an 8051 C program to toggle only pin P1.5
continuously every 250 ms. Use Timer 0, mode 2 (8-bit
auto-reload) to create the delay.
• Solution:
(256-TH)*1.085 μsec= 25 μs
256 – TH = 23
TH= 233=E9 = -23
23 × 1.085 μs = 25 μs and
25 μs × 250 × 40 = 250 ms
#include <reg51.h>
void T0M2Delay(void);
sbit mybit=P1^5;
void main(void){
unsigned char x,y;
while (1) {
mybit=1;
mybit=~mybit;
for (x=0;x<250;x++)
for (y=0;y<40;y++)
T0M2Delay();
}
}
void T0M2Delay(void){
TMOD=0x02;
TH0=-23;
TR0=1;
while (TF0==0);
TR0=0;
TF0=0;
}
• Write an 8051 C program to create a square wave of
frequency of 2500 Hz on pin P2.7. Use Timer 1, mode 2
to create delay.
• Solution
1/2500 Hz = 400 μs
400 μs /2 = 200 μs
200 μs / 1.085 μs = 184
#include <reg51.h>
void T1M2Delay(void);
sbit mybit=P2^7;
void main(void){
unsigned char x;
while (1) {
Mybit=1;
mybit=~mybit;
T1M2Delay();
}
}
void T1M2Delay(void){
TMOD=0x20;
TH1=-184;
TR1=1;
while (TF1==0);
TR1=0;
TF1=0;
}
Counter programming
• Timers can also be used as counters counting events
happening outside the 8051.
• When it is used as a counter, it is a pulse outside of the
8051 that increments the TH, TL registers TMOD and
TH, TL registers are the same as for the timer.
discussed previously.
• Programming the timer in the last section also applies
to programming it as a counter.
• Except the source of the frequency.
• Values obtained for frequencies 10hz, 25hz, 100hz are
0AH, 19H, 64H respectively.
• For f=10hz, T=0.1
• 1sec=0.1*10 ; count=10=0AH
• We can feed an external square wave of frequency 60hz
into a timer, program will generate second, minute and
hour of this input frequency.
• If GATE=1, the start and stop of the timer are done
externally through pins P3.2 and P3.3 (INTX).
• Assume that a 1-Hz external clock is being fed into pin T1 (P3.5). Write
a C program for counter 1 in mode 2 (8-bit auto reload) to count up
and display the state of the TL1 count on P1. Start the count at 0H.
#include <reg51.h>
sbit T1=P3^5;
void main(void){
T1=1;
TMOD=0x60;
TH1=0;
while (1) {
do {
TR1=1;
P1=TL1;
}
while (TF1==0);
TR1=0;
TF1=0;
}
}
Assume that a 1-Hz external clock is being fed into pin T0 (P3.4). Write a C program
for counter 0 in mode 1 (16-bit) to count the pulses and display the state of the TH0
and TL0 registers on P2 and P1, respectively.
• Solution
#include <reg51.h>
void main(void){
T0=1;
TMOD=0x05;
TL0=0
TH0=0;
while (1) {
do {
TR0=1;
P1=TL0;
P2=TH0;
}
while (TF0==0);
TR0=0;
TF0=0;
}
}
Assume that a 2-Hz external clock is being fed into pin T0 (P3.4). Write a C program
for counter 0 in mode 2 to display the count in ASCII. The 8 bit binary count must be
converted to ASCII. Display the ASCII digits in binary on P0, P1 and P2 where P0 has
the least significant digit. Set the initial value of TH) to 0
• Solution
#include <reg51.h>
void BinToASCII(unsigned char);
void main(){
unsigned char value;
T1=1;
TMOD=0x06;
TH0=0;
while (1) {
do {
TR0=1;
value=TL0;
BinToASCII(value);
}
while (TF0==0);
TR0=0;
TF0=0;
}
}
void BinToASCII(unsigned char value);
x=value/10;
d1=value%10;
d2=x%10;
d3=x/10
P0=30|d1;
P1=30|d2;
P2=30|d3;
}
Assume that a 60-Hz external clock is being fed into pin T0 (P3.4). Write a C program
for counter 0 in mode 2 to display seconds and minutes on P1 and P2 respectively.
• Solution
#include <reg51.h>
void ToTime(unsigned char);
void main(){
unsigned char val;
T0=1;
TMOD=0x06;
TH0=-60;
while (1) {
do {
TR0=1;
val=TL0;
ToTime(val);
}
while (TF0==0);
TR0=0;
TF0=0;
}
}
void ToTime(unsigned char val);
unsigned char sec, min;
min=value/60;
sec=value%60;
P0=sec;
P1=min;
}
8051 Serial Communication
• Basics of serial communication
• Computers transfer data in two ways:
• Parallel: Often 8 or more lines (wire conductors) are
used to transfer data to a device that is only a few feet
away.
• Serial: To transfer to a device located many meters
away, the serial method is used. The data is sent one
bit at a time.
8051 Serial Communication
• Serial data communication uses two methods.
• Synchronous method transfers a block of data at a time.
• Asynchronous method transfers a single byte at a time.
• It is possible to write software to use either of these
methods, but the programs can be tedious and long.
• There are special IC chips made by many manufacturers
for serial communications.
UART (universal asynchronous Receiver transmitter)
USART (universal synchronous-asynchronous Receiver-
transmitter)
• Asynchronous Serial data communication:
• The data coming in at the receiver end in serial
communication is all 0’s and 1’s.
• It is difficult to make sense of data unless sender and
receiver agree on a set of rules called as protocol.
Serial communication(UART) data frame
• The 0 (low) is referred to as space.
• The transmission begins with a start bit followed by D0,
the LSB, then the rest of the bits until MSB (D7), and
finally, the one stop bit indicating the end of the
character.
• When there is no transfer, the signal is 1 (high), which is
referred to as mark.
• Data transfer rate:
• The rate of data transfer in serial data communication is
stated in bps (bits per second).
• Another widely used terminology for bps is baud rate.
• It is modem terminology and is defined as the number of
signal changes per second
• As far as the conductor wire is concerned, the baud rate
and bps are the same, and we use the terms
interchangeably.
• 8051 serial communication:
• The 8051 has a serial data communication circuit that
uses registers
• SBUF to hold data
• SCON to control the data communication
• PCON controls data rates
• Pins RXD(P3.0) and pins TXD(P3.1) to connect to the
serial data network.
• SBUF register:
• SBUF is an 8-bit register used solely for serial
communication
• For a byte data to be transferred via the TxD line, it must
be placed in the SBUF register.
• The moment a byte is written into SBUF, it is framed with
the start and stop bits and transferred serially via the
TxD line
• SBUF holds the byte of data when it is received by 8051
RxD line.
• When the bits are received serially via RxD, the 8051
deframes it by eliminating the stop and start bits, making
a byte out of the data received, and then placing it in
SBUF.
• SCON (serial port control) register:
• SCON is an 8-bit register used to program the start bit,
stop bit, and data bits of data framing, among other
things.
SM2: Multiprocessor communication bit. Set/cleared to
enable multiprocessor communication in mode2 and
mode3, cleared to 0 in mode0 and set to 1 in mode1.
REN (receive enable): When it is high, it allows 8051 to
receive data on RxD pin. If low, the receiver is disabled.
TI (transmit interrupt): When 8051 finishes the transfer of
8-bit character. It raises TI flag to indicate that it is ready
to transfer another byte. TI bit is raised at the beginning of
the stop bit.
RI (receive interrupt): When 8051 receives data serially
via RxD, it gets rid of the start and stop bits and places the
byte in SBUF register. It raises the RI flag bit to indicate
that a byte has been received and should be picked up
before it is lost RI is raised halfway through the stop bit.
TB8: transmitted bit8: set or cleared in mode 2 &3.
RB8: received bit8: bit 8 of received data in mode 2 and 3,
stop bit in mode1, not used in mode0.
PCON (Power mode control register):
• PCON register is an 8-bit register. It is not bit
addressable.
• Baud rate in 8051:
• To allow data transfer between the PC and an 8051 system
without any error, we must make sure that the baud rate of
8051 system matches the baud rate of the PC’s COM port.
• The machine cycle frequency of 8051 = 11.0592 / 12 = 921.6
kHz, and 921.6 kHz / 32 = 28,800 Hz is frequency given by
UART to timer 1 to set baud rate.
• When timer 1 is used to set baud rate it must be programmed
in mode2.
• (a) 28,800 / 3 = 9600 where -3 = FD (hex) is loaded into TH1
• (b) 28,800 / 12 = 2400 where -12 = F4 (hex) is loaded into TH1
• (c) 28,800 / 24 = 1200 where -24 = E8 (hex) is loaded into TH1
Serial data communication modes
• In 8051 there 4 serial data transmission modes.
• Modes are selected by setting SM0, SM1 bits in SCON
register.
• Baud rate is fixed for mode0 and variable using timer1
and SMOD in PCON register for mode 1, 2 an 3.
• There are 4 modes
• Serial data mode 0
• Serial data mode 1
• Serial data mode 2
• Serial data mode 3
•
Serial data mode 0(shift register mode)
• Serial data enters and exits through RXD
• TXD outputs the clock.
• 8 bits are transmitted / received.
• The baud rate is fixed at (1/12) of the oscillator
frequency.
• Baud rate is higher than communication rates.
Serial data mode 1(standard UART)
• Serial data enters through RXD.
• Serial data exits through TXD.
• On receive, the stop bit goes into RB8 in SCON
• 10 bits are transmitted / received.
1. Start bit
2. Data bits (8)
3. Stop Bit
• Baud rate is determined by the Timer 1.
• If Timer 1 in mode2, then
• If timer 1 is not mode 2, then
Serial data mode 2 (multiprocessor mode)
• Serial data enters through RXD.
• Serial data exits through TXD.
• On transmit, 9th data bit copied from TB8 and can be
assigned value 0 or 1.
• On receive, the 9th data bit goes into RB8 in SCON.
• Both start and stop bits are discarded.
• 11 bits are transmitted / received.
1.Start bit s
2.Data bits (9)
3.Stop Bit
• Baud rate is programmable.
• Baud rate is higher than communication rates.
Serial data mode 3 (multiprocessor mode)
• Mode 3 is similar to mode2 except that the baud rate is
determined exactly as in mode1 using timer1 to
generate communication frequencies.
Programming 8051 to transfer data serially
1. TMOD register is loaded with the value 20H, indicating
the use of timer 1 in mode 2 (8-bit auto-reload) to set
baud rate.
2. The TH1 is loaded with one of the values to set baud
rate for serial data transfer.
3. The SCON register is loaded with the value 50H,
indicating serial mode 1, where an 8- bit data is framed
with start and stop bits.
4. TR1 is set to 1 to start timer 1.
5. TI is cleared by CLR TI instruction.
6. The character byte to be transferred serially is written
into SBUF register.
7. The TI flag bit is monitored with the use of instruction
JNB TI, xx to see if the character has been transferred
completely.
8. To transfer the next byte, go to step 5.
Programming 8051 to receive data serially
1. TMOD register is loaded with the value 20H, indicating
the use of timer 1 in mode (8-bit auto-reload) to set baud
rate.
2. TH1 is loaded to set baud rate.
3. The SCON register is loaded with the value 50H,
indicating serial mode 1, where an 8- bit data is framed
with start and stop bits.
4. TR1 is set to 1 to start timer 1.
5. RI is cleared by CLR RI instruction.
6. The RI flag bit is monitored with the use of instruction
JNB RI, xx to see if an entire character has been received
yet.
7. When RI is raised, SBUF has the byte, its contents are
moved into a safe place.
8. To receive the next character, go to step 5.
TI=0 indicate SBUF is loaded with new data.
TI=1 indicate SBUF is empty i. e data is
transmitted (transmission complete).
RI=1 indicate entire data has been received and
available in SBUF (reception complete).
RI=0 indicate SBUF is empty and it is available
for new data.
Write a C program for 8051 to transfer the letter “A” serially at
4800 baud continuously. Use 8-bit data and 1 stop bit.
Solution:
#include <reg51.h>
void main(void){
TMOD=0x20; //use Timer 1, mode 2
TH1=0xFA; //4800 baud rate
SCON=0x50;
TR1=1;
while (1) {
SBUF=‘A’; //place value in buffer
while (TI==0);
TI=0;
}
}
• Write an 8051 C program to transfer the message “YES” serially at 9600 baud, 8-bit
data, 1 stop bit. Do this continuously.
• Solution:
#include <reg51.h>
void SerTx(unsigned char);
void main(void){
TMOD=0x20; //use Timer 1, mode 2
TH1=0xFD; //9600 baud rate
SCON=0x50;
TR1=1; //start timer
while (1) {
SerTx(‘Y’);
SerTx(‘E’);
SerTx(‘S’);
}
}
void SerTx(unsigned char x){
SBUF=x; //place value in buffer
while (TI==0); //wait until transmitted
TI=0;
}
Program the 8051 in C to receive bytes of data serially and put
them in P1. Set the baud rate at 4800, 8-bit data, and 1 stop bit.
Solution:
#include <reg51.h>
void main(void){
unsigned char mybyte;
TMOD=0x20; //use Timer 1, mode 2
TH1=0xFA; //4800 baud rate
SCON=0x50;
TR1=1; //start timer
while (1) { //repeat forever
while (RI==0); //wait to receive
mybyte=SBUF; //save value
P1=mybyte; //write value to port
RI=0;
}
}
• Write an 8051 C Program to send the two messages “Normal
Speed” and “High Speed” to the serial port. Assuming that SW is
connected to pin P2.0, monitor its status and set the baud rate as
follows:
• SW = 0, 28,800 baud rate
• SW = 1, 56K baud rate
Assume that XTAL = 11.0592 MHz for both cases.
• Solution:
#include <reg51.h>
sbit MYSW=P2^0; //input switch
void main(void){
unsigned char z;
unsigned char Mess1[]=“Normal Speed”;
unsigned char Mess2[]=“High Speed”;
TMOD=0x20; //use Timer 1, mode 2
TH1=0xFF; //28800 for normal
SCON=0x50;
TR1=1; //start timer
if(MYSW==0) {
for (z=0;z<12;z++) {
SBUF=Mess1[z]; //place value in buffer
while(TI==0); //wait for transmit
TI=0;
}
}
else {
PCON=PCON|0x80; //for high speed of 56K
for (z=0;z<10;z++) {
SBUF=Mess2[z]; //place value in buffer
while(TI==0); //wait for transmit
TI=0;
}
}
}
• Write a C program for the DS89C4x0 to transfer the letter “A” serially at
4800 baud continuously. Use the second serial port with 8-bit data and 1
stop bit. We can only use Timer 1 to set the baud rate.
• Solution:
#include <reg51.h>
sfr SBUF1=0xC1;
sfr SCON1=0xC0;
sbit TI1=0xC1;
void main(void){
TMOD=0x20; //use Timer 1, mode 2
TH1=0xFA; //4800 baud rate
SCON=0x50; //use 2nd serial port SCON1
TR1=1; //start timer
while (1) {
SBUF1=‘A’; //use 2nd serial port SBUF1
while (TI1==0); //wait for transmit
TI1=0;
}
}
Doubling baud rate in 8051
• There are two ways to increase the baud rate of data
transfer
• 1.By using a higher frequency crystal
• 2.By changing a bit in the PCON register
• When 8051 is powered up, SMOD in PCON is zero. We
can set it to high by software and thereby double the
baud rate.
• MOV A,PCON ;place a copy of PCON in ACC
• SETB ACC.7 ;make D7=1
• MOV PCON,A ;changing any other bits
8051 Interrupts
• An interrupt is an external or internal event that
interrupts the microcontroller to inform it that a device
needs its service.
• A single microcontroller can serve several devices by
two ways.
1. Polling: The microcontroller continuously monitors the
status of a given device. When the conditions met, it
performs the service. After that, it moves on to monitor
the next device until every one is serviced.
• Polling can monitor the status of several devices and
serve each of them as certain conditions are met.
• The polling method is not efficient, since it wastes much
of the microcontroller’s time by polling devices that do
not need service.
2. Interrupts: Whenever any device needs its service, the
device notifies the microcontroller by sending it an
interrupt signal. Upon receiving an interrupt signal, the
microcontroller interrupts whatever it is doing and serves
the device. The program which is associated with the
interrupt is called the interrupt service routine(ISR).
Interrupt vs polling
• The polling method is not efficient, since it wastes much
of the microcontroller’s time by polling devices that do
not need service.
• The advantage of interrupts is that the microcontroller
can serve many devices.
• Each devices can get the attention of the
microcontroller based on the assigned priority.
• For the polling method, it is not possible to assign
priority since it checks all devices in a round-robin
fashion.
• The microcontroller can also ignore (mask) a device
request for service. This is not possible for the polling
method
Interrupt service routine
• For every interrupt, there must be an interrupt service
routine (ISR), or interrupt handler.
• When an interrupt is invoked, the microcontroller runs
the interrupt service routine.
• For every interrupt, there is a fixed location in memory
that holds the address of its ISR.
• The group of memory locations set aside to hold the
addresses of ISRs is called interrupt vector table.
Steps in executing an Interrupt
• Upon activation of an interrupt, the microcontroller goes
through the following steps.
1. It finishes the instruction it is executing and saves the
address of the next instruction (PC) on the stack.
2. It also saves the current status of all the interrupts
internally (i.e: not on the stack).
3. It jumps to a fixed location in memory, called the
interrupt vector table, that holds the address of the ISR.
4. The microcontroller gets the address of the ISR from
the interrupt vector table and jumps to it.
5. Upon executing the RETI instruction, the
microcontroller returns to the place where it was
interrupted by popping the into the PC.
Six interrupts in 8051
Six interrupts are allocated as follows
1) Reset – power-up reset
2) Two interrupts are set aside for the timers: one for
timer 0 (TF0) and one for timer 1(TF1).
3) Two interrupts are set aside for hardware: P3.2 and
P3.3 are for the external hardware interrupts INT0, and
INT1.
4) Serial communication has a single interrupt that
belongs to both receive (RI) and transfer (TI).
The 8051 compiler have extensive support for the interrupts
They assign a unique number to each of the 8051 interrupts
It can assign a register bank to an ISR
This avoids code overhead due to the pushes and pops of the
R0 – R7 registers
Enabling and disabling interrupts
• Upon reset, all interrupts are disabled (masked),
meaning that none will be responded to by the
microcontroller if they are activated.
• The interrupts must be enabled by software in order for
the microcontroller to respond to them.
• There is a register called IE (interrupt enable) that is
responsible for enabling (unmasking) and disabling
(masking) the interrupts.
Interrupt Enable (IE) register
Steps to enable the interrupt
• To enable an interrupt, we take the following steps:
1. Bit D7 of the IE register (EA) must be set to high to
allow the rest of register to take effect.
2. If EA = 1, interrupts are enabled and will be
responded to if their corresponding bits in IE are high.
If EA = 0, no interrupt will be responded to, even if the
associated bit in the IE register is high.
Interrupt priority in 8051
Interrupt priority on reset:
• When the 8051 is powered up, the priorities are
assigned according to the following.
• In reality, the priority scheme is nothing but an
internal polling sequence in which the 8051 polls the
interrupts in the sequence listed and responds
accordingly.
Setting priority with IP register:
• We can alter the sequence of interrupt priority by
assigning a higher priority to any one of the interrupts
by programming a register called IP (interrupt
priority).
• To give a higher priority to any of the interrupts, we
make the corresponding bit in the IP register high.
• When two or more interrupt bits in the IP register are
set to high, While these interrupts have a higher
priority than others, they are serviced according to
the sequence of Table.
Interrupt priority(IP) register
Timer programming using Interrupt
• The timer flag (TF) is raised when the timer rolls over.
• In polling TF, we have to wait until the TF is raised. The problem
with this method is that the microcontroller is tied down while
waiting for TF to be raised, and can not do anything else.
• Using interrupts solves this problem and, avoids tying down the
controller.
• If the timer interrupt in the IE register is enabled, whenever the
timer rolls over, TF is raised, and the microcontroller is interrupted
in whatever it is doing, and jumps to the interrupt vector table to
service the ISR.
• In this way, the microcontroller can do other until it is notified that
the timer has rolled over.
• We must avoid using the memory space allocated to the
interrupt vector table therefore start main program from
30h.
• Monitoring TF flag need not be done using JNB TFX,
target and no CLR TF0 required since RETI clears TF
automatically.
Write a C program that continuously gets a single bit of data from P1.7 and
sends it to P1.0, while simultaneously creating a square wave of 200 μs period
on pin P2.5. Use Timer 0 to create the square wave. Assume that XTAL = 11.0592
MHz.
Solution:
We will use timer 0 mode 2 (auto-reload). One half of the period is
100 μs. 100/1.085 μs = 92, and TH0 = 256 - 92 = 164 or A4H
#include <reg51.h>
sbit SW =P1^7;
sbit IND =P1^0;
sbit WAVE =P2^5;
void timer0(void) interrupt 1 {
WAVE=~WAVE; //toggle pin
}
void main() {
SW=1; //make switch input
TMOD=0x02;
TH0=0xA4; //TH0=-92
IE=0x82; //enable interrupt for timer 0
while (1) {
IND=SW; //send switch to LED
}
}
External interrupts INT0 and INT1
• The 8051 has two external hardware interrupts
Pin 12 (P3.2) ----- INT0
Pin 13 (P3.3) ----- INT1
• The interrupt vector table locations 0003H and 0013H are set aside
for INT0 and INT1.
• There are two activation levels for the external hardware interrupts
Level trigged --- IT0 & IT1 both 0’s for low level triggered
Edge trigged --- IT0 & IT1 both 1’s for edge triggered
Edge triggered
• To make INT0 and INT1 edge triggered interrupts, we must program
the bits of the TCON register.
• IT0 and IT1 are bits D0 and D2 of the TCON register must be made
high.
• They are also referred to as TCON.0 and TCON.2 since the TCON
register is bit addressable.
Serial communication interrupts
• TI (transfer interrupt) is raised when the last bit of the framed data,
the stop bit, is transferred, indicating that the SBUF register is
ready to transfer the next byte.
• RI (received interrupt) is raised when the entire frame of data,
including the stop bit, is received.
• In the 8051 there is only one interrupt set aside for serial
communication.
• In that ISR we must examine the TI and RI flags to see which one
caused the interrupt and respond accordingly and clear it.
Write a C program using interrupts to do the following:
(a) Receive data serially and send it to P0
(b) Read port P1, transmit data serially, and give a copy to P2
(c) Make timer 0 generate a square wave of 5 kHz frequency on P0.1
Assume that XTAL = 11.0592 MHz. Set the baud rate at 4800.
Solution:
#include <reg51.h>
sbit WAVE =P0^1;
void timer0() interrupt 1 {
WAVE=~WAVE; //toggle pin
}
void serial0() interrupt 4 {
if (TI==1) {
TI=0; //clear interrupt
}
else {
P0=SBUF; //put value on pins
RI=0; //clear interrupt
}
}
void main() {
unsigned char x;
P1=0xFF; //make P1 an input
TMOD=0x22;
TH1=0xF6; //4800 baud rate
SCON=0x50;
TH0=0xA4; //5 kHz has T=200us
IE=0x92; //enable interrupts
TR1=1; //start timer 1
TR0=1; //start timer 0
while (1) {
x=P1; //read value from pins
SBUF=x; //put value in buffer
P2=x; //write value to pins
}
}
Write a C program using interrupts to do the following:
(a) Generate a 10 KHz frequency on P2.1 using T0 8-bit auto-reload
(b) Use timer 1 as an event counter to count up a 1-Hz pulse and
display it on P0. The pulse is connected to EX1.
Assume that XTAL = 11.0592 MHz. Set the baud rate at 9600.
Solution:
#include <reg51.h>
sbit WAVE =P2^1;
unsigned char cnt;
void timer0() interrupt 1 {
WAVE=~WAVE; //toggle pin
}
void timer1() interrupt 3 {
cnt++; //increment counter
P0=cnt; //display value on pins
}
void main() {
cnt=0; //set counter to 0
TMOD=0x42;
TH0=0x-46; //10 KHz
IE=0x86; //enable interrupts
TR0=1; //start timer 0
while (1); //wait until interrupted
}
Write a C program using interrupts to do the following:
(a) Write a C program that continuously gets a single bit of data from P1.7 and
sends it to P1.0 in the main, while simultaneously (a) creating a square wave of
200 μsec period on pin P2.5 and (b) sending letter ‘A’ to the serial port. Use
Timer 0 to create square wave. Assume that XTAL=11.0592 MHz. use 9600 baud
rate.
Solution:
Timer 0 in mode 2 TH0=100/1.085 μsec =-92= A4H
#include <reg51.h>
sbit sw =P1^7;
sbit ind =P1^0;
sbit WAVE= P2^5;
void timer0() interrupt 1 {
WAVE=~WAVE; //toggle pin
}
void serial0() interrupt 4 {
if (TI==1) {
SBUF=‘A’;
TI=0; //clear interrupt
}
else {
RI=0; //clear interrupt
}
}
void main() {
sw=1
TH1=-3
TMOD=0x22;
TH0=0xA4; //
-92=A4H for timer0
SCON=0x50;
TR0=1; //start timer 0
TR1=1;
IE=0X92;
while (1)
{
IND=sw
}
}
Serial Peripheral Interface (SPI)
• The serial peripheral interface was introduced by Motorola© and is the
simplest synchronous communication protocol in general use.
• SPI doesn’t have any fixed protocol like I2C and there are plenty of
options within “standard” SPI and innumerable variations
• In the simplest form of SPI, One device is the master and the other the
slave
• The master provides the clock for both devices and a signal to select
(enable) the slave, but the path followed by the data is identical in
each.
• SPI requires four wires (plus ground, which is essential but never
counted) and transmits data simultaneously in both directions (full
duplex) between two devices
182
Master and Slave connection using SPI
183
Bus with
slaves
individually
selected
184
Daisy chain
185
Introduction to I2C • The name I2C translates into
“Inter IC”, Sometimes the
bus is called IIC or I²C bus
• The I2C bus was designed by
Philips in the early 1980s to
allow easy communication
between components which
reside on the same circuit
board (Philips
Semiconductors migrated
to NXP in 2006)
186
Features of I2C
• Only two signals (clock and data) are used, regardless of how many devices are on
the bus.
• Both signals are pulled up to a positive power supply voltage through appropriately
sized resistors.
• Every device interfaces to the clock and data signal through open-drain (or open-
collector) output drivers.
• Each slave device is identified by means of a 7-bit address; the master must know
these addresses in order to communicate with a particular slave.
• All transmissions are initiated and terminated by a master; the master can write
data to one or more slaves or request data from a slave.
• The labels “master” and “slave” are inherently non-permanent: any device can
function as a master or slave if it incorporates the necessary hardware and/or
firmware. In practice, though, embedded systems often adopt an architecture in
which one master sends commands to or gathers data from multiple slaves.
187
• SDA (Serial Data) – The line for the master
The physical and slave to send and receive data.
I2C Bus • SCL (Serial Clock) – The line that carries the
clock signal.
188
• The devices connected to the I2C bus are categorized as either masters or
slaves.
Device • At any instant of time only a single master stays active on the I2C bus
• It controls the SCL clock line and decides what operation is to be done on
Addressing the SDA data line
• For differentiating between multiple slave devices connected to the same
I2C bus, each slave device is physically assigned a permanent 7-bit address.
• When a master device wants to transfer data to or from a slave device, it
specifies this particular slave device address on the SDA line and then
proceeds with the transfer.
189
• Start Condition: The SDA line switches from a high voltage level
to a low voltage level before the SCL line switches from high to
Data Transfer low
• Stop Condition: The SDA line switches from a low voltage level to
Protocol a high voltage level after the SCL line switches from low to high
• Read/Write Bit: A single bit specifying whether the master is
sending data to the slave (low voltage level) or requesting data
from it (high voltage level).
• ACK/NACK Bit: Each frame in a message is followed by an
acknowledge/no-acknowledge bit. If an address frame or data
frame was successfully received, an ACK bit is returned to the
sender from the receiving device
190
Start and
Stop Bit in
I2C
191
Sending Data to a Slave Device
• The master device sends the start condition
• The master device sends the 7 address bits which corresponds to the slave device to be targeted
• The master device sets the Read/Write bit to ‘0’, which signifies a write
• Now two scenarios are possible:
• If no slave device matches with the address sent by the master device, the next ACK/NACK
bit stays at ‘1’ (default). This signals the master device that the slave device identification is
unsuccessful. The master clock will end the current transaction by sending a Stop condition
or a new Start condition
• If a slave device exists with the same address as the one specified by the master device, the
slave device sets the ACK/NACK bit to ‘0’, which signals the master device that a slave device
is successfully targeted
• If a slave device is successfully targeted, the master device now sends 8 bits of data which is
only considered and received by the targeted slave device. This data means nothing to the
remaining slave devices
• If the data is successfully received by the slave device, it sets the ACK/NACK bit to ‘0’, which
signals the master device to continue
• The previous two steps are repeated until all the data is transferred
• After all the data is sent to the slave device, the master device sends the Stop condition which
signals all the slave devices that the current transaction has ended 192
I2C Write
193
Reading Data from a Slave Device
• The master device sets the Read/Write bit to ‘1’ instead of ‘0’ which signals
the targeted slave device that the master device is expecting data from it
• The 8 bits corresponding to the data block are sent by the slave device and
the ACK/NACK bit is set by the master device
• Once the required data is received by the master device, it sends a ACK/
NACK bit. Then the slave device stops sending data and releases the SDA
line
• If the master device to read data from specific internal location of a slave
device, it first sends the location data to the slave device using the steps in
previous scenario. It then starts the process of reading data with a repeated
start condition
194
I2C Read
195
Timing
Diagram of
I2C
196