PJRC.COM Offline Archive, February 07, 2004 Visit this page on the live site |
| ||
Shopping Cart Checkout Shipping Cost Download Website |
Home | MP3 Player | 8051 Tools | All Projects | PJRC Store | Site Map |
You are here: 8051 Tools Development Board Example Code 82C55 I/O | Search PJRC |
|
Figure 1: Two 82C55 Chips Provide 40 I/O Lines and 8 LEDs |
The chips shown in figure 1 are NEC UPD71055L. Despite the strange part number, these are NEC's version of the 82C55 chip. They are labeled D71055L on the top of each chip.
Assembly Language (AS31) | C Language (SDCC) |
---|---|
.equ port_a, 0xF800 .equ port_b, 0xF801 .equ port_c, 0xF802 .equ port_abc_pgm, 0xF803 .equ port_d, 0xF900 .equ port_e, 0xF901 .equ port_f, 0xF902 .equ port_def_pgm, 0xF903 |
volatile xdata at 0xF800 unsigned char p82c55_port_a; volatile xdata at 0xF801 unsigned char p82c55_port_b; volatile xdata at 0xF802 unsigned char p82c55_port_c; volatile xdata at 0xF803 unsigned char p82c55_abc_config; volatile xdata at 0xF900 unsigned char p82c55_port_d; volatile xdata at 0xF901 unsigned char p82c55_port_e; volatile xdata at 0xF902 unsigned char p82c55_port_f; volatile xdata at 0xF903 unsigned char p82c55_def_config; |
Since the 82C55 chips are connected to the exteral memory bus, they must be accessed using the MOVX instruction. The MOVX instruction always uses DPTR to specify the memory location, and data is always transfered to/from the accumulator. Here is an example of how the 82C55 registers are accessed using assembly language:
do_some_io: mov dptr, #port_a mov a, #0xA2 movx @dptr, a ;Write 0xA2 to Port A mov dptr, #port_b movx a, @dptr ;Read Port B into the accumulator ret |
When programming in C, the compiler takes care of handling the registers, so all you need to do is read the 82C55 registers as if they were ordinary global variables. Here is a simple example, equivilant to the assembly code above (the compile may generate slightly different assembly code):
unsigned char do_some_io(void) { p82c55_port_a = 0xA2; /* Write 0xA2 to Port A */ return(p82c55_port_b); /* Read Port B and return it */ } |
Using SDCC, the variable declaration gives the compiler all the information it needed to "know" how to access the 82C55 chip. The "volatile" keyword tells the compiler's optimizer to always access the chip as shown. The "xdata" keyword tells the compiler that the access is the external data bus. The special syntax "at 0xF800" tells the compiler that the variable is located in memory at 0xF800 (by default, the linker would choose a location). And, of course, the variable is an unsigned char, so it will be accessed as a single byte. The 8 definitions above will simply work with the 82C55 chips, but understanding the definitions is necessary if you need to create them for additional custom hardware.
Configuration Byte | Port A | Port B | Port C | Port C | |
---|---|---|---|---|---|
Decimal | Hex | Bits 7:0 | Bits 7:0 | Bits 7:4 | Bits 3:0 |
128 | 0x80 | Output | Output | Output | Output |
129 | 0x81 | Output | Output | Output | Input |
136 | 0x88 | Output | Output | Input | Output |
137 | 0x89 | Output | Output | Input | Input |
130 | 0x82 | Output | Input | Output | Output |
131 | 0x83 | Output | Input | Output | Input |
138 | 0x8A | Output | Input | Input | Output |
139 | 0x8B | Output | Input | Input | Input |
144 | 0x90 | Input | Output | Output | Output |
145 | 0x91 | Input | Output | Output | Input |
152 | 0x98 | Input | Output | Input | Output |
153 | 0x99 | Input | Output | Input | Input |
146 | 0x92 | Input | Input | Output | Output |
147 | 0x93 | Input | Input | Output | Input |
154 | 0x9A | Input | Input | Input | Output |
155 | 0x9B | Input | Input | Input | Input |
Each chip requires its own configuration byte, so the process for configuring ports D, E (leds) and F is the same.
When the system is reset, the 82C55 chips default to all inputs (configuration byte 0x9B). When configuring the 82C55 chips immediately following a system reset, a delay should be added. The reset signal is generated by a resistor and capacitor, and as the voltage falls, the 8051 will often begin executing code before the 82C55 reset pin detects the voltage change (it tends to "see" the high to low transition at a lower voltage). So a simple software delay before configuring the 82C55 chip should be used to allow time for the 82C55 to begin operating. The 82C55 will ignore the write to its configuration register if it is still in reset mode.
Once you have written the configuration byte, the three ports may be accessed simply by reading or writing their registers. Port C (or port E on the second 82C55 chip) may be configured where half of the pins are input and the other half output. In that case, 82C55 chip ignores the unneeded 4 bytes when you write to port C, and when you read port C, the undefined 4 bits should be ignored.
You may change the 82C55 configuration at any time by writing a new configuration byte. Doing this effectively resets the 82C55 chip. All pins defined as outputs by the new configuration byte are cleared to zero. This should be considered when designing hardware that interfaces to 82C55 pins in an applicaton where the configuration will be changed, rather than simply programmed once at startup. The output pins default to low immediately after the configuration byte is written to the 82C55.
TODO: explain the complex modes
TODO: single bit writes to port C
TODO: example code (any suggestions ??)