Open-drain Outputs on the PIC

Open-drain outputs are outputs which at any given time are either actively sinking current (i.e., low voltage, typically considered logic 0) or are high impedance, but which never source current (high voltage, logic 1). Open-drain refers to the drain terminal of a MOS FET transistor. The equivalent concept on a bipolar device is called open-collector.

Most microcontrollers don't have dedicated open-drain outputs. On some PICs the PA4 pin (also known as RTCC) may be used as an open-drain output. Most of the other port pins are bidirectional, and have separate output data registers and direction registers.

On the PIC, the direction registers are called TRIS registers, an abbreviation for Tri-state, which is actually a trademark of National Semiconductor. The TRIS register bits should be set to logic 0 for lines that should be active outputs, and logic 1 for lines that should be high-impedance inputs. Note that this is the reverse of the conventions used by almost all other microcontrollers and peripheral devices.

In order to obtain the effect of open-drain output, it is necessary to use the TRIS register bit to control the output rather than the more usual use of the data output register. This is most easily accomplished by leaving the appropriate bit of the data output register set to 0, and setting the corresponding TRIS bit to 0 when the output should sink current, and 1 when the output should be in the open-drain (high-impedance) state.

On the low-end PIC parts (16C5x family) there is no way to access the TRIS register other than writing the whole register with the TRIS instruction. That is OK if you only have one output for which the TRIS bit ever needs to change, but if more than one TRIS bit is dynamic you will have to either keep a shadow copy of the TRIS register in RAM, or recompute the correct values to be used for all the bits.

On the mid-range PIC parts (all other 16C parts), the TRIS register can be read, but it is in the second register bank. This would typically require setting the RP0 bit in the status register to switch banks, changing the TRIS bit, and clearing the RP0 bit again. However, if you are going to be changing TRIS bits for a particular port frequently, and you don't otherwise need to use indirect addressing, you can put the address of the TRIS register into FSR and access the TRIS register indirectly through IND.


Ordinarilly when using an port pin as an open-drain output by this method, you can simply write a 0 to the port output data register once, and never need to change it. However, if you use any RMW (Read-Modify-Write) instructions on the port, the values of some bits may change unexpectedly. RMW instructions include the BSF and BCF bit instructions, INCF, INCFSZ, DECF, DECFSZ, COMF, RRF, RLF, and SWAPF. This problem can occur because the read portion of the instruction uses the input buffer to get a logic level based on the voltage at the pin, without regard to the data in the port output data register, and without regard to the TRIS register. If you are using a pin to sink a lot of current, the value read from the port may be a 1 even though the pin is configured to output a 0.

As a consequence of this, if you use a BSF or BCF instruction to set or clear bits other than your open-drain output, it may change the output register bit for the open drain output pin. The safest course of action is to avoid using RMW instructions on ports entirely, by doing the RMW on a file register then copying the file register to the port.

This problem is described in the Microchip data sheets.


When using open-drain outputs it is important to make sure that you have pullup resistors so that the voltage on the pin doesn't float between the valid logic 0 and logic 1 levels. If it floats the input buffer in the PIC will consume far more current than normal, and the noise immunity of other ports and of PIC internal signals may suffer, causing serious reliability problems.
Back to my PIC Projects page
Back to my home page

Last updated September 9, 1995

Copyright 1995 Eric Smith

eric@brouhaha.com