# Multiplexing vs shift registers (input)

I'm going to use a microcontroller to read 80 digital inputs (push button switches). I'm wondering (just to understand, I don't have any critical time constraint) if it would take less time using multiplexing over a 9*9 matrix (but using one shift register on the rows to reduce used pins on the uC, and columns directly connected to the uC) or using 10x chained shift registers (74HC165). I'm having hard time calculting that, so I'm asking for some clarification. Also, how does that change if I use SPI. Other assumptions: - uC: arduino uno - I'd like to consider also the time needed in software to provide the data in a "clean" format. Thanks

• Do you realy have an application where this speed difference would matter? – Wouter van Ooijen Sep 20 '18 at 19:05
• A lot depends on your requirements. Is this an array of buttons which have on and off states or are they simply push on buttons? Do you need N-key rollover (will multiple buttons be down at the same time)? Do you have to de-bounce the buttons? TI have an I2C chip that will do 80 inputs in a matrix with no diodes required, the TCA8418. The down side is you need to track key up/down events rather than just blind scanning. This would certainly simplify your hardware task (fewer chips) albeit with a somewhat more complex scanning routine. – Jack Creasey Sep 20 '18 at 23:54
• @JackCreasey That's one cool chip. The software will be actually simpler, since it delivers scan codes right away, something that other methods will end up anyway, only after lots of loops, conversions and maybe one or two ISRs. Why don't you make an answer of that? – Maple Sep 21 '18 at 5:53

Here's one way: Daisy chain the 10 shift-in registers with pullup resistors on their inputs, buttons to connect pins to Gnd when pressed. Scan periodically (Arduino C++ style code):

total = 0;
digitalWrite (latchInPin, LOW):
digitalWrite (latchInPin, HIGH); // capture the input states
for (x=0, x<10; x=x+1){
inputArray[x] = SPI.transfer(0);  // this loop can be fast, maybe 25 uS with 8 MHz SPI clock
total = total + inputArray[x];
}
if (total == 0x08F7){
// no zeros found, go to next scan period
}
else {
// one or more zeros was found, process it from the array
}


Could also DIODE AND all the inputs together, only do the latch and then scan when a LOW from the diodes was detected on an interrupt line.

• What is "diode and"? – Maple Sep 20 '18 at 20:34
• Diode anode is connected to each input. Diode anodes are connected in common to the interrupt pin with a pullup resistor. When any anode goes low, the common cathode goes low, creating a low interrupt. – CrossRoads Sep 21 '18 at 1:34
• In other words, "OR" – Maple Sep 21 '18 at 5:42
• I think that a LOW output with any LOW input is AND. A HIGH output from any HIGH input would be OR. – CrossRoads Sep 21 '18 at 11:34
• Diode AND gate has pull-up and common anodes. Diode OR gate has pull-down and common cathodes. What you described above has "anode connected to each input" and "anodes are connected in common" and "common cathode". I have no idea what is that supposed to be – Maple Sep 21 '18 at 16:31

There are so many possibilities I don't even know where to begin.

It all depends on two things: button wiring and availability of the MCU pins. You mentioned "push button switches" first, then "9*9 matrix". If you have matrix keyboard with built-in diodes it is one thing, if you have discrete push buttons that you planning on assembling into matrix it is completely different.

Keep in mind that physical button arrangement has nothing to do with electrical wiring. For example, a single 16 bit 74LS674 shift register needs only 5 additional wires to read all 80 buttons. The buttons can be placed 9x9, 4x20 etc.

Anyway, here are just some options out of many.

• For matrix with diodes you can actually use both, multiplexor for columns and shift register on rows. This will reduce required number of pins even more.

• You can also use BCD to decimal decoder like HCF4028B instead of multiplexor.

• You can use two I2C or SPI mux-demux chips. This will reduce the number of required IO pins down to only 2, but will increase polling time a lot.

• You can use a single ADG725 chip. It has two 16 bit muxes, so you can use one for columns and the other one for rows. This option has extremely easy wiring.

• If you do not wire your buttons into matrix, you can use a chain of 9 shift registers as in your question. Or you can use 3 ADG731 chips, each is 32 bit mux.

Now, regarding processing time. The shift registers require clocking for reading data. In this regard they are slower than muxes or decoders with binary address input. However the later require you to switch between all addresses to get one reading, so in the end they are slightly slower. The chips with I2C or SPI control will be slower still.

However the differences between the chips do not define the processing time, because they are negligible when compared with the timings of human interaction. The defining factor is system latency and the shortest button pressed time you want to detect. In all the schematics above (and in your question) you need very frequent polling by MCU. It is not the best use of MCU time, really.

You did not specify in the question whether your MCU is supposed to do something between presses, or it should only react when button pressed. In the former case MCU can constantly poll the matrix. It has nothing else to do anyway. In the latter you need something better.

So, here is one trick you can use to minimize the reaction time without polling constantly:

• Use output shift register like 74HC595 on the columns. This would allow you to power up several columns simultaneously, something that muxes or decoders cannot do.
• Use input shift register like 74HC165 on the rows.
• Also connect all rows via diodes into single line wired to separate GPIO.
• Introduce "waiting mode" in you code. In this mode all output lines are high, so pressing any button will result in signal on one of the rows. And consequently, this will produce a signal on that additional line combining the rows.
• Program that pin for interrupt. This would free entire MCU time for your other needs. When interrupt triggers, it will assert boolean flag telling your main loop that button should be processed. Then you main loop can pause what it was doing, perform some debouncing and use shift registers to figure out which button is pressed. When button released debounce again and de-assert the flag to return to waiting mode.

Note, that the above trick can be used with non-matrixed keyboard as well. Only instead of combining rows you will be combining all the buttons into one interrupt line.

In short - there are almost too many options available to you. Figure out the required latency of the system and how many pins you can spare, this will narrow it down.

Here's what I was describing in my comment above.

Corrected for the diode orientation, I had them flipped end for end.

• OK, now you have pull-ups on both inputs and outputs... and refuse to listen too. There is a reason AND diode gates use common anode. Grounding of the anode in your circuit will not pull down cathode pin. That's not how diodes work. – Maple Sep 21 '18 at 18:04
• You are correct. I had them the other way around in my mind, but that's not what was coming out! Thanks for catching that. I actually used this in an RF remote control I made, with the diodes on a keypad to interrupt up the uC and signal it to wake up and run the keypad.h library to scan the keypad and find the button that was pressed, transmit it to a receiver, then go back to sleep. – CrossRoads Sep 21 '18 at 18:12