I/O Ports

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.


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:
Read reads data value on the I/O pin reads data value held in the port latch
Write writes data value to the port latch writes 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.

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.

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.


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 data sheet. 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.

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 Peripheral Pin Select 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. Peripheral Pin Select is performed in software and generally does not require the device to be reprogrammed. Hardware safeguards are included that prevent accidental or spurious changes to the peripheral mapping once it has been established.

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


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 the Peripheral Pin Select 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 in the Peripheral Pin Select feature 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 remappable peripherals are not associated with a default I/O pin like non-remappable peripherals are. Remappable peripherals must always be assigned to a specific I/O pin before it 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.

Controlling Peripheral Pin Select

Peripheral Pin Select 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.



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, with 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.



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

//C Example – Map U1TX to RP1

RPOR0bits.RP1R = 3;

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 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 which 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.

Pin Function Priority

1 Analog Functions ANx, Vref+/-
2 PPS Outputs UART TX, SDO, OC
4 Fixed Digital Peripheral Outputs I2C, PMP
5 Fixed Digital Peripheral Inputs I2C, PMP

20th Annual
Microchip MASTERs Conference 2016
Register now - Deadline: July 29

JW Marriott Desert Ridge Resort-Phoenix, AZ

© 2016 Microchip Technology, Inc.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.