# How to extend a microcontroller GPIO to ~300 inputs?

I need to find out the address of buttons pushed. Say I need about 300 Input port required dedicated for individual buttons. Then I would need 300 I/O pins to read the address of a pushed button which is not feasible for Microcontroller without using any sort of Integrated Circuit.

My question is is there any IC that would dedicate an individual address for push button so whenever I push button it would send/give me an address like 0xA ? Or is there work around?

• serial keyboard scanner Jan 19 '20 at 1:40
• For 300 buttons, you would only need 35 I/O in a matrix format (20x15). You may be able to get away with less using other techniques like Charlieplexing. Jan 19 '20 at 2:05
• @Enslaved Also, consider carefully techniques using diodes to allow multiple button press detections without confusion, when scanning.
– jonk
Jan 19 '20 at 2:19
• Does this answer your question? A good circuit for a large number of push button inputs? Jan 19 '20 at 12:37
• Where are the 300 buttons? On a PCB close to the microcontroller, or distributed all over a building with lots of wires? Jan 19 '20 at 18:09

If 256 buttons will be enough, you can use two MCP23017 (16 port I2C GPIO): the first one as 16 outputs, the second one as 16 inputs, of course with 16x16 matrix of buttons. If not enough, you can use three of them, or "borrow" additional three lines form MCU (so, it will make 16x19 = 304 buttons possible).

As @jonk mentioned, if you want to detect multiple buttons pressed at the same time, you need to add diodes (1N4148, 1N914) to each button, like below:

If you don't need to handle multiple pressed buttons, you need to protect only the output lines by diodes, like below:

MCP23017 is pretty cheap and works very well.

• Just to add to this, you wouldn't normally use discrete 1N4148s. In the same way as you can get resistor network packages, you can also get packages with multiple diodes. Jan 19 '20 at 10:23
• @Graham, it depends to mechanical idea of buttons mouting. It is up to OP. Jan 19 '20 at 13:44

I would also choose multiplexing or Charlieplexing for this role.

If you insist on using dedicated I/O lines for every single button, a handful of shift registers could also do the job, e.g. SN74HC166/SN74HC165. You could also combine the two, use 595s to shift out a pattern and 166s to input the button states. It's easy to use these chips with a microcontroller's SPI interface, and they're very cheap if you buy more of them at the same time.

• Charlieplexing is used for LEDs but I'm not sure it is applicable to reading switches. Do you have any references for that? Why do recommend the 166/165 and then say "use 595s"? Remember that your talking to a beginner. Jan 19 '20 at 17:47

Yep. The very simplest solution is called a shift register. You can use them for both input and output -- though generally each chip is dedicated to one or the other. Well, that is to say, they're either "serial to parallel" or "parallel to serial".

Say you have an 8-bit parallel-to-serial shift register, it'll have 8 parallel input lines, and when you read the serial line, it'll give you the value of each of its 8 parallel input pins in sequence. Or for output, the other way around (writing 8 bits to one line sets the output on all 8 parallel output pins). Usually you can chain them together, so that reading/writing beyond those 8 bits shifts in the values from the next register you've connected.

But if you have a LOT of inputs, like building in a keyboard, then it makes sense to do the multiplexing arrangement others have mentioned. That way with N GPIOs you can read N2 inputs. In addition to the advice here, you should find plenty of tutorials online since DIY keyboards are a thing.

Still, since shift registers are so cheap (I've seen them at 50 for \$1), sometimes it's just all a matter of managing complexity in whatever way makes the most sense for you at the time.