Pull high in software

I was porting Arduino library ps/2 mouse to pic and I wondered why pull high works when declaring the pin as an input and then making it high and that worked for pic and Arduino alike, but when I declare the pin as an output then write high, I didn't get the acknowledgment right.

Why does pull high require being an input?and why software writing to an input work?

An input that is "pulled high" as you refer to it, or also commonly "pulled up" refers to a signal that is connected to a positive rail via a medium value resistor (generally a few 10s of kΩ). As such, its voltage level is defined by the positive rail, provided that no significant current flows through the pull up resistor. Inside the PIC or AVR, it looks something like this:

simulate this circuit – Schematic created using CircuitLab

If we draw significant current out of that I/O pin, for example by connecting it to ground via a low impedance, be that a wire, a switch or an open collector transistor, the voltage at the I/O pin will drop. This sounds like a bad thing, but it can be really useful. It allows us to define the default voltage at the I/O pin, and then let external circuits modify it. Even better, because we don't require those circuits to define the high-state voltage themselves, you could have lots of switches (or open collector resistors) in parallel - and if any one of them switches on, that would pull the I/O pin voltage low. The I2C protocol makes use of this to allow the slave device to acknowledge data transfer by pulling the pulled-up SDA (data) pin low.

I don't have any practical knowledge of PS/2, but I am guessing that the same sort of thing is going on here. If you drive the pin high as an output, instead of being via a medium value resistor you are driving it hard via a transistor - and that's a much lower resistance path. You would need to pull a lot more current out of the pin to drive it low, and so the acknowledge won't work. You can think of this as a pulled up pin being a weakly defined voltage state - other circuits can change the voltage at the pin relatively easily. An output driven pin is a much more strongly defined state - and deliberately so, as you don't want it to be susceptible to influence by other circuits.

As for why writing a high value to an input pin works - this is a quirk of the way that the registers inside the AVR and PIC are laid out. If the DDxn bit for a particular pin is set to be an input, the AVR interprets the PORTxn value bit as whether to connect a pull up or not. If the DDxn bit is set to be an output, the PORTxn value bit determines the drive level (high or low). For an explanation of this, see p.76 of the Atmega328 datasheet. Other architectures react differently (some, for example, allow for the connection of a pull-up OR pull-down resistor, via different register settings). As Arduino has grown to include a wider range of architectures, the use of

pinMode(pin, INPUT);
digitalWrite(pin, HIGH);


to enable a pulled-up input has been superseded by

pinMode(pin, INPUT_PULLUP);


in order to be easier to understand and more generally adaptable to more modern architectures.

• Saves me writing an answer. I wanted / You could include a reference to e.g. atmel.com/images/doc2503.pdf Page 50. Apr 28, 2016 at 15:22
• Thanks @Scheintod - added the link as suggested (although to the Atmega328 datasheet) Apr 28, 2016 at 15:39