11 Oct 2011

Knight Rider with 74HC594 8 bit shift register

Please note, the next article «Finally a threesome» includes an arduino library for the 74HC595 (not for the 74HC594) and probably obsoletes this post.



As a follow up to the bit shift register (74HC595) example I ordered some more of these. Unfortunately MM74HC594 (Datasheet) were delivered. These chips are a bit more complicated to handle. Here is the same example as in the previous post:


As a byproduct of the above drawing,  I have created a Fritzing part for the 74HC594 chip.


Code:

/**
 * Board: Pro Mini 5V
 * 
 * Chained 74HC595 8 bit shift register demo. Knight Rider!
 *
 * Based on: http://bildr.org/2011/02/74hc595/
 * 
 * $Id: test_74HC595.pde 309 2011-10-13 18:50:44Z wunderlins $
 */

int PIN_SER = 8;   //pin 14 on the 75HC595
int PIN_SCK = 9;  //pin 12 on the 75HC595
int PIN_RCK = 10; //pin 11 on the 75HC595

// how many shift registers are chained? (must be >=1)
#define NUM_SHIFT_REGISTERS 3

// store all LED states in this array. every element of the array stores a 
// binary mask of of 8 pin states (per chip).
uint8_t pins[NUM_SHIFT_REGISTERS];

// reset all chips to 0
void sr_reset() {
 for(int i=0; i<NUM_SHIFT_REGISTERS; i++)
  pins[i] = 0;
}

// set a pin high or low. if you have 1 chip use pins 0-7, if youhave 2 chips
// you might use 0-7, 8-15 as pin numbers. state sets LED on (true) or 
// off (false)
void sr_set(int pin, bool state) {
 
 // check which register to manipulate
 int current = pin / 8;
 int p = pin - current*8;
 
 if (state == true) // set pin to true
  pins[current] |= 1 << p;
 else { // set pin to false
  int tmp = ~pins[current];
  tmp |= 1 << p;
  pins[current] = ~tmp;
 }
 
}

// check if pin is set to high
boolean sr_isset(int pin) {
 int current = pin / 8;
 int p = pin - current*8;
 if ((1 << p) & pins[current])
  return true;
 return false;
}

// move data into shift register and from there into storage at once. make 
// sure to fill the shift pins before acitivating the storage pins.
void sr_update() {
 
 digitalWrite(PIN_SCK, LOW);
 
 // set state
 for(int i=8 * NUM_SHIFT_REGISTERS - 1; i >= 0 ; i--) {
  digitalWrite(PIN_RCK, LOW);
  
  if (sr_isset(i))
   digitalWrite(PIN_SER, HIGH); // ON
  else
   digitalWrite(PIN_SER, LOW); // OFF

  digitalWrite(PIN_RCK, HIGH);
 }
 
 digitalWrite(PIN_SCK, HIGH);
}

void setup(){
  pinMode(PIN_SER, OUTPUT);
  pinMode(PIN_SCK, OUTPUT);
  pinMode(PIN_RCK, OUTPUT);

 // initialize pin state
 sr_reset();
 
}               

int i = 0;
int direction = 1; // 1 = L2R, -1 R2L
void loop(){
 
 sr_reset();
 sr_set(i, true);
 sr_update();
 
  if (i+1 == NUM_SHIFT_REGISTERS * 8) {
   direction = -1;
  } else if (i == 0) {
   direction = 1;
  }
  i += direction;

  delay(100);
}