Problem reading from MCP23016


New Member
Hi all,
I'm trying to read from the ports of an MCP23016. GP0 port inputs are all configured as inputs. GP1 has been configured as 7 input pins (GP1.0 - GP1.6) and one output pin (GP1.7).
I'm trying to read four or more inputs on GP1 to supplement the eight GP0 inputs to give me 12 inputs, with the eight GP0 inputs read to one PIC byte variable and four of the GP1 inputs (GP1.0 - GP1.3) to another byte; then read the two bytes as one word.

#picaxe 14m2
setfreq m4

pause 500          'allow time for LCD and driver to initialise
w4 = 0            'set retard value for watering timing

hi2csetup i2cmaster, 70, i2cfast, i2cbyte    'set i2c address to I/O expander 1
hi2cout 6, (%11111111)        'set IODIR0 to be all inputs
hi2cout 7, (%01111111)        'set IODIR1 to be all inputs except 1.7

hi2cin 0, (b2)                        'read GP0 port inputs
hi2cin 1, (b3)                        'read GP1 port inputs
serout B.5, N2400_4, (254,192, "       ", #w3, "       ")   'display on LCD
goto Tst                'loop
Unfortunately I get a garbled result with all kinds of unexpected numbers being displayed when I make any of the GP1 inputs high. There are pull-down resistors on all input pins including unused ones, and only one input at a time is ever high - I'm reading a 12-position rotary switch.
I've read the MCP23016 datasheet as insightfully as I can and I can't, for instance, see a way to mask the 1.7 input from that port, if indeed that is the cause of my problem.
I'm hoping someone can point me towards a solution!?!



Senior Member

I don't know the MCP23016 specifically, but your code appears to be reading b2 and b3 (which together form w1) but then sending #w3 to the display? Also try i2cslow, just in case.

With issues like this it's normally best to send the exact received data bytes directly to the serial terminal for testing, e.g. SERTXD ("b2,b3= ",#b2," ",#b3,cr,lf). If necessary, put a #terminal 4800 at the top of the program.

Cheers, Alan.


I cannot see where you set up the register format for ports A and B as blocks or sequential.
I did quite a bit some years ago with the MCP23017.
Have a look at some of my code here (post 6 in particular):

And see if that helps for information/ guidance (sorry but late here 1am to delve further).


New Member
oops, the w3 was a typo from where I was experimenting with outputting just the b2 and b3... it should of course be w1! BTW the b2 data, from GP0 which are all configured as inputs, worked perfectly. But the outputting the b3 data, from the GP1 port (mix of inputs and one output) was definitely messed up.


New Member
Have tried i2cslow but there is no change.

I'm not familiar (newbie to i/o expanders!) with how to set the register format for ports A and B as blocks or sequential and how this works or even the reason for doing it... I can see it referenced in westaust55's control map but can't find the note 1 mentioned there.

Basically I can't imagine they designed this device without the ability to accurately access the state of the inputs of a port when one (or more) of the inputs has been configured as an output... just can't find out - and can't figure out - how it is done.

An awful plan B would be to use another i/o expander specifically for the outputs (I'm actually running five expanders to read five 12-posn rotary switches and trying to use an unused pin on each expander as an output to switch on/off solenoids via mosfet etc.) which seems a waste and would make my pcb a bit bigger than I have room for; or throw a slave pic onto the i2c line and use five of its outputs to drive the solenoids but that's just as awful and also takes up more room than I have available and seems just sooooo clunky and wrong!!!



First set the IOCON (reg $0A) to zero (0)

next to set the ports they are then registerS $00 and $01
(Otherwise they are $00 and $10)

you are trying to set registers 6 and 7 to set up the direction of the 16 IO pins.

Next to read the inputs you need to read (hi2cin) from the GPIOA ($12) and GPIOB ($13) registers.
Not registers 1 and 2.

hope that helps (and hope my typing on an iPhone does not introduce too many spelling errors etc)


New Member
Well now... in frustration and bearing in mind what you guys have suggested and what I have learned since started building the code for this project I have re-started from scratch and put together a simple bit of code to set the i/o directions and read the inputs and flash an LED on that one output 1.7 when an input is made high... and it works!!!
I'm now settling down to re-build the whole programme bit by bit whilst keeping an eye on whether the i/o is doing what I expect it will... fresh start and fresh eyes and more knowledge and cleaner code might do the trick. Still not sure exactly what the problem has been but fingers are crossed for success this time around! Tks once again for your nudge in the right direction when I come unstuck or go cross-eyed!



Still not sure exactly what the problem has been . . .
Notwithstanding the W3 variable matter, the key problem was that you were not using the correct MCP23017 registers for set-up and reading the inputs.

Nevertheless, great to read that you are now making progress 👍


New Member
Sorry to take so long to get back on this after you guys responded to my query so promptly... after trying every other possibility I did a thorough check of the PCB and discovered two slightly dodgy solder joints!!! I'm still so lacking in confidence about Picaxe stuff that I automatically assume problems are caused by my lack of knowledge or in-depth experience in programming, interfacing, etc. I could kick myself!