Why program the 8051 in C?
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:
  1. Microcontrollers have limited on-chip ROM.
  2. The code space for the 8051 is limited to 64K bytes.
How does the choice of programming language affect the compiled program size? While Assembly language produces a hex file that is much smaller than C, programming in Assembly language is tedious and time consuming. C programming, on the other hand, is less time consuming and much easier to write, but the hex file size produced is much larger than if we used Assembly language. The following are some of the major reasons for writing programs in C instead of Assembly:
  1. It is easier and less time consuming to write in C than Assembly.
  2. C is easier to modify and update.
  3. You can use code available in function libraries.
  4. C code is portable to other microcontrollers with little or no modification.
    The study of C programming for the 8051 is the main topic of this chapter. In Section 7.1, we discuss data types and time delays. I/O programming is shown in Section 7.2. The logic operations AND, OR, XOR, inverter, and shift are discussed in Section 7.3. Section 7.4 describes ASCII and BCD conversions and checksums. In Section 7.5 we show how 8051 C compilers use the program (code) ROM space for data. Finally, in Section 7.6 data serialization for 8051 is shown.
    In this section we first discuss C data types for the 8051 and then provide code for time delay functions.
    C data types for the 8051
    Since one of the goals of 8051 C programmers is to create smaller hex files, it is worthwhile to re-examine C data types for 8051 C. In other words, a good understanding of C data types for the 8051 can help programmers to create smaller hex files. In this section we focus on the specific C data types that are most useful and widely used for the 8051 microcontroller.
Unsigned char

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.

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 7-1). We can also use the unsigned char data type for a string of ASCII characters, including extended ASCII characters. Example 7-2 shows a string of ASCII characters. See Example 7-3 for toggling ports.
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 7-2

Example 7-1

Run the above program on your simulator to see how PI displays values 30H, 31H, 32H. 33H. 34H. 35H. 41H. 42H, 43H, and 44H, the hex values for ASCII 0, 1, 2, and so on.

Example 7-3
Write an 8051 C program to toggle all the bits of PI continuously. Solution:
// Toggle PI forever ^include <reg51.h> void main(void)

Run the above program on your simulator to see how PI toggles continuously. Examine the asm code generated by the C compiler.
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 7-4

Run the above program on your simulator to see how PI displays values of 1, FFH, 2, FEH, 3, FDH, 4, and FCH, the hex values for +!,-!, +2, -2, and so on.
Unsigned int
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. 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. 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. 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. 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. 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.
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.
Sbit (single bit)
The sbit keyword is a widely used 8051 C data type designed specifically to access single-bit addressable registers. It allows access to the single bits of the SFR registers. As we saw in Chapter 5, some of the SFRs are bit^addressable. Among the SFRs that are widely used and are also bit-addressable are ports PO -P3. We can use sbit to access the individual bits of the ports as shown in Example 7-5.
Example 7-5
Write an 8051 C program to toggle bit DO of the port PI (Pl.O) 50,000 times.

Bit and sfr

The bit data type allows access to single bits of bit-addressable memory spaces 20 – 2FH. Notice that while the sbit data type is used for bit-addressable SFRs, the bit data type is used for the bit-addressable section of RAM space 20 -2FH. To access the byte-size SFR registers, we use the sfr data type. We will see the use of sbit, bit, and sfr data types in the next section.
Table 7-1; Some Widely Used Data Types for 8051 C

Time Delay
There are two ways to create a time delay in 8051 C:
  1. Using a simple for loop
  2. Using the 8051 timers
In either case, when we write a time delay we must use the oscilloscope to measure the duration of our time delay. Next, we use the for loop to create time delays. Discussion of the use of the 8051 timer to create time delays is postponed until Chapter 9.
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. As we saw in Chapter 3, the number of machine cycles and the
    number of clock periods per machine cycle vary among different versions of
    the 8051/52 microcontroller. 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 peri
    ods per machine cycle, while the DS89C420 uses only one clock per machine
  2. 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.
  3. 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.
For the above reasons, when we write time delays for C, we must use the oscilloscope to measure the exact duration. Look at Examples 7-6 through 7-8.
Example 7-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 7-7
Write an 8051 C program to toggle the bits of PI ports continuously with a 250 ms
The program below is tested for the DS89C420 with XTAL = 11.0592 MHz.

Example 7-8

Next post:

Previous post: