Using a Shift register
Reasons for using a shift register:
A shift register is a device which takes a serial input and provides a parallel output.
The most common application is as a port expansion. Often you find yourself with too few pins when using a microcontroller, this is where a shift register comes in, by using 3 pins you can have anywhere from 8 to an infine number of ports (…slight exageration, as you will end up with timing problems)
Here i will describe a 74HC595. Its part of the TTL logic series, and a high current version (compared to 74LS595). Alternativly you could use the 74HC164, which functions in almost the same way except that the 74HC164 doesn’t have a latch, more about this later.
74HC595 Chip layout
Obviously this chip is powered and has both Vcc and GND, in my case, +5V and GND.
There are 8 ports, Q0-Q7 these are the parallel out pins.
DS is where we enter the serial data, which is pulsed in along with SH_CP (data clock).
We also have /OE which is the output enable pin, when this is high, Q0-Q7 are powered down.
When we are ready to show the data, we clock the latch pin, ST_CP.
Q7′ is the serial out, when the input overflows this pin will send the data to the next shift register, allowing you to place a large number in series.
Code for driving the shift register:
How the code works:
Lines 1-7 declare the pins on which the shift register are assigned
The function shift_data(outdate) sends the data tot he shift register by masking out all other bits and then clocking this out.
The function clear_shift(number of ics) clears the shift register by outputting 0’s for all the pins.
Fianlly the main function, here is a minimal function which only shoes the bare essentials, declartions for the pins have been removed.
First the shift register is cleared, and then data is shifted out. (This function would be repeated a number of times depending on how many shift registers are chained together.
Finally the output enable is brought high so that the pins are broght to 0 for 1 second.
Code:
[code lang="c"] //Declare pins for shift register #define clock portb.0 #define latch portb.1 #define data portb.2 #define MR portb.5 #define OE portb.4 #define SRdelay delay_us(10) void shift_data(unsigned char outdata){ //make sure all pins are low data=0; latch=0; clock=0; SRdelay; unsigned char mask=0; //Keep incrementing until overflow, and therefore == 0 for(mask=1;mask!=0;mask<<=1){ if((outdata&mask)>0) //Mask off all other bits, then check if remaining bit is high data=1; //Set data pin else data=0; //Set data pin clock=1; //raise clock pulse SRdelay; //Give a slight delay so that it can register (only nessacary if there is a //large number of chips on one line) clock=0; data=0; } //Data has been written, raise latch, to write data to output pins latch=1; SRdelay; latch=0; } void clear_shift(unsigned char ics){ unsigned char i=0; //Empty register, by writing 0 to all pins for (i=0;i<ics;i++) shift_data(0); } void main() { // Code initialization, declare variables etc clear_shift(2); shift_data(vals); OE=1; delay_s(2); OE=0; } [/code]
Speed
So far i haven’t experienced any problems with speed. Running 64516 bytes to the shift register, took less than 1ms even with a 10us pause between each bitshift opperation.
SRdelay | Time for 64516 loops (s) | Time per loop (us) |
nop() | 22.34 | 346 |
2us | 41.44 | 642 |
5us | 46.50 | 720 |
10us | 51.72 | 801 |