Microcontroller 8051 Programming in C
Microcontroller 8051 Programming in C
Microcontroller 8051 Programming in C
8051 Timer programming in Assembly and C: Programming 8051 timers, Counter programming, Programming
timers 0 and 1 in 8051 C
Timer 0 registers
The 16-bit register of Timer 0 is accessed as low byte and high byte. The low byte register is called TLO (Timer 0 low
byte) and the high byte register is referred to as THO (Timer 0 high byte). These registers can be accessed like any
other register, such as A, B, RO, Rl, R2, etc. For example, the instruction “MOV TLO, #4FH” moves the value 4FH
into TLO, the low byte of Timer 0. These registers can also be read like any other register. For example, “MOV R5 ,
THO” saves THO (high byte of Timer 0) in R5.
Timer 1is also 16 bits, and its 16-bit register is split into two bytes, referred to as TLl (Timer 1 low byte) and TH1
(Timer 1 high byte). These registers are accessible in the same way as the registers of Timer 0.
Both timers 0 and 1 use the same register, called TMOD, to set the various timer operation modes. TMOD is an 8-bit
register in which the lower 4 bits are set aside for Timer 0 and the upper 4 bits for Timer 1. In each case, the lower 2
bits are used to set the timer mode and the upper 2 bits to specify the operation.
M1, MO
M0 and M1 select the timer mode. As shown above, there are four modes: 0, 1, 2 and 3. Mode 0 is a 13-bit timer, mode
1 is a 16-bit timer, mode 2 is an 8-bit timer, and mode 3 is a 8-bit split timer.
C/₸ (clock/timer)
This bit in the TMOD register is used to decide whether the timer is used as a delay generator or an event counter. If C/
₸ = 0, it is used as a timer for time delay generation. The clock source for the time delay is the crystal frequency of the
8051.
Ex-1: Indicate which mode and which timer is selected for each of the following.
(a) MOV TMOD, #01H (b) MOV TMOD, #20H (c) MOV TMOD, #12H
Solution:
Ex-3: Find the timer’s clock frequency and its period for various 8051-based systems, with the following crystal
frequencies. a) 13MHz b) 16MHz c) 11.0592 MHz
Solution:
b) f = 1/12×16×106 = 1.333MHz
T = 1/1.333×106 = 0.75 µs
c) f = 1/12×11.0592×106 = 921.6KHz
T = 1/921.6×106 = 1.085 µs
GATE
The timers in 8051 have two means of starting & stopping: i) controlled by way of software by the TR (timer start)
bits TRO and TR1. This is achieved by the instructions “SETB TR1” and “CLR TR1″ for Timer 1, and “SETB TRO”
and “CLR TRO” for Timer 0. The SETB instruction starts it, and it is stopped by the CLR instruction. ii) Controlled by
hardware switch connected to external interrupt pins. Selection of these two means is done using the GATE bit.
Software way of starting & stopping the timers is enabled when GATE = 0 in the TMOD register. The hardware way
of starting and stopping the timer by an external source is achieved by making GATE = 1 in the TMOD register.
Ex-4: Find the value for TMOD if we want to program Timer 0 in mode 2, use 8051 XTAL for the clock source,
and use instructions to start and stop the timer.
Solution:
TMOD = 0000 0010 Timer 0, mode 2, XTAL clock source and internal control for start & stop
TCON register:
bit addressable as TCON.0 to TCON.7
7 6 5 4 3 2 1 0
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
Timer Control Interrupt control
Total delay = count × 1.085 µs, where count = (FFFF – YYXX+1), YYXX are TH & TL values initially
i) Time delay:
Number of counts for roll over if the loaded value in TH:TL register FFF2h
Count = FFFFh - FFF2h = 0Dh (13d) + 1 for the extra clock to roll over from FFFF h to 0000h & raise the TF flag.
i.e., 13+1=14
Delay = 14×1.085µs= 15.19µs
Dept. of EEE, SJBIT
6
Microcontroller 15EE52
Cycles
Here: MOV TL0, #0F2h ; low byte 2
MOV TH0, #0FFh ; high byte 2
CPL P1.5 ; toggle P1.5 1
ACALL Delay 2
SJMP Here ; repeat 2
; delay using timer 0
Delay: SETB TR0 ; start timer 0 1
Again: JNB TF0, Again ; monitor timer 0 flag until it rolls over 14
CLR TR0 ; stop timer 0 1
CLR TF0 ; clear timer 0 flag 1
RET 2
Total 28
T = 2x28x1.085µs = 60.76 µs
F = 16458.2 Hz
Ex-6: Find the delay generated by Timer 0 in the following code. Do not include the overhead due to
instructions.
1. In hexadecimal: (FFFF – B83E + 1) = 47C2H= 18370 in decimal and 18370 x 1.085 µs = 19.93145ms.
2. In Decimal: Since TH:TL = B83EH = 47166 (in decimal) we have 65536 – 47166 = 18370.
This means that the timer counts from B83EH to FFFFH. This plus rolling over to
0 goes through a total of 18370 clock cycles, where each clock is 1.085 µs in duration. Therefore, we have 18370
x 1.085 µs = 19.93145 ms as the width of the pulse.
Ex-7: Calculate the Time delay generated in the below program and also find the largest time delay generated
considering XTAL = 22 MHz.
CLR P1.3 ; clear P1.3
MOV TMOD, #10H ; Timer 1, mode
MOV TH0, #0FFH ; load high byte value
MOV TL0, #00H ; load low byte
SETB P1.3 ; set bit P1.3
SETB TCON.6 ;TR1 is set to start Timer 1
AGAIN: JNB TCON.7, AGAIN ; monitor Timer 1 flag
CLR TCON.6 ; stop Timer 1 by making TR1=0
CLR TCON.7 ; clear Timer 1 flag for next round
CLR P1.3 ; clear the port for next round
Solution:
For a crystal frequency of 22 MHz, the value of the instruction cycle = 1/12 of 22 MHz = 1.833 MHz and T=0.546 µs.
i) Delay generated:
The delay is calculated as FFFFH – FF00H = FFH = 255+1 = 256.
Delay = 256x0.546 = 139.2µs.
ii) Maximum delay:
The maximum delay possible is when both TH and TL stores values of 00.
The FFFFH - 0000 = FFFFH = 65,535+1=65,536.
DELAY = 65,536X0.546=35,782µs = 35.75ms.
Ex-8: Assume that XTAL = 11.0592 MHz. What value do we need to load into the timer’s registers if we want to
have a time delay of 5 ms (milliseconds)? Show the program for Timer 0 to create a pulse width of 5 ms
on P2.3.
Solution:
Since XTAL = 11.0592 MHz, the counter counts up every 1.085 µs.
No. of clocks required to generate 5ms using 1.085 µs pulse is = 5 ms/ 1.085 µs = 4608 clocks.
Value to load into timer registers TH0:TL0 = 65536 – 4608 = 60928 = EEOOH.
Therefore, we have TH0 = EEh and TL0 = 00h.
For a crystal frequency of 22 MHz, the value of the instruction cycle = 1/12 of 22 MHz = 1.833 MHz and T=0.546 µs.
Ex-11: Assuming XTAL=22 MHZ, Write A Program to generate a pulse train of 2 seconds period on pin P2.4.
Use Timer 1 in mode1.
Solution:
For a crystal frequency of 22 MHz, the value of the instruction cycle = 1/12 of 22 MHz = 1.833 MHz and T=0.546 µs.
The maximum delay possible is when both TH and TL stores values of 00.
The FFFFH - 0000 = FFFFH = 65,535+1=65,536.
DELAY = 65,536X0.546=35,782µs = 35.75ms.
Calculation=28x35.75ms=1001ms.
Solution:
For a crystal frequency of 22 MHz, the value of the instruction cycle = 1/12 of 22 MHz = 1.833 MHz and T=0.546 µs.
This means first creating a delay of 50ms ON time and 50ms OFF time, followed by five repetitions of 10ms ON time
and 10ms OFF time.
To generate a delay of 50ms, a 10ms delay is repeated 5 times.
Mode 0
Mode 0 is exactly like mode 1 except that it is a 13-bit timer instead of 16-bit. The 13-bit counter can hold values
between 0000 to 1FFFH in TH – TL. Therefore, when the timer reaches its maximum of 1FFH, it rolls over to 0000,
and TF is raised.
Mode 2 programming
The following are the characteristics and operations of mode 2.
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 TRO” for Timer 0 and “SETB TR1” for Timer 1. This is just like mode 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 high the TF (timer flag). If we are using Timer 0, TFO goes
high; if we are using Timer 1, TF1 is raised.
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.
It must be emphasized that mode 2 is an 8-bit timer. However, it has an auto-reloading capability. In auto-reload, TH is
loaded with the initial count and a copy of it is given to TL. This reloading leaves TH unchanged, still holding a copy
of the original value. This mode has many applications, including setting the baud rate in serial communication.
Ex-13: Assuming that XTAL = 11.0592 MHz, find (a) the frequency of the square wave generated on pin P1.0 in
the following program, and (b) the smallest frequency achievable in this program, and the TH value to
do that.
a) First notice the target address of SJMP. In mode 2 we do not need to reload TH since it is auto-reload. Now (256 –
05) x 1.085 µs = 251 x 1.085 µs = 272.33 µs is the high portion of the pulse.
Since it is a 50% duty cycle square wave, the period T is twice that;
T = 2 x 272.33 µs = 544.67 µs and the f = 1.83597 kHz.
b) To get the smallest frequency, we need the largest T and that is achieved when TH= 00. In that case, we have T = 2
x 256 x 1.085 µs = 555.52 µs and the frequency = 1.8kHz.
Ex-14: Assuming that XTAL=22MHz, write a program to generate a square wave of frequency 1 kHz on pin
P1.2.
Solution:
For a crystal frequency of 22 MHz, the value of the instruction cycle = 1/12 of 22 MHz = 1.833 MHz and T=0.546 µs.
The smallest frequency possible in this setup is when the delay is maximum. Largest delay is when TH reduces to 00
from FF, i.e., delay is 256x0.546 µs = 139µs.
T = 2x139 = 278µs i.e., the smallest frequency is 3.6 kHz. Hence, to get a smaller frequency, we need to use a register
for creating the additional delay.
To get a delay of 0.5ms, we need 0.5ms/0.546µs=915 cycles.
To use the TH register to get a delay of 915/5=183cycles, and a register R0 to get the rest of it.
183 cycles have to be covered by the TH register when it rolls from its count value to FFH.
183=B7H. The TH value should be FFH-B7H=48H.
Thus the effective delay is 183x0.546x5 = 499µs = 0.5ms, T = 0.5msx2 =1ms and frequency = 1 kHz.
Ex-15: Assuming that we are programming the timers for mode 2, find the value (in hex) loaded into TH for
each of the following cases.
a) MOV TH1, # -200
b) MOV TH1, # -3
c) MOV TH0, # -48
d) MOV TH0, # -60
e) MOV TH1, # -12
Solution:
The following is what we get.
Decimal 2’s complement (TH value)
-200 38H
-60 C4H
-3 FDH
-12 F4H
-48 D0H
Since the timer is 8-bit in mode 2, we can let the assembler calculate the value for TH. For example, in “MOV
TH1 ,#-10 0″, the assembler will calculate the -100 = 9C, and makes TH1 = 9C in hex.
Counter Programming:
When the timer/counter is used as a timer, the 8051's crystal is used as the source of the frequency. When it is used as a
counter, however, it is a pulse outside the 8051 that increments the TH, TL register. In counter mode, the TMOD and
TH, TL registers are the same as for the timer; they even have the same names. The timer’s are the same as well.
Ex-1: Design a counter for counting the pulses of an input signal. The pulses to be counted are fed to pin P3.4.
XTAL = 22 MHz.
Solution:
ORG 0000H
RPT: MOV TMOD, #15H ; timer 1 as timer and Timer 0 as counter
SETB P3.4 ; make port P3.4 an input port
MOV TL0, #00 ; clear TL0
MOV TH0, #00 ; clear TH0
SETB TR0 ; start counter
MOV R0, #28 ; R0=28, to time 1 second
AGAIN: MOV TL1, #00H ; TL1=0
MOV TL1, #00H ; TL1=0
SETB TR1 ; start Timer 1
BACK: JNB TF1, BACK ; test Timer 1 flag
CLR TF1 ; clear Timer 1 flag
CLR TR1 ; stop Timer 1
DJNZ R0, AGAIN ; repeat the loop until R0=0
MOV A, TL0 ; since 1 sec has elapsed, check TL0
MOV P2, A ; move TL0 to port 2
MOV A, TH0 ; move TH0 to ACC
MOV P1, A ; move it to port 1
SJMP RPT ; repeat
END
Ex-2: Assume that a 1-Hz frequency pulse is connected to input pin 3.4. Write a program to display counter 0
on an LCD. Set the initial value of TH0 to -60.
Solution:
To display the TL count on an LCD, we must convert 8-bit binary data to ASCII.
In 8051 C we can access the timer registers TH, TL, and TMOD directly using the reg51.h header file.
Ex-1: Write a 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) //repeat forever
{
P1=0x55; //toggle all bits of P1
T0Delay ( ); //delay size unknown
P1 = 0xAA; //toggle all bits of P1
T0DELAY ();
}
}
void T0Delay ( )
{
TMOD=0x01; //Timer 0, Mode1
TL0=0x00; //load TL0
TH0=0x35; //load TH0
TR0=1; //turn on T0
While (TF0= = 0); //wait for TF0 to roll over
TR0=0; //turn off T0
TF0=0; // clear TF0
}
FFFFH - 3500H = CAFFH = 51967+1 = 51968
51968x1.085µs=56.384 ms is the approximate delay.
#include <reg51.h>
void T0M1Delay(void);
sbit mybit=P1^5;
void main(void)
{
while (1)
{
mybit=~mybit; //toggle P1.5
T0M1Delay ( ); //Timer 0, mode 1 (16-bit)
}
}
void T0M1Delay (void )
{
TMOD=0x01; //Timer 0, Mode1 (16-bit)
TL0=0xFD; //load TL0
TH0=0x4B; //load TH0
TR0=1; //turn on T0
While (TF0= = 0); //wait for TF0 to roll over
TR0=0; //turn off T0
TF0=0; // clear TF0
}
Ex-3: 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:
#include <reg51.h>
void T1M1Delay(void);
void main(void)
{
unsigned char x;
P2=0x55;
while (1)
{
P2= ~ P2; // toggle all bits of P2
for (x=0; x<20; x++)
T1M1Delay( );
}
}
void T1M1Dealy(void)
{
Dept. of EEE, SJBIT
16
Microcontroller 15EE52
TMOD=0x10; //Timer 1, Mode1 (16-bit)
TL1=0xFE; //load TL1
TH1=0XA5; //load TH1
TR1=1; //turn on T1
While (TF1= = 0); //wait for TF1 to roll over
TR1=0; //turn off T1
TF1=0; // clear TF1
}
Ex-4: Write an 8051 C program to toggle only pin P1.5 continuously every 250ms. Use Timer 0, mode2 (8-bit
auto-reload) to create the delay.
Solution:
#include <reg51.h>
void T0M2Delay(void);
sbit mybit=P1^5;
void main(void)
{
unsigned char x, y;
while (1)
{
mybit = ~mybit // toggle P1.5
for (x=0; x=250; x++) //due to for loop overhead
for(y=0; y=36;y++) //we put 36 and not 40
T0M2Delay( );
}
}
void T0M2Delay (void )
{
TMOD=0x02; //Timer 0, Mode2 (8-bit auto-reload)
TH0=-23; //load TH0 (auto-reload value)
TR0=1; //turn on T0
While (TF0= = 0); //wait for TF0 to roll over
TR0=0; //turn off T0
TF0=0; // clear TF0
}
256 – 23 = 233
23x1.085µs = 25µs
25µsx250x40 = 250ms by calculation.
Ex-5: Write an 8051 C program to create a frequency of 2500 Hz on pin P2.7. Use Timer 1, mode 2 to create the
delay.
Solution:
Dept. of EEE, SJBIT
17
Microcontroller 15EE52
#include <reg51.h>
void T1M2Delay(void);
sbit mybit=P2^7;
void main(void)
{
unsigned char x, y;
while (1)
{
mybit = ~mybit // toggle P2.7
T1M2Delay( );
}
}
void T1M2Delay (void )
{
TMOD=0x20; //Timer 1, Mode2 (8-bit auto-reload)
TH0=-184; //load TH1 (auto-reload value)
TR1=1; //turn on T1
while(TF0= = 0); //wait for TF0 to roll over
TR1=0; //turn off T1
TF1=0; // clear TF1
}
1/2500Hz=400µs
400µs/2 = 200 µs
200µs/1.085µs=184
Ex-6: 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:
#include <reg51.h>
sbit mybit=P1^5;
sbit SW=P1^7;
void T0M1Delay(unsigned char);
void main(void)
{
SW=1; //make P1.7 an input
while (1)
{
mybit = ~mybit // toggle P1.5
if(SW= = 0) //check switch
T0M1Delay(0);
else
T0M1Delay(1);
}
}
void T0M1Delay(unsigned char c);
{
TMOD=0x01;
Dept. of EEE, SJBIT
18
Microcontroller 15EE52
If (c= = 0)
{
TL0=0x67; //FC67
TH0=0xFC;
}
else
{
TL0=0x9A; //FD9A
TH0=0xFD;
}
TR0=1;
while(TF0= = 0);
TR0=0;
TF0=0;
}
FC67H = 64615
65536-64615=921
921x1.085µs=999.285µs
1/(999.285µsx2)=500Hz
Ex-7: 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 98-bit auto reload) to count up and display the state of the TL1 count on P1. Start count at 0H.
Solution:
#include <reg51.h>
sbit T1 = P3^5;
void main(void)
{
T1=1; // make T1 an input
TMOD = 0x60; //
TH1= 0; //set count to 0
While (1) //repeat forever
{
Do
{
TR1=1; //start timer
P1=TL1; //place value on pins
}
while(TF1= = 0); //wait here
TR1=0; //stop timer
TF1=0; //clear flag
}
}
Ex-8: 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 TH0 and TL0 registers on P2 and P1, respectively.
Solution:
#include <reg51.h>
void main(void)
{
T0=1; // make T0 an input
TMOD=0x05; //
TL0=0; //set count to 0
TH0=-0; //set count to 0
while (1) //repeat forever
{
do
{
TR0=1; //start timer
P1=TL0; //place value on pins
P2=TH0; //
}
while (TF0= = 0); //wait here
TR0=0; //stop timer
TF0=0;
}
}
Ex-9: Assume that a 2-Hz external clock is being fed into pin T1 (P3.5). Write a C program for counter 0 in
mode 2 (8-bit auto reload) 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 TH0 to 0.
Solution:
To display the TL1 count we must convert 8-bit binary data to ASCII.
#include <reg51.h>
void BinToASCII (unsigned char);
void main(void)
{
unsigned char value;
T1=1;
TMOD=0x06;
TH0=0;
while (1)
{
do
{
TR0=1;
value=TL0;
BinToASCII(value);
}
while (TF0= = 0);
Dept. of EEE, SJBIT
20
Microcontroller 15EE52
TR0=0;
TF=0;
}
}
void BinToASCII(unsigned char value) //see Chapter7
{
unsigned char x, d1,d2,d3;
x= value/10;
d1= value%10
d2= x/10;
d3 = x/10
p0 =30 | d1;
p1 =30 | d2;
p2 =30 | d3;
}
Ex-10: 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 (8-bit auto-reload) to display the seconds and minutes on P1 and P2, respectively.
Solution:
#include <reg51.h>
void ToTime (unsigned char);
void main(void)
{
unsigned char val;
T0=1;
TMOD=0x06; //T0, mode 2, counter
TH0=--60; //sec = 60 pulses
while (1)
{
Do
{
TR=1;
Sec=TL0;
ToTime(val);
}
while(TF= = 0);
TR0=0;
TF=0;
}
}
void ToTime (unsigned char val)
{
unsigned char sec, min;
min = value / 60;
sec = value %60;
P1 = sec;
P2 = min;
}
Dept. of EEE, SJBIT
21
Microcontroller 15EE52