Perhaps the easiest of the external IC solutions, a shift register brigade can handle an almost infinite number of inputs and pipe them down into 3 pins on your microcontroller. The only real catch, is that its a bit of a pain unless you use the SPI interface on your microcontroller to communicate with the external shift registers. For one or two registers, this isn’t a problem, as you can bit-bang the 8 or 16 bits in a relatively short period of time. But, with larger brigades, a dedicated peripheral makes it much easier. An example of a shift register brigade connected to a SPI peripheral is show below. Note that you will need a buffer chip of some sort if you want to share the SPI MISO line with another device.
Figure 1 – Example shift register brigade schematic.
The 74HC165 is a parallel-in, serial-out shift register. There are other chips with similar functionality, but this one is the most common. It has a parallel load pin (PL), which stores the data present at the input pins when it goes high. the data is then clocked out with every low to high transition on the clock pin (CP). A series of these chips can be placed into a long line, and they can pass data down the line until it all reaches the microcontroller.
One advantage to this setup is that all of the buttons are sampled at once, synchronizing your data. And although it can take a long time to clock in the data, if you use the SPI interface, this can be automated to happen during an interrupt. In this case, it requires minimal overhead, and delivers the data in nice 8 bit chunks. This makes for a very simple programming interface.
The disadvantage is that it requires a fair number of ICs, and each one requires 8 pull-up resistors, as they are not built in like they are in the microcontroller. It can also tie up your SPI lines, and it does not allow for button presses to trigger external interrupts.