Control CD4021 and 74HC595 over the same SPI bus
Working on a project I needed extra digital in’s and extra digital out’s for my Arduino Uno (lots of LEDs, lots of buttons). I’ll use a CD4021 to extend the digital in’s and a 74HC595 to gain extra digital out’s. I decided it would be best to both access the data of the CD4021 and send data to the 74HC595 over the hardware SPI bus on the Arduino (see previous post). Turns out te be not that hard (fortunately ;) ). Here’s the eagle schematic for 1 4021 and 1 595. Of course you can cascade more IC’s if you need more in’s or out’s. Only difference is that you’ll have to interpret and send more bytes (1 byte per IC).
Here’s my Arduino code so far:
#include <SPI.h> #define PIN_SCK 13 // SPI clock #define PIN_MISO 12 // SPI data input #define PIN_MOSI 11 // SPI data output #define PIN_SS1 10 // SPI hardware default SS pin, 4021 #define PIN_595_1 9 // SPI 74HC595 // result byte for 4021 byte buttons8; // global vars for button timeout and debounce long button1timeout = 0; long button2timeout = 0; long debounce = 200; void setup() { Serial.begin(9600); SPI.begin(); // set all IC select pins HIGH digitalWrite(PIN_SS1,HIGH); pinMode(PIN_595_1, OUTPUT); digitalWrite(PIN_595_1,HIGH); } void loop() { // SS1 = HIGH -> 4021 is gathering data from parallel inputs // select 595 digitalWrite(PIN_595_1,LOW); // send BIN number to 595 to light 1 LED (not necessarily the 1 example LED on the schematic) SPI.transfer(B00000100); // deselect 595 digitalWrite(PIN_595_1,HIGH); // select 4021 digitalWrite(PIN_SS1,LOW); // read CD4021 IC buttons8 = SPI.transfer(0x00); // button functions and debounces // needs refactoring for smaller footprint if((B10000000 & buttons8) && (millis() - button1timeout > debounce)) { Serial.println("but1"); button1timeout = millis(); } if((B01000000 & buttons8) && (millis() - button2timeout > debounce)) { Serial.println("but2"); button2timeout = millis(); } // deselect 4021 digitalWrite(PIN_SS1,HIGH); }