Digital I/O Ports

Last modified by Microchip on 2023/11/09 09:00

The general purpose I/O pins can be considered the simplest of peripherals. They allow the PIC® MCU to monitor and control other devices. Depending on which peripheral features are on a specific device, some pins are multiplexed with alternate functions to add flexibility and functionality. In general, when a peripheral is functioning, that pin may not be used as a general purpose I/O pin.

The following is a diagram of a typical I/O port where we can see the clear distinction between ports and latches. This block diagram does not take into account peripheral functions that may be multiplexed onto the I/O pin, we will discuss those later.

Basic Diagram of Digital I/O Port Without Analog or Other Peripheral Functions Muxed In​​​​​

I/O Port Control Registers

All I/O ports have four registers directly associated with the operation of the port, where x is a letter that denotes the particular I/O port:

  • TRISx: PORTx Data Direction Control register
  • PORTx: I/O Port register
  • LATx: PORTx Data Latch register
  • ODCx: PORTx Open-Drain Control register

Each I/O pin on the device has an associated bit in the TRIS, PORT, LAT, and ODC registers.

TRISx Registers

The TRISx register control bits determine whether each pin associated with the I/O port is an input or an output. If the TRIS bit for an I/O pin is a 1, then the pin is an input. If it is a 0, then the pin is configured as an output. It is important to remember that all port pins will be defined as inputs after a reset. By defaulting to inputs, the pins will not conflict with any logic outputs or other voltage sources connected to them.

PORTx Registers

Data on an I/O pin is accessed through a PORTx register. A read of the PORTx register reads the value of the I/O pin, while a write to the PORTx register writes the value to the port data latch.

Many instructions on the 16-bit MCUs are read-modify-write operations; therefore, a write to a port implies that the port pins are read, the value is modified, and then written back to the port data latch. You should be careful when using these instructions on the PORTx registers. If an I/O pin configured as an input is changed to an output later, an unexpected value may be output on the I/O pin. This effect occurs because the read-modify-write instruction reads the instantaneous value on the input pin and loads that value into the port data latch. Similarly, if an I/O pin is configured as an output, unintended I/O behavior may occur based on the device speed and I/O capacitive loading.

LATx Registers

The LATx register associated with an I/O pin eliminates the problems that can occur with read-modify-write instructions. A read of the LATx register returns the values that are held in the port output latches instead of the values on the I/O pins. A read-modify-write operation on the LATx register associated with an I/O port avoids the possibility of writing the input pin values into the port latches. A write to the LATx register has the same effect as a write to the PORTx register.

The differences between the PORTx and LATx registers are summarized in the following table:

 PORTxLATx
ReadReads data value on the I/O pinReads data value held in the port latch
WriteWrites data value to the port latchWrites data value to the port latch

ODC Registers

Each I/O pin can be individually configured for either normal digital output or open-drain output. The open-drain feature allows a load to be connected to a voltage higher/lower than VDD on any desired digital-only pins by using external pull-up resistors. This is controlled by the PORTx Open-Drain Control register, ODCx, associated with each I/O pin. If the ODC bit for an I/O pin is 1, then the pin acts as an open-drain output. If the ODC bit for an I/O pin is 0, then the pin is configured for a normal digital output (ODC bit is valid only for output pins). After a reset, the status of all the bits of the ODCx register is set to 0. It is important to note that the ODCx register setting takes effect in all the I/O modes, allowing the output to behave as an open-drain even if a peripheral is controlling the pin.

The open-drain I/O feature is not supported on pins that have analog functionality multiplexed on the pin.

Back to top

Analog and Digital Port Pins

Pins can be configured as digital inputs or outputs, and analog inputs or outputs. The ANSELx register controls the operation of the analog port pins. The port pins that are to function as analog inputs must have their corresponding ANSEL and TRIS bits set. To use port pins for I/O functionality with digital modules, such as Timers, UARTs, and so on, the corresponding ANSELx bit must be cleared. The ANSELx register has a default value of 0xFFFF. Therefore, all pins that share analog functions are analog (not digital) by default.

Back to top

Peripheral Multiplexing

Many pins support one or more peripheral modules. An I/O port that shares a pin with another peripheral is always subservient to the peripheral. The peripheral’s output buffer data and control signals are provided to a pair of multiplexers. The multiplexers select whether the peripheral or the associated port has ownership of the output data and control signals of the I/O pin. When configured to operate with a peripheral, a pin may not be used for general input or output. However, in most cases, a pin must still be configured for input or output, although some peripherals override the TRIS configuration.

When a peripheral is enabled, the associated pin output drivers are typically module controlled, while a few can be configured by the user. The I/O pin may be read through the input data path but the output driver for the I/O port bit is generally disabled. The image below shows how ports are shared with other peripherals and the associated I/O pin to which they are connected.

Generic I/O Port Pin Diagram Showing Muxing of Other Functions Onto Pin​​​​

For some PIC24 devices, particularly those with a small number of I/O pins, multiple peripheral functions may be multiplexed on each I/O pin. The priority of the peripheral function depends on the order of the pin description in the pin diagram of the specific product datasheet. For example, in the image above, we see that the I/O pin shown is named PERA/PERB/PIO. This means that if Peripheral A and Peripheral B are enabled at the same time, Peripheral A will take control of the I/O pins.

Back to top

Peripheral Pin Select

A major challenge in general-purpose devices is providing the largest possible set of peripheral features while minimizing the conflict of features on I/O pins. Peripheral Pin Select (PPS) allows the user to select what pins will be used by certain digital peripherals. It is intended to allow better flexibility for parts with multiple functions multiplexed onto single pins. The PPS configuration feature operates over a fixed subset of digital I/O pins. Users may independently map the input and/or output of most digital peripherals to any one of these I/O pins. PPS is performed in software and generally does not require the device to be reprogrammed. Hardware safeguards that prevent accidental or spurious changes to the peripheral mapping once it has been established are included.

The number of available pins is dependent on the particular device and its pin count. Pins that support PPS include the designation, “RPn” in their full pin designation where “RP” designates a remappable peripheral and “n” is the remappable pin number.

Peripheral Pin Select Pins Illustrated on a PC24FJ16MC101 Device​​​​

On a device’s schematic symbol, remappable input pins are designated as RPIn and remappable output pins are designated as RPn.

The peripherals managed by PPS are all digital-only peripherals. These include general serial communications (UART and SPI), general-purpose timer clock inputs, timer-related peripherals (input capture and output compare), and interrupt-on-change inputs. Some digital-only peripheral modules are never included because the peripheral’s function requires special I/O circuitry on a specific port and cannot be easily connected to multiple pins. These modules include I2C and the motor control PWM. A similar requirement excludes all modules with analog inputs, such as an A/D Converter.

The main difference between remappable and non-remappable peripherals is that, unlike non-remappable peripherals, remappable peripherals are not associated with a default I/O pin. Remappable peripherals must always be assigned to a specific I/O pin before they can be used. Non-remappable peripherals are always available on a default pin, assuming that the peripheral is active and not conflicting with another peripheral.

Back to top

Controlling Peripheral Pin Select

PPS features are controlled through two sets of SFRs, one to map peripheral inputs and another one to map outputs. Because they are separately controlled, a particular peripheral’s input and output (if the peripheral has both) can be placed on any selectable function pin without constraint. The association of a peripheral to a peripheral-selectable pin is handled in two different ways, depending on whether an input or output is being mapped.

Input Mapping

The inputs of the PPS options are mapped on the basis of the peripheral; that is, the control register associated with a peripheral dictates the pin it will be mapped to. The RPINRx registers are used to configure peripheral input mapping. Each register contains sets of 5-bit fields with each set associated with one of the remappable peripherals. Programming a given peripheral’s bit field with an appropriate 5-bit value maps the RPn pin with the corresponding value to that peripheral. For any given device, the valid range of values for any bit field corresponds to the maximum number of peripheral pin selections supported by the device.

The following is a diagram of input mapping. Note that there is a mux for each peripheral input function (e.g., U1 receive, U1 CTS, U2RX, each IC module…). Each mux allows the user to select any single RP pin as the peripheral's input.

Input Pins Mapped to Peripheral Via PPS Mux​​​​

Example

Here is the code for setting the USART RX input to RP8:

//C Example – Map U1RX to RP8

RPINR18bits.U1RXR = 8;

Output Mapping

In contrast to inputs, the outputs of the PPS options are mapped on the basis of the pin. In this case, a control register associated with a particular pin dictates the peripheral output to be mapped. The RPORx registers are used to control output mapping. Like the RPINRx registers, each register contains sets of 5-bit fields, each set associated with one RPn pin. The value of the bit field corresponds to one of the peripherals and that peripheral’s output is mapped to the pin. A null output is associated with the output register reset value of 0. This is done to ensure that remappable outputs remain disconnected from all output pins by default.

The following is a diagram of output mapping. Note that there is a mux for each RP pin. Each mux allows the user to select any single remappable peripheral output function as the pin's output. This ensures that you can't have two outputs driving the same pin.

Image Showing Peripheral Outputs Mapped to I/O Pin Via PPS Mux​​​​

Example

Here is the code for mapping the UART TX to pin RP1.

//C Example – Map U1TX to RP1

RPOR0bits.RP1R = 3;

Back to top

Controlling Configuration Changes

The absolute last thing we want is for our pinout to change while the device is running. Therefore, we have a few protection schemes implemented to prevent this.

First, there is an internal register integrity checking. If a bit is ever flipped by an ESD/EFT event, this will catch it and cause a device reset. It is important to note that when this occurs, it is noted as a configuration mismatch reset in the RCON register.

There is also internal protection that prevents unintended software changes to the RP registers. This is done with an IOLOCK bit in the OSCCON register. If this bit is set, the RP registers cannot be changed in software.

The IOLOCK bit itself is protected through two methods. First, it can only be changed by using an unlock sequence on the OSCCON register. This is similar to the unlock sequence performed for clock switches or NVM writes. Second, a configuration bit is provided that allows you to select if IOLOCK can be cleared. By default, the device resets with IOLOCK=0, so you can initially configure the I/O. You can set the configuration in such a way that once you set IOLOCK=1, it can never be cleared, allowing an ensured static IO mapping. Note that if you want to dynamically remap pins, you will need to turn off this setting.

Back to top

Pin Function Priority

1Analog FunctionsANx, Vref+/-
2PPS OutputsUART TX, SDO, OC
3PPS InputsUART RX, SDI, IC
4Fixed Digital Peripheral OutputsI2C, PMP
5Fixed Digital Peripheral InputsI2C, PMP

Back to top