MODULE 3: 8051 Programming in C: Microcontroller Notes:18EE52
MODULE 3: 8051 Programming in C: Microcontroller Notes:18EE52
Structure
3 a)
Objectives
Compilers produce hex files that we download into the ROM of the microcontroller. The size
of the hex file produced by the compiler is one of the main concerns of microcontroller
programmers, for two reasons:
Following are some of the major reasons for writing programs in C instead of Assembly:
1. Unsigned char
A. Since the 8051 is an 8-bit microcontroller, the character data type is the most natural
choice for many applications. The unsigned char is an 8-bit data type that takes a
value in the range of 0 – 255 (00 – FFH). It is one of the most widely used data types
for the 8051. In many situations, such as setting a counter value.
B. Where there is no need for signed data we should use the unsigned char instead of the
signed char. Remember that C compilers use the signed char as the default if we do
not put the keyword unsigned in front of the char (see Example 1-1). We can also use
the unsigned char data type for a string of ASCII characters, including extended
ASCII characters. Example 1-2 shows a string of ASCII characters. See Example 1-3
for toggling ports.
C. In declaring variables, we must pay careful attention to the size of the data and try to
use unsigned char instead of int if possible. Because the 8051 has a limited number of
registers and data RAM locations, using the int in place of the char data type can lead
to a larger size hex file. Such a misuse of the data types in compilers such as
Microsoft Visual C++ for x86 IBM PCs is not a significant issue.
Example 1-1
Example 1-2
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[ ] = “0,1,2,3,4,5,A,B,C,D”;
Unsigned char z;
For(z=0;z<=10;z++)
P1=mynum(z);
}
Example 1-3
Write an 8051 C program to toggle all the bits of PI continuously.
Solution:
// Toggle PI forever
include <reg51.h>
void main(void)
2. Signed char
The signed char is an 8-bit data type that uses the most significant bit (D7 of D7 – DO) to
represent the – or + value. As a result, we have only 7 bits for the magnitude of the signed
number, giving us values from -128 to +127. In situations where + and – are needed to
represent a given quantity such as temperature, the use of the signed char data type is a must.
Again notice that if we do not use the keyword unsigned, the default is the signed value. For
that reason we should stick with the unsigned char unless the data needs to be represented as
signed numbers.
Example 1-4
3. Unsigned int
1. The unsigned int is a 16-bit data type that takes a value in the range of 0 to 65535
(0000 – FFFFH). In the 8051, unsigned int is used to define 16-bit variables such as
memory addresses. It is also used to set counter values of more than 256.
2. Since the 8051 is an 8-bit microcontroller and the int data type takes two bytes of
RAM, we must not use the int data type unless we have to.
3. Since registers and memory accesses are in 8-bit chunks, the misuse of int variables
will result in a larger hex file. Such misuse is not a big deal in PCs with 256
megabytes of memory, 32-bit Pentium registers and memory accesses, and a bus
speed of 133 MHz.
4. However, for 8051 programming do not use unsigned int in places where unsigned
char will do the job. Of course the compiler will not generate an error for this misuse,
but the overhead in hex file size is noticeable.
5. Also in situations where there is no need for signed data (such as setting counter
values), we should use unsigned int instead of signed int.
6. This gives a much wider range for data declaration. Again, remember that the C
compiler uses signed int as the default if we do not use the keyword unsigned.
4. Signed int
Signed int is a 16-bit data type that uses the most significant bit (015 of D15 – DO) to
represent the – or + value. As a result, we have only 15 bits for the magnitude of the number,
or values from -32,768 to +32,767.
Example 1-5
Write an 8051 C program to toggle bit DO of the port P1 (Pl.0) 50,000 times.
In creating a time delay using a for loop, we must be mindful of three factors that can affect
the accuracy of the delay.
1. The 8051 design. Since the original 8051 was designed in 1980, both the fields
of 1C technology and microprocessor architectural design have seen great
advancements.The number of machine cycles and the
number of clock periods per machine cycle vary among different versions of
the 8051/52 microcontroller.
2. While the original 8051/52 design used 12 clock periods per machine cycle, many of
the newer generations of the 8051 use fewer clocks per machine cycle.
For example, the DS5000 uses 4 clock periods per machine cycle, while the
DS89C420 uses only one clock per machine cycle.
3. The crystal frequency connected to the XI – X2 input pins. The duration of the
clock period for the machine cycle is a function of this crystal frequency.
4. Compiler choice. The third factor that affects the time delay is the compiler
used to compile the C program. When we program in Assembly language, we
can control the exact instructions and their sequences used in the delay sub
routine. In the case of C programs, it is the C compiler that converts the C
statements and functions to Assembly language instructions. As a result, dif
ferent compilers produce different code. In other words, if we compile a given
8051 C programs with different compilers, each compiler produces different
hex code.
Example 1-6
Write an 8051 C program to toggle bits of PI continuously forever with some delay.
Solution:
// Toggle PI forever with some delay in between “on” and “off”,
include <reg51.h>
Example 1-7
Write an 8051 C program to toggle the bits of PI ports continuously with a 250 ms delay.
Solution:
The program below is tested for the DS89C420 with XTAL = 11.0592 MHz.
Example 1-8
Example 1-10
Write an 8051 C program to get a byte of data from PI, wait 1/2 second, and then send it to
P2.
Solution:
Example 1-11
Write an 8051 C program to get a byte of data from PO. If it is less than 100, send it to
PI; otherwise, send it to P2.
Solution:
Example 1-12
Write an 8051 C program to toggle only bit P2.4 continuously without disturbing the rest of
the bits of P2.
Solution:
Example 1-13
Write an 8051 C program to monitor bit PI.5. If it is high, send 55H to PO; otherwise,
sendAAHtoP2.
Solution:
Example 1-14
A door sensor is connected to the P 1.1 pin, and a buzzer is connected to PI.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:
Example 1-15
The data pins of an LCD are connected to PI. The information is latched into the LCD
whenever its Enable pin goes from high to low. Write an 8051 C program to send “The Earth
is but One Country” to this LCD.
Solution:
Example 1-16
Write an 8051 C program to get the status of bit Pl.0, save it, and send it to P2.7 continuously.
Solution:
Example 1-17
Write an 8051 C program to toggle all the bits of PO, P1, and P2 continuously with a
250 ms delay.’ Use the sfr keyword to declare the port addresses.
Example 1-18
Write an 8051 C program to get the status of bit Pl.O, save it, and send it to P2.7
continuously.
Solution:
Bit-wise operators in C
1. While every C programmer is familiar with the logical operators AND (&&), OR (||),
and NOT (!), many C programmers are less familiar with the bitwise operators AND
(&), OR (|), EX-OR (^), Inverter (~), Shift Right (»), and Shift Left («).
2. These bit-wise operators are widely used in software engineering for embedded
systems and control; consequently, understanding and mastery of them are critical in
microprocessor-based system design and interfacing. See Table 1-3.
Example 1-19
Run the following program on your simulator and examine the results.
Solution:
#include <reg51.h> void main (void)
{
P0 = 0×35 & OxOF; //ANDing
Pl = 0×04 | 0×68; //ORing
P2= 0×54 * 0×78; //XORing
P0= -0×55; //inversing
Pl= Ox9A » 3; //shifting right 3 times
P2= 0×77 » 4; //shifting right 4 times
p0= 0×6 « 4; //shifting left 4 times
Example 1-20
Write an 8051 C program to toggle all the bits of PO and P2 continuously with a 250 ms
delay. Use the inverting operator.
Solution:
The program below is tested for the DS89C420 with XTAL = 11.0592 MHz.
Example 1-21
Write an 8051 C program to toggle all the bits of PO, PI, and P2 continuously with a 250 ms
delay. Use the Ex-OR operator.
Solution:
Example 1-22
Write an 8051 C program to get bit Pl.0 and send it to P2.7 after inverting it.
Solution:
Example 1-23
Write an 8051 C program to read the P1.0 and P1.1 bits and issue an ASCII character to PO
according to the following table.
a)ASCII numbers
On ASCII keyboards, when the key “0″ is activated, “Oil 0000″ (30H) is provided to
the computer. Similarly, 31H (Oil 0001) is provided for the key “1″, and so on, as shown in
Table 1-4.
After this conversion, the packed BCD numbers are processed and the result will be in
packed BCD format Chapter 16discusses the RTC chip and uses the BCD and ASCII
conversion programs shown in Examples 1-24 and 1-25.
Example 1-24
Example 7-25
4. The checksum byte is an extra byte that is tagged to the end of a series of bytes of
data. To calculate the checksum byte of a series of bytes of data, the following steps
can be taken.
5. Add the bytes together and drop the carries.
1. Take the 2′s complement of the total sum. This is the checksum byte, which
becomes the last byte of the series.
2. To perform the checksum operation, add all the bytes, including the checksum
byte. The result must be zero. If it is not zero, one or more bytes of data have
been changed (corrupted).
Example 1-26
Assume that we have 4 bytes of hexadecimal data: 25H, 62H, 3FH, and 52H. (a) Find the
checksum byte, (b) perform the checksum operation to ensure data integrity, and (c) if the
second byte 62H has been changed to 22H, show how checksum detects the error.
Solution:
Example 1-27
Write an 8051 C program to calculate the checksum byte for the data given in Example 7-26.
Solution:
Example 1-28
Write an 8051 C program to perform step (b) of Example 7-26. If data is good, send ASCII
character ‘G’ to PO. Otherwise send ‘B’ to PO.
Solution:
Example 1-29
Write an 8051 C program to convert 11111101 (FD hex) to decimal and display the digits on
PO, PI, and P2.
Solution:
Using the code (program) space for predefined data is the widely used option in the 8051.
RAM data space v. code data space
In the 8051 we have three spaces in which to store data. They are as follows:
1. The 128 bytes of RAM space with address range 00 – 7FH. (In the 8052, it is
256 bytes.) We can read (from) or write (into) this RAM space directly or indirectly
using the RO and Rl registers.
2. The 64K bytes of code (program) space with addresses of 0000 – FFFFH. This
64K bytes of on-chip ROM space is used for storing programs (opcodes) and
therefore is directly under the control of the program counter (PC).
3. There are two problems with using this code space for
data.
a) First, since it is ROM memory, we can burn our predefined data and
tables into it. But we cannot write into it during the execution of the program.
b) The second problem is that the more of this code space we use for data, the less
is left for our program code. For example, if we have an 8051 chip such as
DS89C420 with only 16K bytes of on-chip ROM, and we use 4K bytes of it to
store some look-up table, only 12K bytes is left for the code program. For
some applications this can be a problem. For this reason Intel created another
memory space called external memory especially for data.
4. The 64K bytes of external memory, which can be used for both RAM and ROM. This
64K bytes is called external since we must use the MOVX Assembly language
instruction to access it. At the time the 8051 was designed, the cost of on-chip ROM
was very high; therefore, Intel used all the on-chip ROM for code but allowed
connection to external RAM and ROM. In other words, we have a total of 128K bytes
of memory space since the off-chip or external memory space of 64K bytes plus the
64K bytes of on-chip space provides you a total of 128K bytes of memory space.
In Assembly language programming, as shown in Chapters 2 and 5, the 128 bytes of RAM
space is used mainly by register banks and the stack. Whatever remains is used for scratch
pad RAM. The 8051 C compiler first allocates the first 8 bytes of the RAM to bank 0 and
then some RAM to the stack. Then it starts to allocate the rest to the variables declared by the
C program. While in Assembly the default starting address for the stack is 08, the C compiler
moves the stack’s starting address to somewhere in the range of 50 – 7FH. This allows us to
allocate contiguous RAM locations to array elements.
In cases where the program has individual variables in addition to array elements, the 8051 C
compiler allocates RAM locations in the following order:
1. Bank 0 addresses 0-7
2. Individual variables addresses 08 and beyond
3. Array elements addresses right after variables
4. Stack addresses right after array elements
5. You can verify the above order by running Example 7-30 on your 8051 C simulator
and examining the contents of the data RAM space. Remember that array elements
need contiguous RAM locations and that limits the size of the array due to the fact
that we have only 128 bytes of RAM for everything. In the case of Example 1-31 the
array elements are limited to around 100.
Example 1-30
Compile and single-step the following program on your 8051 simulator. Examine the
contents of the 128-byte RAM space to locate the ASCII values.
Example 1-31
Write, compile, and single-step the following program on your 8051 simulator. Examine the
contents of the code space to locate the values.
To make the C compiler use the code space instead of the RAM space, we need to put the
keyword code in front of the variable declaration. The following are some examples:
Example 1-32
Compile and single-step the following program on your 8051 simulator. Examine the
contents of the code space to locate the ASCII values.
Solution:
Compiler variations
Example 1-33. It shows three different versions of a program that sends me string “HELLO”
to the PI port. Compile each program with the 8051 C compiler of your choice and compare
the hex file size. Then compile each program on a different 8051 C compiler, and examine
the hex file size to see the effectiveness of your C compiler.
Example 1-33
Compare and contrast the following programs and discuss the advantages and disadvantages
of each one.
Solution:
All the programs send out “HELLO” to PI, one character at a time, but they do it in different
ways. The first one is short and simple, but the individual characters are embedded into the
program. If we change the characters, the whole program changes. It also mixes the code and
data together. The second one uses the RAM data space to store array elements, therefore the
size of the array is limited. The third one uses a separate area of the code space for data. This
allows the size of the array to be as long as you want if you have the on-chip ROM. However,
the more code space you use for data, the less space is left for your program code. Both
programs (b) and (c) are easily upgradable if we want to change the string itself or make it
longer. That is not the case for program (a).
Serializing data is a way of sending a byte of data one bit at a time through a single pin of
microcontroller. There are two ways to transfer a byte of data serially:
1. Using the serial port. When using the serial port, the programmer has very
limited control over the sequence of data transfer. The detail of serial port data
transfer is discussed in Chapter 10.
2. The second method of serializing data is to transfer data one bit a time and control the
sequence of data and spaces in between them. In many new generations
of devices such as LCD, ADC, and ROM the serial versions are becoming popular
since they take less space on a printed circuit board.
Example 1-34
Write a C program to send out the value 44H serially one bit at a time via Pl.O. The LSB
should go out first.
Example 1-35
Write a C program to send out the value 44H serially one bit at a time via Pl.O. The
MSB should go out first.
Example 1-36
Write a C program to bring in a byte of data serially one bit at a time via PI .0. The LSB
should come in first.
The 8051 has two timers: Timer 0 and Timer 1. They can be used either as timers or as event
counters.
Basic registers of the timer
Both Timer 0 and Timer 1 are 16 bits wide. Since the 8051 has an 8-bit architecture, each 16-
bit timer is accessed as two separate registers of low byte and high byte. Each timer is
discussed separately.
Timer 0 registers
1. 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).
2. 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.
3. These registers can also be read like any other register. For example, “MOV R5 ,
THO” saves THO (high byte of Timer 0) in R5.
1. 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.
2. In each case, the lower 2 bits are used to set the timer mode and the upper 2 bits to
specify the operation.
Example 1-37
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 values from hex to binary. From Figure 9-3 we have:
1. TMOD = 00000001, mode 1 of Timer 0 is selected.
2. TMOD = 00100000, mode 2 of Timer 1 is selected.
1. TMOD = 00010010, mode 2 of Timer 0, and mode 1 of
Timer 1 are selected.
Clock source for timer
As you know, every timer needs a clock pulse to tick. What is the source of the clock pulse
for the 8051 timers? If C T = 0. the crystal frequency attached to the 8051 is the source of the
clock for the timer. This means that the size of the crystal frequency attached to the 8051 also
decides the speed at which the 8051 timer ticks. The frequency for the timer is always 1 12th
the frequency of the crystal attached to the 8051.
Example 1-38
Example 1-39
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.
Now that we have this basic understanding of the role of the TMOD register, we will look at
the timer’s modes and how they are programmed to create a time delay. Because modes 1 and
2 are so widely used, we describe each of them in detail.
Although various 8051-based systems have an XTAL frequency of 10 MHz to 40 MHz, we
will concentrate on the XTAL frequency of 11.0592 MHz. The reason behind such an odd
number has to do with the baud rate for serial communication of the 8051. XTAL = 11.0592
MHz allows the 8051 system to communicate with the IBM PC with no errors.
GATE
1. The other bit of the TMOD register is the GATE bit. Notice in the TMOD register of
that both Timers 0 and 1 have the GATE bit.
2. Every timer has a means of starting and stopping. Some timers do this by software,
some by hardware, and some have both software and hardware controls. The timers in
the 8051 have both.
3. The start and stop of the timer are 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.
4. The SETB instruction starts it, and it is stopped by the CLR instruction. These
instructions start and stop the timers as long as GATE = 0 in the TMOD register.
5. The hardware way of starting and stopping the timer by an external source is achieved
by making GATE = 1 in the TMOD register.
6. However, to avoid further confusion for now, we will make GATE = 0, meaning that
no external hardware is needed to start and stop the timers. In using software to start
and stop the timer where GATE = 0. all we need are the instructions “SETB TRx” and
“CLR TRx”.
To calculate the exact time delay and the square wave frequency generated on pin P1 .5, we
need to know the XTAL frequency.
The scientific calculator in the Accessories directory of Microsoft Windows can help you to
find the TH, TL values. This calculator supports decimal, hex, and binary calculations.
(a) in hex
(FFFF – YYXX + 1) X 1.085 us where YYXX are TH, TL initial values respectively. Notice
that values YYXX are in hex.
(b) in decimal
Convert YYXX values of the TH,TL register to decimal to get a NNNNN decimal number,
then (65536 – NNNNN) x 1.085 mircosec
Timer Delay Calculation for XTAL = 11.0592 MHz
Example 1-40
In the following program, we are creating a square wave of 50% duty cycle (with equal
portions high and low) on the PI.5 bit. Timer 0 is used to generate the time delay. Analyze the
program.
Solution:
In the above program notice the following steps.
1. TMOD is loaded.
2. FFF2H is loaded into THO – TLO.
3. P1.5 is toggled for the high and low portions of the pulse.
4. The DELAY subroutine using the timer is called.
5. In the DELAY subroutine, Timer 0 is started by the “SETB TRO” instruction.
1. Timer 0 counts up with the passing of each clock, which is provided by the
crystal
oscillator. As the timer counts up, it goes through the states of FFF3, FFF4,
FFF5,
FFF6, FFF7, FFF8, FFF9, FFFA, FFFB, and so on until it reaches FFFFH.
One more
clock rolls it to 0, raising the timer flag (TFO = 1). At that point, the JNB
instruction
falls through.
2. Timer 0 is stopped by the instruction “CLR TRO”. The DELAY subroutine
ends,
and the process is repeated.
Notice that to repeat the process, we must reload the TL and TH registers and start the timer
again.
Example 1-41
Calculate the amount of time delay in the DELAY subroutine generated by the timer. Assume
that XTAL = 11.0592 MHz.
Solution:
The timer works with a clock frequency of 1/12 of the XTAL frequency; therefore, we have
11.0592 MHz / 12 = 921.6 kHz as the timer frequency. As a result, each clock has a period of
T = 1 / 921.6 kHz = 1.085 (is. In other words, Timer 0 counts up each 1.085 us resulting in
delay = number of counts x 1.085 us.
The number of counts for the rollover is FFFFH – FFF2H = ODH (13 decimal). However, we
add one to 13 because of the extra clock needed when it rolls over from FFFF to 0 and raises
the TF flag. This gives 14 x 1.085 us = 15.19 us for half the pulse. For the entire period T = 2
x 15.19 (as = 30.38 (is gives us the time delay generated by the timer.
Example 1-42
Calculate the frequency of the square wave generated on pin P1. 5.
Solution:
In the time delay calculation of Example 9-5, we did not include the overhead due to
instructions in the loop. To get a more accurate timing, we need to add clock cycles due to the
instructions in the loop. To do that, we use the machine cycles from Table A-l in Appendix A,
as shown below.
Example 1-43
Find the delay generated by Timer 0 in the following code, using both of the methods of
Figure 3.3. Do not include the overhead due to instructions.
Making TH and TL both zero means that the timer will count from 0000 to FFFFH, and then
roll over to raise the TF flag. As a result, it goes through a total of 65536 states. Therefore,
we have delay = (65536 – 0) x 1.085 µs = 71.1065 ms.
Example 1-45
The following program generates a square wave on pin PL5 continuously using Timer 1 for a
time delay. Find the frequency of the square wave if XTAL =11.0592 MHz. In your
calculation do not include the overhead due to instructions in the loop.
In the above program notice the target of SJMP. In mode 1, the program must reload the TH,
TL register every time if we want to have a continuous wave. Now the calculation. Since
FFFFH – 7634H = 89CBH + 1 = 89CCH and 89CCH = 35276 clock count. 35276 x 1.085 us
= 38.274 ms for half of the square wave. The entire square wave length is 38.274 x 2 =
76.548 ms and has a frequency = 13.064 Hz.
Also notice that the high and low portions of the square wave pulse are equal. In the above
calculation, the overhead due to all the instructions in the loop is not included.
Example 1-46
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 us. This means that out of
many 1.085 us intervals we must make a 5 ms pulse. To get that, we divide one by the other.
We need 5 ms /•! .085 us = 4608 clocks. To achieve that we need to load into TL and TH the
value 65536 – 4608 = 60928 = EEOOH. Therefore, we have TH = EE and tt = on
Example 1-47
Assuming that XTAL = 11.0592 MHz, write a program to generate a square wave of 2 kHz
frequency on pin P1 .5.
Solution:
Look at the following steps.
1. T = 1 / f = 1 / 2 kHz = 500 µs the period of the square wave.
2. 1/2 of it for the high and low portions of the pulse is 250 µs.
3. 250 us / 1.085 us = 230 and 65536 – 230 = 65306. which in hex is FF1AH.
4. TL = 1AH and TH = FFH. all in hex. The program is as follows.
Example 1-48
Assuming XTAL = 11.0592 MHz, write a program to generate a square wave of 50 Hz
frequency on pin P2.3.
Solution:
Look at the following steps.
1. T — 1 / 50 Hz = 20 ms, the period of the square wave.
2. 1/2 of it for the high and low portions of the pulse = 10 ms
3. 10 ms / 1.085 us = 9216 and 65536 – 9216 = 56320 in decimal, and in hex it is
DCOOH.
4. TL = 00 and TH = DC (hex)
As we have seen in the examples so far, the size of the time delay depends on two factors,
(a) The crystal frequency, and
(b) The timer’s 16-bit register in mode 1.
Both of these factors are beyond the control of the 8051 programmer. We saw earlier that the
largest time delay is achieved by making both TH and TL zero.
Example 1-49
Examine the following program and find the time delay in seconds. Exclude the overhead due
to the instructions in the loop.
Solution:
TH – TL = 0108H = 264 in decimal and 65536 – 264 = 65272. Now 65272 x 1.085 µs =
70.820 ms, and for 200 of them we have 200 x 70.820 ms = 14.164024 seconds.
3.7.4 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.
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.
Example 1-50
Assuming that XTAL = 11.0592 MHz. find (a) the frequency of the square wave generated
on pin P 1.0 in the following program, and (b) the smallest frequency achievable in this
program, and the TH value to do that.
Solution:
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 us = 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; as a result T = 2 x 272.33 us = 544.67 us and the frequency = 1.83597
kHz.
1. To get the smallest frequency, we need the largest T and that is achieved when TH
= 00.
2. In that case, we have T = 2 x 256 x 1.085 µs = 555.52 µs and the frequency
= 1.8kHz.
Example 1-51
Example 1-52
Assuming that we are programming the timers for mode 2, find the value (in hex) loaded into
TH for each of the following cases.
You can use the Windows scientific calculator to verify the results provided by the assembler.
In Windows calculator, select decimal and enter 200. Then select hex, then +/- to get the TH
value. Remember that we only use the right two digits and ignore the rest since our data is an
8-bit data. The following is what we get.
Solution:
For the TH value in mode 2, the conversion is done by the assembler as long as we enter a
negative number. This also makes the calculation easy. Since we are using 150 clocks, we
have time for the DELAY subroutine = 150 x 1.085 µs = 162 µs. The high portion of the
pulse is twice that of the low portion (66% duty cycle). Therefore, we have: T = high portion
+ low portion = 325.5 (is + 162.25µs = 488.25 µs and frequency = 2.048 kHz.
Notice that in many of the time delay calculations we have ignored the clocks caused by the
overhead instructions in the loop. To get a more accurate time delay, and hence frequency,
you need to include them. If you use a digital scope and you don’t get exactly the same
frequency as the one we have calculated, it is because of the overhead associated with those
instructions.
Example 1-54
Assuming that clock pulses are fed into pin Tl, write a program for counter 1 in mode
2 to count the pulses and display the state of the TL1 count on P2.
In Example 1-54, we use Timer 1 as an event counter where it counts up as clock pulses are
fed into pin 3.5. These clock pulses could represent the number of people passing through an
entrance, or the number of wheel rotations, or any other event that can be converted to pulses.
In Example 1-54, the TL data was displayed in binary. In Example 9-19, the TL registers are
converted to ASCII to be displayed on an LCD.
Example 1-55
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 THO to -60.
Solution:
To display the TL count on an LCD, we must convert 8-bit binary data to ASCII. See Chapter
6 for data conversion.
Figure 3.3 :Timer 0 with External Input (Mode 2) Figure 3.4 Timer 1 with External
Input (Mode 2)
As another example of the application of the timer with C/T = 1, we can feed an external
square wave of 60 Hz frequency into the timer. The program will generate the second, the
minute, and the hour out of this input frequency and display the result on an LCD. This will
be a nice digital clock, but not a very accurate one.
Table 1.5 : Equivalent Instructions for the Timer Control Register (TCON)
the control of the user of that product. However, a switch connected to pin P3.2 can
be used to turn on and off the timer, thereby shutting down the alarm.
To verify this very important point, compare parts (a) and (b) of Example 9-21 since they
have been tested on these two chips with the same speed and C compiler.
Timers 0 and 1 delay using mode 1 (16-bit non auto-reload)
Examples 9-21 and 9-22 show 8051 C programming of the timers 0 and 1 in mode 1 (16-bit
non-auto reload). Examine them to get familiar with the syntax.
Timers 0 and 1 delay using mode 2 (8-bit auto-reload)
Study these examples below to get familiar with the syntax.
Example 1-57
Write an 8051 C program to toggle only bit PI.5 continuously every 50 ms. Use Timer 0,
mode 1 (16-bit) to create the delay. Test the program (a) on the AT89C51 and (b) on the
DS89C420.
Solution:
Example 1-58
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:
Example 1-59
Write an 8051 C program to toggle only pin PI.5 continuously every 250 ms. Use Timer 0,
mode 2 (8-bit auto-reload) to create the delay.
Solution:
256-23 = 233
23 x 1.085 us = 25 us
25 us x 250 x 40 = 250 ms by calculation.
However, the scope output does not give us this result. This is due to overhead of the for loop
in C. To correct this problem, we put 36 instead of 40.
Example 1-60
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:
Example 1-61
A switch is connected to pin PI.2. Write an 8051 C program to monitor SW and create
the following frequencies on pin PI.7:
SW=0: 500 Hz
SW=1: 750 Hz
Use Timer 0, mode 1 for both of them.
Solution:
A timer can be used as a counter if we provide pulses from outside the chip instead of using
the frequency of the crystal oscillator as the clock source. By feeding pulses to the TO (P3.4)
and Tl (P3.5) pins, we turn Timer 0 and Timer 1 into counter 0 and counter 1, respectively.
Study the next few examples to see how timers 0 and 1 are programmed as counters using the
C language.
Example 1-62
Assume that a 1-Hz external clock is being fed into pin Tl (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
PI. Start the count at OH.
Solution:
Example 1-63
Assume that a 1-Hz external clock is being fed into pin TO (P3.4). Write a C program for
counter 0 in mode -1 (16-bit) to count the pulses and display the THO and TLO registers on
P2 and PI, respectively.
Solution:
Example 1-64
Assume that a 2-Hz external clock is being fed into pin Tl (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 PO, PI, and P2 where
PO has the least significant digit. Set the initial value of THO to 0.
Solution:
To display the TL1 count we must convert 8-bit binary data to ASCII. See Chapter 7 for data
conversion. The ASCII values will be shown in binary. For example, ’9′ will show as
00111001 on ports.
Example 1-65
Assume that a 60-Hz external clock is being fed into pin TO (P3.4). Write a C program for
counter 0 in mode 2 (8-bit auto-reload) to display the seconds and minutes on PI and P2,
respectively.
Solution:
Outcomes