Using an external latch IC gives you a good trade-off between pin usage and speed. It does this by still using a parallel set of I/O pins, but doubling them up for both the row and columns. So first you set your microcontroller pins to output and set the active row through the latch, and then you set them to input and read back the columns. It’s important that the latch have HI-Z outputs, or else the rows will fight with the columns during the setting phase. A schematic of this setup is shown below. Note that we are reversing the usual usage of rows and columns for this example, as the schematic reads better this way.
Figure 1 – Example latch mux schematic.
The latch here is a 74HC573 or 74HC373, but any similar latch will work. The ’573 is preferred, as it is identical to the ’373, but has a much better pin-out. Basically, all the I/O flow from left to right across the chip, making layout much easier. The latch has data input pins, which are passed to the output when the latch enable pin (LE) is held high, and then frozen in their state when LE is brought low. That way you can change the input pins without effecting the output pins. It also has an output enable pin (OE) which determines whether or not the output data drivers are active. When OE is low, the data is driven at the output pins. When OE is high, the output is blank, and essentially acts like an input that doesn’t go anywhere. This is called HI-Z state, as it has a really high impedance.
The advantages of this method include using very few microcontroller pins, good read speed, and the ability to have any of the pins cause an external interrupt. The main drawback, is that the procedure has a number of steps for each read. These can be executed relatively quickly, though, and shouldn’t slow down the whole process. A read cycle is executed as follows:
0. Make sure the latch in in HI-Z by pulling OE high.
1. Set the I/O pins to output.
2. Set the I/O pin low corresponding to the row you want to read.
3. Latch the data by pulling LE high then low.
4. Set the I/O pins to input with pull-ups on.
5. Activate the rows by pulling OE low
6. Read back the columns on the I/O pins
It might be possible to automate this task, depending upon your microcontroller and your PCB layout. Some of the Atmega microcontrollers have an XMEM interface, which is meant to allow for easy data reading and writing to external SRAM. As it turns out, SRAM is essentially a matrix of data bits just like our rows and columns of buttons. The only difference, is that inside the SRAM, they take up a lot less space than all of our PCB traces and switch contacts. What this means for us, is that we can not scan our switches as fast as we can SRAM, as it takes a bit of time to change the voltage on all those long traces.
But, with the XMEM interface, you can set the hold time before reading. So if your layout is compact enough, it might be possible to just read in from your switches as if you were reading data from internal memory. How’s that for easy?