Code is available here: IOSerialFun
This project, IO Serial Fun, demonstrates serial programming using IO, namely buttons and LEDs. My multiputs project demonstrated how to monitor many inputs using a 74HC595 IC. The ‘595 IC is a parallel out/serial in IC. So, using it to monitor multiple output is really just a trick feature of the chip. Several great people over at GHI commented that I could (should?) use 74HC165s, a parallel in/serial out, integrated circuit to accomplish the goal of monitoring many inputs. If you understand how ‘595s work, you’ll grasp ‘165 wiring. The ‘165 works pretty much in the reverse of the ‘595. My Marquee project is a good refresher for ‘595 programming if you need it.
Using ‘165s have a few advantages over ‘595s for monitoring inputs:
- No diodes needed making the solution cheaper and easier
- Simpler programming
Here’s the video of the project.
This project uses a single ‘165 and ‘595. The ‘165 monitors buttons presses. The FEZ Raptor serially reads the output of the ‘165 and serially writes the results to the ‘595 to display which buttons are pressed. This is much how a digital piano would work.
Both types of ICs can daisy chained. This allows a board to use only 4 pins to monitor nearly an unlimited number of inputs. Outputs only need 3 wires.
Here is the most important part of the code; the reading of the ‘165 and writing to the ‘595.
void dataReadTimer_Tick(GT.Timer timer) { output_pl.Write(false); output_pl.Write(true); output_ce.Write(false); int retval = 0; for (int i = 0; i <= 7; i++) { retval = retval << 1; if (input.Read()) { retval = retval + 1; } Clock(); } output_ce.Write(true); Debug.Print(retval.ToString()); // if (retval > 0) // uncomment if you want to keep the lights on DisplayLeds(retval); } private void DisplayLeds(int retval) { output_srclk.Write(false); // Bit reversal :) int copy = (int)((((ulong)retval * 0x0202020202UL) & 0x010884422010UL) % 1023); for (int i = 0; i <= 7; i++) { int x = copy & 1; if (x == 0) { output_ser.Write(false); } else { output_ser.Write(true); } output_clk.Write(true); output_clk.Write(false); copy = copy >> 1; } output_srclk.Write(true); output_srclk.Write(false); }
The DisplayLeds() method is copied from the Marquee project so I won’t cover that here. The steps to use the ‘165 are pretty simple.
- Toggle the load pin from Low -> High
- Set the clock enable pin Low
- For each pin
- Read the input pin
- Clock the CP pin Low->High
- Set the clock enable pin High
Final note : The input pins D0 -> D7 must be either high or pulled low. The ‘165 IC doesn’t behave well if they are left floating. I use a 10K resistor to ground the pin in the absence of current. It’s probably not the most efficient way to do this. I didn’t have enough NPN transistors or DPST buttons.