Shift Registers are a specific type of semiconductor which use bitwise control to toggle outputs. In doing so, a number of outputs can be controlled with minimal wires or programming.
For the examples this document, we’ll be focusing on the Texas Instruments 6b595, which has been replaced by the 6b596 and 6b598-Q1. They all function the same, but the manufacturing architecture and packages have been updated.
Additionally, this document is being written based on a set of 7-segment displays and custom PCB’s I made while a student at UTA some years ago. While Shift Registers can be used for many things, this document should give you a good concept of how they work and how you can implement them into your project.
Texas Instruments 6b595, 6b596, 6b598-Q1
The 595 and 596 are older products which were primarily available in a Dual Inline Package (DIP) array intended to go into a socket. The newer 598 is a Surface Mount Device (SMD) package intended to be soldered directly to a PCB.
Communication
Communication with shift registers is very straight forward, using three pins on the SPI protocol. The names of these pins can vary between microcontrollers.
Slave Select (SS) , Chip Select (CS), Peripheral Select (PS): This pin is RCK on the shift registers. When sending data to the shift register, this pin should be LOW, as setting it to HIGH is what commits the bit status to the internal transistor.
Master Out Slave In (MOSI), Controller Out Peripheral In (COPI): This pin is SER IN on the shift registers. This pin is pulsed by the SPI library to pass the individual bitstream.
Serial Clock (SCK or SCLK), Serial Running Clock (SRCK or SRCLK): This pin is the baseline carrier for the SPI interface, which keeps all devices on the bus synchronized for reading the bitstream.
When daisy-chaining shift registers, the SER OUT of the first chip goes to the SER IN of the second; SER OUT of the second goes to SER IN of the third, and so-forth. There is no limit for how many may be daisy-chained.
Organizing bits
Shift registers are a non-inverting semiconductor. Sending a ‘1’ turns that output on, sending a ‘0’ turns it off.
For these examples, the following layout is to be assumed:
Drain0 = Decimal Point
Drain1 = Segment C
Drain2 = Segment D
Drain3 = Segment E
Drain4 = Segment F
Drain5 = Segment A
Drain6 = Segment G
Drain7 = Segment B
Something to notice in the datasheet, is that the bits are processed backwards of counting logic – Drain7 as Most Significant Bit (MSB) and Drain0 as Least Significant Bit (LSB).
When daisy-chaining modules, the first instruction sent by the controller goes to the furthest shift register down the chain, with each following instruction to the next-furthest.
As a result, the output segment structure looks like this:
0 = b, g, a, f, e, d, c , p = B10111110 = 190
1 = b, g, a, f, e, d, c, p = B10000010 = 130
2 = b, g, a, f, e, d, c, p = B11101100 = 236
3 = b, g, a, f, e, d, c, p = B11100110 = 230
4 = b, g, a, f, e, d, c, p = B11010010 = 210
5 = b, g, a, f, e, d, c, p = B01110110 = 118
6 = b, g, a, f, e, d, c, p = B01111110 = 126
7 = b, g, a, f, e, d, c, p = B10100010 = 162
8 = b, g, a, f, e, d, c, p = B11111110 = 254
9 = b, g, a, f, e, d, c, p = B11110110 = 246
To turn on the decimal point, you just increment the number by 1, since the period is the LSB.
int alphaNumToInt(int alphaNum){
int intValue;
switch(alphaNum){
case 0:
//0 = a, b, c, d, e, f = B10111110 = 190
intValue = 190;
break;
case 1:
//1 = b,c = B10000010 = 130
intValue = 130;
break;
case 2:
//2 = a, b, g, e, d = B11101100 = 236
intValue = 236;
break;
case 3:
//3 = a, b, g, c, d = B11100110 = 230
intValue = 230;
break;
case 4:
//4 = f, g, b, c = B11010010 = 210
intValue = 210;
break;
case 5:
//5 = a, f, g, c, d = B01110110 = 118
intValue = 118;
break;
case 6:
//6 = a, f, g, c, e, d = B01111110 = 126
intValue = 126;
break;
case 7:
//7 = a, b, c = B10100010 = 162
intValue = 162;
break;
case 8:
//8 = all = B11111110 = 254
intValue = 254;
break;
case 9:
//9 = a, f, b, g, c, d = B11110110 = 246
intValue = 246;
break;
return intValue;
}
Sending Bits
Because the code I wrote used input knobs to determine what to send, I broke the code into multiple functions – reading the knobs, interpreting what each knob meant (alphanumeric), converting that alphanumeric to the proper int, then sending that int to the shift registers.
digitalWrite(slaveSelectPin,LOW);
SPI.transfer(alphaNumToIntPrd(dig1)); //turns on the Period
/Decimal Point
SPI.transfer(alphaNumToInt(dig2)); //period is off
SPI.transfer(alphaNumToInt(dig3));
SPI.transfer(alphaNumToInt(dig4));
SPI.transfer(alphaNumToInt(dig5));
SPI.transfer(alphaNumToInt(dig6));
SPI.transfer(alphaNumToInt(dig7));
digitalWrite(slaveSelectPin,HIGH);
Conclusion
Shift Registers are very simple to use and give you many options for turning them on and off. While most commonly used for 7 segment displays, they are frequently used anywhere that multiplexing, or turning on/off many circuits, may be performed.