The 8051

  Parallel Input/Output
  One of the major advantages of using a microcontroller as opposed to a microprocessor is the fact that interfaces to the outside world are built into a microcontroller chip. These interfaces are most often through parallel input and output ports (serial ports are often also available; we will look at these in the next section).
  The basic 8051 microcontroller has four 8-bit ports, P0, P1, P2 and P3. By looking at the memory map we see them at addresses 80H, 90H, A0H and B0H respectively. All of the ports, except P1, have alternate functions, which can be seen from the 8051 pinout, but in this section we will treat them as I/O ports only.
  All pins on all the ports (32 pins) can be used as either inputs or outputs.
  Initialising Ports
  The initialisation of 8051 parallel ports is slightly unusual. Before we examine it, we will take a look at a more common form, that of the PIC microcontroller. The basic PIC microcontroller has one 4-bit port (PORT A) and two 8-bit ports (PORT B and PORT C). All pins for all three ports can be set as either input pins or output pins. This is achieved by loading a value into a special register known as the tri-state register.
  Tri-state Buffers
  A tri-state buffer is a single-input/single-output gate with an enable input, the schematic for which is shown below.
  There are four versions of the buffer. The inverting buffer acts like an inverter when enabled. (In the case of the active-high enable, the gate acts as an inverter when a logic 1 is applied to the enable input. In the case of the active-low enable, the gate acts as an inverter when a logic 0 is applied to the enable input.)
  The non-inverting buffer simply passes the input through to the output (unchanged) when enabled.
  In either case, when the gate is disabled then the input and output are isolated from each other.
  Using Tri-state Buffers to set Port Pins as Inputs and Outputs
  For each port pin in the PIC there is a bit in a special register known as the tri-state register. To initialise a port pin as an input, the corresponding bit in the tri-state register is set. To initialise a port pin as an output, the corresponding bit in the tri-state register is cleared.
  To understand why this is so, take a look at the diagram of a single PIC port pin below.
  The single port pin is split into two lines. One line goes to the input of a non-inverting active-high enables buffer, while the other goes to the output of a non-inverting active-low enabled buffer. The buffers' enable inputs are connected to the tri-state register bit. Therefore, by setting the tri-state register bit, the input buffer is enabled (while the output buffer is disabled, ensuring the line coming out from the CPU is isolated from the port pin) and there is a path for data from the pin through to the CPU, ie; it is now an input port pin.
  When the tri-state register bit is cleared, the input buffer is disabled (isolating the line into the CPU from the port pin) while the output buffer is enabled. This results in a path from the CPU out to the port pin, ie; the port pin is now an output pin.
  Setting all PORT C pins as outputs - load 0 into TRISC (the name given to the tri-state register for PORT C).
  Setting all PORT A pins as inputs - load FH (15 in decimal; 1111 in binary) into TRISA (remember, PORT A in the PIC is a 4-bit port).
  Setting the 2 MSBs of PORT B as inputs and the rest as outputs - load C0H (192 in decimal; 1100 0000 in binary) into TRISB.
  Initialising 8051 Port Pins
  Because of the way the 8051 port pin circuitry is designed, to use a port pin as an output requires no initialisation. You simply write to the port. For example, SETB P1.5 will send a logic 1 to P1 bit 5. MOV P0, A will send the data in the accumulator to P0.
  To initialise a port pin as an input we must first write a logic 1 to that pin. For example, to set P3 pin 2 as an input we could execute the code: SETB P3.2
  This code is exactly the same as if you were writing a logic 1 to an output pin. Therefore, simply by examining a line of code, say, MOV P2, #0FFH, there is no way of telling if this is sending all 1s to P2 because P2 is an output port, or sending all 1s to P2 to make all of P2's pins inputs. Only by examining what is connected to P2 would we be able to decipher this piece of code correctly. For example, if 8 LEDs are connected to P2, then this is an output port (you never read the value of an LED, you either turn it on or off by writing 1s and 0s to it) and the code MOV P2, #0FFH is turning on or off (depending on the way the LEDs are connected) the LEDs.
  If, on the other hand, 8 switches were connected to P2, then these pins must be used as inputs (because we read the value of a switch) and the code MOV P2, #0FFH is initialising each pin of P2 as an input.
  It is very important when initialising a port pin on the 8051 to write a comment stating this, otherwise it is difficult to know whether data is being sent out to the port pin, or the port pin is being initialised for input. Taking the above example, the code should be written something like:
MOV P2, #0FFH ; initialising P2, all pins, as inputs
  Why must a logic 1 be written to the port pin to make it an input pin?
  To understand why writing a 1 to a port pin is necessary if the pin is to be used as an input, take a look at the schematic for an 8051 port pin.
(The 8051 Microcontroller, 3rd Edition - I. Scott MacKenzie)
  When data is written to the port pin, it first appears on the latch input (D) and is then passed through to the output (Q) and through an inverter to the FET. If a logic 0 is written to the port pin, this 0 on Q is inverted to a logic 1, which turns on the FET. There is now a direct path from the port pin to ground (therefore it is at logic 0, as desired).
  However, if this pin is to be used as an input and there is a logic 0 on the latch, then the pin will always be at 0 because it is connected directly to ground through the switched on FET. No matter what voltage is applied to the port pin it will not rise above 0V.
  Therefore, to use the port pin as an input we first write a logic 1 to the latch. This logic 1 is then inverted and the FET is switched off. Now there is no connection between the port pin and ground and the voltage applied to the pin can be read through the READ pin buffer.
  Reading and Writing
  Writing to a port pin is very simple, as shown below:
SETB P3.5 ; set pin 5 of port 3
MOV P1, #4AH ; sending data 4AH to port 1 - the binary pattern on the port will be 0100 1010
MOV P2, A ; send whatever data is in the accumulator to port 2
  Reading a port pin is also very simple, once the pin has been initialised for input:
SETB P1.0 ; initialise pin 0 of port 1 as an input pin
MOV P2, #FFH ; set all pins of port 2 as inputs
MOV C, P1.0 ; move value on pin 0 of port 1 to the carry
MOV R3, P2 ; move data on port 2 into R3
Copyright (c) 2005-2006 James Rogers