CD4021B Shift Registers
A list of examples to modify CD4021B shift registers
Updated by Scott Fitzgerald Feb 2014
Shifting In & the CD4021B
Sometimes you'll end up needing more digital input than there are pins on your Arduino. Using a parallel to serial shift register you can collect information from 8 or more switches while only using 3 of the pins on your Arduino.
An example of a parallel to serial register is the CD4021B, sometimes referred to as an 8-Stage Static Shift Register. This means you can read the state of up to 8 digital inputs attached to the register all at once. This is called Asynchronous Parallel Input. "Input" because you are collecting information. "Parallel" because it is all at once, like hearing a musical cord. "Asynchronous" because the CD4021B is doing all this data collection at its own pace without coordinating with the Arduino.
The 8 inputs are translated into a series of HIGH and LOW pulses on the serial-out pin of the shift register. This pin should be connected to an input pin on your Arduino Board, referred to as the data pin. The transfer of information on the data pin is called "Synchronous Serial Output" because the shift register waits to deliver linear sequence of data to the Arduino until the Arduino asks for it. Synchronous Serial communication, either input or output, is heavily reliant on what is referred to as a clock pin. The clock pin is the metronome of the conversation between the shift register and the Arduino, it is what keeps the two systems synchronous. Every time the Arduino changes the clock pin from LOW to HIGH the shift register changes the state of the Serial Output pin, indicating the value of the next switch.
The third pin attached to the Arduino is a "Parallel to Serial Control" pin. It is referred to as a latch pin. When the latch pin is HIGH the shift register is listening to its 8 parallel inputs. When the latch pin is LOW, it listens to the clock pin and passes information serially. That means every time the latch pin transitions from HIGH to LOW the shift register will start passing its most current switch information.
The pseudo code to coordinate this all looks something like this:
Make sure the register has the latest information from its parallel inputs (i.e. that the latch pin is HIGH)
Tell the register the Arduino is ready to get the information serially (latch pin LOW)
For each of the inputs that are to be read, pulse the clockPin and check to see if the data pin is LOW or HIGH
This is a basic diagram.
1_______2switch -> | |3switch -> | C |4switch -> | D |5switch -> | 4 | -> Serial Data to Arduino6switch -> | 0 |7switch -> | 2 |8switch -> | 1 | <- Clock Data from Arduino9switch -> |_____| <- Latch Data from Arduino
There is more information about shifting in the ShiftOut tutorial.
Before you start wiring up your board here is the pin diagram of the CD4021 from the Texas Instruments Datasheet
PINS 1,4-7, 13-15
P1, P8 (Pins 0-7)
Parallel Inputs
PINS 2, 12, 3
Q6, Q7, Q8
Serial Output Pins from different steps in the sequence. Q7 is a pulse behind Q8 and Q6 is a pulse behind Q7. Q8 is the only one used in these examples.
PIN 8
Vss
GND
PIN 9
P/S C
Parallel/Serial Control (latch pin)
PIN 10
CLOCK
Shift register clock pin
PIN 11
SERIAL-IN
Serial data input
PIN 16
VDD
DC supply voltage
Example 1: One Shift Register
The first step is to extend your Arduino with one shift register.
The Circuit
1. Power Connections
Make the following connections:
GND (pin 8) to ground,
VDD (pin 16) to 5V
2.Connect to Arduino
Q8 (pin 3) to Ardunio DigitalPin 9 (blue wire)
CLOCK (pin 10) to to Ardunio DigitalPin 7 (yellow wire)
P/S C (pin 9) to Ardunio DigitalPin 8 (green wire)
From now on those will be referred to as the dataPin, the clockPin and the latchPin respectively.
3. Add 8 Switches
Diagram
The Code
Code Sample 1.1 Hello World Code Sample 1.2 What is Pressed? Code Sample 1.3 Button Combination Check Code Sample 1.4 Is it pressed? (sub-function)
Example 2: Multiple Shift Registers
In this example you'll add a second shift register, doubling the number of input pins while still using the same number of pins on the Arduino.
If supplementing your Arduino with an additional 8 digital inputs isn't going to be enough for your project, you can have a second CD4021 pass its information on to another CD4021 which will stream all 16 bits of information to the Arduino. If you know you will need to use multiple shift registers like this, check that any shift registers you buy can handle Synchronous Serial Input as well as the standard Synchronous Serial Output capability. Synchronous Serial Input is the feature that allows the first shift register to receive and transmit the serial output from a second one. The example below details how to use this system. Within reason, you can keep extending this daisy-chain of shift registers until you have all the inputs you need.
1_______2switch -> | |3switch -> | C |4switch -> | D |5switch -> | 4 | -> Serial Data to Arduino6switch -> | 0 |7switch -> | 2 | <- Clock Data from Arduino8switch -> | 1 | <- Latch Data from Arduino9switch -> |_____| <------10|11|12|13_______ | Serial Data Passed to First14switch -> | | | Shift Register15switch -> | C | |16switch -> | D | |17switch -> | 4 | ______|18switch -> | 0 |19switch -> | 2 | <- Clock Data from Arduino20switch -> | 1 | <- Latch Data from Arduino21switch -> |_____|
The Circuit
1. Add a second shift register.
2. Connect the 2 registers.
Two of these connections simply extend the same clock and latch signal from the Arduino to the second shift register (yellow and green wires). The blue wire is going from the serial out pin (pin 9) of the first shift register to the serial data input (pin 14) of the second register.
3. Add a second set of Switches.
Notice that there is one momentary switch and the rest are toggle switches. This is because the code examples will be using the switches attached to the second shift register as settings, like a preference file, rather than as event triggers. The one momentary switch will be telling the microcontroller that the setting switches are being changed.
Diagram
The Code
- Code Sample 2.1 Hello World
- Code Sample 2.2 Using the second byte for settings, Print all
- Code Sample 2.3 Using the second byte for settings, Print on only (uses sub-function)
Examples
ShftIn11
1//**************************************************************//2// Name : shiftIn Example 1.1 //3// Author : Carlyn Maw //4// Date : 25 Jan, 2007 //5// Version : 1.0 //6// Notes : Code for using a CD4021B Shift Register //7// : //8//****************************************************************9
10//define where your pins are11int latchPin = 8;12int dataPin = 9;13int clockPin = 7;14
15//Define variables to hold the data16//for shift register.17//starting with a non-zero numbers can help18//troubleshoot19byte switchVar1 = 72; //0100100020
21void setup() {22
23 //start serial24
25 Serial.begin(9600);26
27 //define pin modes28
29 pinMode(latchPin, OUTPUT);30
31 pinMode(clockPin, OUTPUT);32
33 pinMode(dataPin, INPUT);34
35}36
37void loop() {38
39 //Pulse the latch pin:40
41 //set it to 1 to collect parallel data42
43 digitalWrite(latchPin,1);44
45 //set it to 1 to collect parallel data, wait46
47 delayMicroseconds(20);48
49 //set it to 0 to transmit data serially50
51 digitalWrite(latchPin,0);52
53 //while the shift register is in serial mode54
55 //collect each shift register into a byte56
57 //the register attached to the chip comes in first58
59 switchVar1 = shiftIn(dataPin, clockPin);60
61 //Print out the results.62
63 //leading 0's at the top of the byte64
65 //(7, 6, 5, etc) will be dropped before66
67 //the first pin that has a high input68
69 //reading70
71 Serial.println(switchVar1, BIN);72
73//white space74Serial.println("-------------------");75//delay so all these print statements can keep up.76delay(500);77
78}79
80//------------------------------------------------end main loop81
82////// ----------------------------------------shiftIn function83///// just needs the location of the data pin and the clock pin84///// it returns a byte with each bit in the byte corresponding85///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 086
87byte shiftIn(int myDataPin, int myClockPin) {88
89 int i;90
91 int temp = 0;92
93 int pinState;94
95 byte myDataIn = 0;96
97 pinMode(myClockPin, OUTPUT);98
99 pinMode(myDataPin, INPUT);100//we will be holding the clock pin high 8 times (0,..,7) at the101//end of each time through the for loop102
103//at the beginning of each loop when we set the clock low, it will104//be doing the necessary low to high drop to cause the shift105//register's DataPin to change state based on the value106//of the next bit in its serial information flow.107//The register transmits the information about the pins from pin 7 to pin 0108//so that is why our function counts down109
110 for (i=7; i>=0; i--)111
112 {113
114 digitalWrite(myClockPin, 0);115
116 delayMicroseconds(0.2);117
118 temp = digitalRead(myDataPin);119
120 if (temp) {121
122 pinState = 1;123
124 //set the bit to 0 no matter what125
126 myDataIn = myDataIn | (1 << i);127
128 }129
130 else {131
132 //turn it off -- only necessary for debugging133
134 //print statement since myDataIn starts as 0135
136 pinState = 0;137
138 }139
140 //Debugging print statements141
142 //Serial.print(pinState);143
144 //Serial.print(" ");145
146 //Serial.println (dataIn, BIN);147
148 digitalWrite(myClockPin, 1);149
150 }151
152 //debugging print statements whitespace153
154 //Serial.println();155
156 //Serial.println(myDataIn, BIN);157
158 return myDataIn;159}
ShftIn12
1//**************************************************************//2// Name : shiftIn Example 1.2 //3// Author : Carlyn Maw //4// Date : 25 Jan, 2007 //5// Version : 1.0 //6// Notes : Code for using a CD4021B Shift Register //7// : //8//****************************************************************9
10//define where your pins are11int latchPin = 8;12int dataPin = 9;13int clockPin = 7;14
15//Define variables to hold the data16//for shift register.17//starting with a non-zero numbers can help18//troubleshoot19byte switchVar1 = 72; //0100100020
21//define an array that corresponds to values for each22//of the shift register's pins23char note2sing[] = {24
25 'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};26
27void setup() {28
29 //start serial30
31 Serial.begin(9600);32
33 //define pin modes34
35 pinMode(latchPin, OUTPUT);36
37 pinMode(clockPin, OUTPUT);38
39 pinMode(dataPin, INPUT);40
41}42
43void loop() {44
45 //Pulse the latch pin:46
47 //set it to 1 to collect parallel data48
49 digitalWrite(latchPin,1);50
51 //set it to 1 to collect parallel data, wait52
53 delayMicroseconds(20);54
55 //set it to 0 to transmit data serially56
57 digitalWrite(latchPin,0);58
59 //while the shift register is in serial mode60
61 //collect each shift register into a byte62
63 //the register attached to the chip comes in first64
65 switchVar1 = shiftIn(dataPin, clockPin);66
67 //Print out the results.68
69 //leading 0's at the top of the byte70
71 //(7, 6, 5, etc) will be dropped before72
73 //the first pin that has a high input74
75 //reading76
77 Serial.println(switchVar1, BIN);78
79 //This for-loop steps through the byte80
81 //bit by bit which holds the shift register data82
83 //and if it was high (1) then it prints84
85 //the corresponding location in the array86
87 for (int n=0; n<=7; n++)88
89 {90
91 //so, when n is 3, it compares the bits92
93 //in switchVar1 and the binary number 0000100094
95 //which will only return true if there is a96
97 //1 in that bit (ie that pin) from the shift98
99 //register.100
101 if (switchVar1 & (1 << n) ){102
103 //print the value of the array location104
105 Serial.println(note2sing[n]);106
107 }108
109 }110
111//white space112Serial.println("-------------------");113//delay so all these print statements can keep up.114delay(500);115
116}117
118//------------------------------------------------end main loop119
120////// ----------------------------------------shiftIn function121///// just needs the location of the data pin and the clock pin122///// it returns a byte with each bit in the byte corresponding123///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0124
125byte shiftIn(int myDataPin, int myClockPin) {126
127 int i;128
129 int temp = 0;130
131 int pinState;132
133 byte myDataIn = 0;134
135 pinMode(myClockPin, OUTPUT);136
137 pinMode(myDataPin, INPUT);138//we will be holding the clock pin high 8 times (0,..,7) at the139//end of each time through the for loop140
141//at the beginning of each loop when we set the clock low, it will142//be doing the necessary low to high drop to cause the shift143//register's DataPin to change state based on the value144//of the next bit in its serial information flow.145//The register transmits the information about the pins from pin 7 to pin 0146//so that is why our function counts down147
148 for (i=7; i>=0; i--)149
150 {151
152 digitalWrite(myClockPin, 0);153
154 delayMicroseconds(0.2);155
156 temp = digitalRead(myDataPin);157
158 if (temp) {159
160 pinState = 1;161
162 //set the bit to 0 no matter what163
164 myDataIn = myDataIn | (1 << i);165
166 }167
168 else {169
170 //turn it off -- only necessary for debugging171
172 //print statement since myDataIn starts as 0173
174 pinState = 0;175
176 }177
178 //Debugging print statements179
180 //Serial.print(pinState);181
182 //Serial.print(" ");183
184 //Serial.println (dataIn, BIN);185
186 digitalWrite(myClockPin, 1);187
188 }189
190 //debugging print statements whitespace191
192 //Serial.println();193
194 //Serial.println(myDataIn, BIN);195
196 return myDataIn;197}
ShftIn13
1//**************************************************************//2// Name : shiftIn Example 1.3 //3// Author : Carlyn Maw //4// Date : 25 Jan, 2007 //5// Version : 1.0 //6// Notes : Code for using a CD4021B Shift Register //7// : //8//****************************************************************9
10//define where your pins are11int latchPin = 8;12int dataPin = 9;13int clockPin = 7;14
15//Define variables to hold the data16//for shift register.17//starting with a non-zero numbers can help18//troubleshoot19byte switchVar1 = 72; //0100100020
21//define an array that corresponds to values for each22//of the shift register's pins23char note2sing[] = {24
25 'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};26
27void setup() {28
29 //start serial30
31 Serial.begin(9600);32
33 //define pin modes34
35 pinMode(latchPin, OUTPUT);36
37 pinMode(clockPin, OUTPUT);38
39 pinMode(dataPin, INPUT);40
41}42
43void loop() {44
45 //Pulse the latch pin:46
47 //set it to 1 to collect parallel data48
49 digitalWrite(latchPin,1);50
51 //set it to 1 to collect parallel data, wait52
53 delayMicroseconds(20);54
55 //set it to 0 to transmit data serially56
57 digitalWrite(latchPin,0);58
59 //while the shift register is in serial mode60
61 //collect each shift register into a byte62
63 //the register attached to the chip comes in first64
65 switchVar1 = shiftIn(dataPin, clockPin);66
67 //Print out the results.68
69 //leading 0's at the top of the byte70
71 //(7, 6, 5, etc) will be dropped before72
73 //the first pin that has a high input74
75 //reading76
77 Serial.println(switchVar1, BIN);78
79 //This for-loop steps through the byte80
81 //bit by bit which holds the shift register data82
83 //and if it was high (1) then it prints84
85 //the corresponding location in the array86
87 for (int n=0; n<=7; n++)88
89 {90
91 //so, when n is 3, it compares the bits92
93 //in switchVar1 and the binary number 0000100094
95 //which will only return true if there is a96
97 //1 in that bit (ie that pin) from the shift98
99 //register.100
101 if (switchVar1 & (1 << n) ){102
103 //print the value of the array location104
105 Serial.println(note2sing[n]);106
107 }108
109 }110
111//This following is a away to examine the whole112//byte at once and create combinations113//of settings.114
115//By passing the switchVar1 variable to116//a "switch" statement and comparing it against117//a set nemerical value (written in binary)118//you can create special cases119
120 switch (switchVar1) {121
122 case 0b00101010:123
124 Serial.println("D minor");125
126 break;127
128 case 0b00010101:129
130 Serial.println("C major");131
132 break;133
134 case 0b01010100:135
136 Serial.println("E minor");137
138 break;139
140 case 0b00101001:141
142 Serial.println("F major");143
144 break;145
146 case 0b01010010:147
148 Serial.println("G major");149
150 break;151
152 case 0b00100101:153
154 Serial.println("A minor");155
156 break;157
158 case 0b01001010:159
160 Serial.println("B diminished");161
162 break;163
164 default:165
166 // if nothing else matches, do the default167
168 Serial.println("Play It, Joe");169
170 }171
172//white space173Serial.println("-------------------");174//delay so all these print statements can keep up.175delay(500);176
177}178
179//------------------------------------------------end main loop180
181////// ----------------------------------------shiftIn function182///// just needs the location of the data pin and the clock pin183///// it returns a byte with each bit in the byte corresponding184///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0185
186byte shiftIn(int myDataPin, int myClockPin) {187
188 int i;189
190 int temp = 0;191
192 int pinState;193
194 byte myDataIn = 0;195
196 pinMode(myClockPin, OUTPUT);197
198 pinMode(myDataPin, INPUT);199//we will be holding the clock pin high 8 times (0,..,7) at the200//end of each time through the for loop201
202//at the beginning of each loop when we set the clock low, it will203//be doing the necessary low to high drop to cause the shift204//register's DataPin to change state based on the value205//of the next bit in its serial information flow.206//The register transmits the information about the pins from pin 7 to pin 0207//so that is why our function counts down208
209 for (i=7; i>=0; i--)210
211 {212
213 digitalWrite(myClockPin, 0);214
215 delayMicroseconds(0.2);216
217 temp = digitalRead(myDataPin);218
219 if (temp) {220
221 pinState = 1;222
223 //set the bit to 0 no matter what224
225 myDataIn = myDataIn | (1 << i);226
227 }228
229 else {230
231 //turn it off -- only necessary for debugging232
233 //print statement since myDataIn starts as 0234
235 pinState = 0;236
237 }238
239 //Debugging print statements240
241 //Serial.print(pinState);242
243 //Serial.print(" ");244
245 //Serial.println (dataIn, BIN);246
247 digitalWrite(myClockPin, 1);248
249 }250
251 //debugging print statements whitespace252
253 //Serial.println();254
255 //Serial.println(myDataIn, BIN);256
257 return myDataIn;258}
ShftIn14
1//**************************************************************//2// Name : shiftIn Example 1.4 //3// Author : Carlyn Maw //4// Date : 25 Jan, 2007 //5// Version : 1.0 //6// Notes : Code for using a CD4021B Shift Register //7// : //8//****************************************************************9
10//define where your pins are11int latchPin = 8;12int dataPin = 9;13int clockPin = 7;14
15//Define variables to hold the data16//for shift register.17//starting with a non-zero numbers can help18//troubleshoot19byte switchVar1 = 72; //0100100020
21byte lowcBitNum = 7;22byte dBitNum = 6;23byte eBitNum = 5;24byte fBitNum = 4;25byte gBitNum = 3;26byte aBitNum = 2;27byte bBitNum = 1;28byte highcNum = 0;29
30boolean dBit;31
32void setup() {33
34 //start serial35
36 Serial.begin(9600);37
38 //define pin modes39
40 pinMode(latchPin, OUTPUT);41
42 pinMode(clockPin, OUTPUT);43
44 pinMode(dataPin, INPUT);45
46}47
48void loop() {49
50 //Pulse the latch pin:51
52 //set it to 1 to collect parallel data53
54 digitalWrite(latchPin,1);55
56 //set it to 1 to collect parallel data, wait57
58 delayMicroseconds(20);59
60 //set it to 0 to transmit data serially61
62 digitalWrite(latchPin,0);63
64 //while the shift register is in serial mode65
66 //collect each shift register into a byte67
68 //the register attached to the chip comes in first69
70 switchVar1 = shiftIn(dataPin, clockPin);71
72 //Print out the results.73
74 //leading 0's at the top of the byte75
76 //(7, 6, 5, etc) will be dropped before77
78 //the first pin that has a high input79
80 //reading81
82 Serial.println(switchVar1, BIN);83
84//You can get a bit state through the subfunction85//written below by either...86
87//setting a boolean variable88
89dBit = getBit(switchVar1, dBitNum);90
91 if (dBit) {92
93 Serial.println("D");94
95 }96
97//just validating a function (no new variable required)98
99 if (getBit(switchVar1, aBitNum)) {100
101 Serial.println("A");102
103 }104
105//white space106Serial.println("-------------------");107//delay so all these print statements can keep up.108delay(500);109
110}111
112//------------------------------------------------end main loop113
114////// ----------------------------------------shiftIn function115///// just needs the location of the data pin and the clock pin116///// it returns a byte with each bit in the byte corresponding117///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0118
119byte shiftIn(int myDataPin, int myClockPin) {120
121//internal function setup122
123 int i;124
125 int temp = 0;126
127 int pinState;128
129 byte myDataIn = 0;130
131 pinMode(myClockPin, OUTPUT);132
133 pinMode(myDataPin, INPUT);134
135//we will be holding the clock pin high 8 times (0,..,7) at the136//end of each time through the for loop137
138//at the beginning of each loop when we set the clock low, it will139//be doing the necessary low to high drop to cause the shift140//register's DataPin to change state based on the value141//of the next bit in its serial information flow.142//The register transmits the information about the pins from pin 7 to pin 0143//so that is why our function counts down144
145 for (i=7; i>=0; i--)146
147 {148
149 digitalWrite(myClockPin, 0);150
151 delayMicroseconds(0.2);152
153 temp = digitalRead(myDataPin);154
155 if (temp) {156
157 pinState = 1;158
159 //set the bit to 0 no matter what160
161 myDataIn = myDataIn | (1 << i);162
163 }164
165 else {166
167 //turn it off -- only necessary for debugging168
169 //print statement since myDataIn starts as 0170
171 pinState = 0;172
173 }174
175 //Debugging print statements176
177 //Serial.print(pinState);178
179 //Serial.print(" ");180
181 //Serial.println (dataIn, BIN);182
183 digitalWrite(myClockPin, 1);184
185 }186
187 //debugging print statements whitespace188
189 //Serial.println();190
191 //Serial.println(myDataIn, BIN);192
193 return myDataIn;194}195
196////// ----------------------------------------getBit197boolean getBit(byte myVarIn, byte whatBit) {198
199 boolean bitState;200
201 bitState = myVarIn & (1 << whatBit);202
203 return bitState;204}205
206////// A little extra function...207////// ----------------------------------------setBit208byte setBit(byte myVarIn, byte whatBit, boolean s) {209
210 boolean bitState;211
212 if (s) {213
214 myVarIn = myVarIn | (1 << whatBit);215
216 } else {217
218 myVarIn = myVarIn & ~(1 << whatBit);219
220 }221
222 return myVarIn;223}
ShftIn21
1//**************************************************************//2// Name : shiftIn Example 2.1 //3// Author : Carlyn Maw //4// Date : 25 Jan, 2007 //5// Version : 1.0 //6// Notes : Code for using a CD4021B Shift Register //7// : //8//****************************************************************9
10//define where your pins are11int latchPin = 8;12int dataPin = 9;13int clockPin = 7;14
15//Define variables to hold the data16//for each shift register.17//starting with non-zero numbers can help18//troubleshoot19byte switchVar1 = 72; //0100100020byte switchVar2 = 159; //1001111121
22void setup() {23
24 //start serial25
26 Serial.begin(9600);27
28 //define pin modes29
30 pinMode(latchPin, OUTPUT);31
32 pinMode(clockPin, OUTPUT);33
34 pinMode(dataPin, INPUT);35
36}37
38void loop() {39
40 //Pulse the latch pin:41
42 //set it to 1 to collect parallel data43
44 digitalWrite(latchPin,1);45
46 //set it to 1 to collect parallel data, wait47
48 delayMicroseconds(20);49
50 //set it to 0 to transmit data serially51
52 digitalWrite(latchPin,0);53
54 //while the shift register is in serial mode55
56 //collect each shift register into a byte57
58 //the register attached to the chip comes in first59
60 switchVar1 = shiftIn(dataPin, clockPin);61
62 switchVar2 = shiftIn(dataPin, clockPin);63
64 //Print out the results.65
66 //leading 0's at the top of the byte67
68 //(7, 6, 5, etc) will be dropped before69
70 //the first pin that has a high input71
72 //reading73
74 Serial.println(switchVar1, BIN);75
76 Serial.println(switchVar2, BIN);77
78//white space79Serial.println("-------------------");80//delay so all these print statements can keep up.81delay(500);82
83}84
85//------------------------------------------------end main loop86
87////// ----------------------------------------shiftIn function88///// just needs the location of the data pin and the clock pin89///// it returns a byte with each bit in the byte corresponding90///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 091
92byte shiftIn(int myDataPin, int myClockPin) {93
94 int i;95
96 int temp = 0;97
98 int pinState;99
100 byte myDataIn = 0;101
102 pinMode(myClockPin, OUTPUT);103
104 pinMode(myDataPin, INPUT);105
106//we will be holding the clock pin high 8 times (0,..,7) at the107//end of each time through the for loop108
109//at the beginning of each loop when we set the clock low, it will110//be doing the necessary low to high drop to cause the shift111//register's DataPin to change state based on the value112//of the next bit in its serial information flow.113//The register transmits the information about the pins from pin 7 to pin 0114//so that is why our function counts down115
116 for (i=7; i>=0; i--)117
118 {119
120 digitalWrite(myClockPin, 0);121
122 delayMicroseconds(2);123
124 temp = digitalRead(myDataPin);125
126 if (temp) {127
128 pinState = 1;129
130 //set the bit to 0 no matter what131
132 myDataIn = myDataIn | (1 << i);133
134 }135
136 else {137
138 //turn it off -- only necessary for debugging139
140 //print statement since myDataIn starts as 0141
142 pinState = 0;143
144 }145
146 //Debugging print statements147
148 //Serial.print(pinState);149
150 //Serial.print(" ");151
152 //Serial.println (dataIn, BIN);153
154 digitalWrite(myClockPin, 1);155
156 }157
158 //debugging print statements whitespace159
160 //Serial.println();161
162 //Serial.println(myDataIn, BIN);163
164 return myDataIn;165}
ShftIn22
1//**************************************************************//2// Name : shiftIn Example 2.2 //3// Author : Carlyn Maw //4// Date : 25 Jan, 2007 //5// Version : 1.0 //6// Notes : Code for using a CD4021B Shift Register //7// : //8//****************************************************************9
10//define where your pins are11int latchPin = 8;12int dataPin = 9;13int clockPin = 7;14
15//Define variables to hold the data16//for each shift register.17//starting with non-zero numbers can help18//troubleshoot19byte switchVar1 = 72; //0100100020byte switchVar2 = 159; //1001111121
22//define an array that corresponds to values for each23//of the first shift register's pins24char note2sing[] = {25
26 'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};27
28//define an array that has a place for the values of29//pins 1-7 (not 0) of the second shift register's30//pins. Not 0 because that will be used as a flag value31byte settingVal[] = {32
33 0, 0, 0, 0, 0, 0, 0};34
35//a flag variable used to track whether the program36//is in a setting update mode or not37byte settingSwitch = 0;38
39void setup() {40
41 //start serial42
43 Serial.begin(9600);44
45 //define pin modes46
47 pinMode(latchPin, OUTPUT);48
49 pinMode(clockPin, OUTPUT);50
51 pinMode(dataPin, INPUT);52
53}54
55void loop() {56
57 //Pulse the latch pin:58
59 //set it to 1 to collect parallel data60
61 digitalWrite(latchPin,1);62
63 //set it to 1 to collect parallel data, wait64
65 delayMicroseconds(20);66
67 //set it to 0 to transmit data serially68
69 digitalWrite(latchPin,0);70
71 //while the shift register is in serial mode72
73 //collect each shift register into a byte74
75 //the register attached to the chip comes in first76
77 switchVar1 = shiftIn(dataPin, clockPin);78
79 switchVar2 = shiftIn(dataPin, clockPin);80
81 //Print out the results.82
83 //leading 0's at the top of the byte84
85 //(7, 6, 5, etc) will be dropped before86
87 //the first pin that has a high input88
89 //reading90
91 Serial.println(switchVar1, BIN);92
93 Serial.println(switchVar2, BIN);94
95 //This for-loop steps through the byte96
97 //bit by bit which holds the shift register data98
99 //and if it was high (1) then it prints100
101 //the corresponding location in the array102
103 for (int n=0; n<=7; n++)104
105 {106
107 //so, when n is 3, it compares the bits108
109 //in switchVar1 and the binary number 00001000110
111 //which will only return true if there is a112
113 //1 in that bit (ie that pin) from the shift114
115 //register.116
117 if (switchVar1 & (1 << n) ){118
119 //print the value of the array location120
121 Serial.println(note2sing[n]);122
123 }124
125 }126
127//This is a away to examine the whole128//byte at once and create combinations129//of settings.130
131//By passing the switchVar1 variable to132//a "switch" statement and comparing it against133//a set nemerical value (written in binary)134//you can create special cases135
136 switch (switchVar1) {137
138 case 0b00101010:139
140 Serial.println("D minor");141
142 break;143
144 case 0b00010101:145
146 Serial.println("C major");147
148 break;149
150 case 0b01010100:151
152 Serial.println("E minor");153
154 break;155
156 case 0b00101001:157
158 Serial.println("F major");159
160 break;161
162 case 0b01010010:163
164 Serial.println("G major");165
166 break;167
168 case 0b00100101:169
170 Serial.println("A minor");171
172 break;173
174 case 0b01001010:175
176 Serial.println("B diminished");177
178 break;179
180 default:181
182 // if nothing else matches, do the default183
184 Serial.println("Play It, Joe");185
186 }187
188//--- SHIFT REGISTER 2189// This is a more complicated behavior190
191//If the switch attached to pin 7 is High192
193 if (switchVar2 & (1 << 7) ){194
195 //print"Check, Check" to let us know the settings are being updated"196
197 Serial.println("Check, Check");198
199 //set a flag variable to let the program know the settings are being updated200
201 settingSwitch = 1;202
203 //While the switch attached to seven is high,204
205 //take the bottom 7 bits and load them into206
207 //an array for easy access later.208
209 for (int v=6; v>=0; v--)210
211 {212
213 if (switchVar2 & (1 << v) ){214
215 settingVal[v] = 1;216
217 }218
219 else {220
221 settingVal[v] = 0;222
223 }224
225 }226
227 }228
229 //if the switch is low230
231 else {232
233 //and if it was high the very last time it came through234
235 //this if statement (indicated by the settingSwitch variable still236
237 //set to "1")238
239 if (settingSwitch) {240
241 //turn off the settingSwitch variable242
243 settingSwitch=0;244
245 //Print out the current settings246
247 Serial.println("___SETTINGS___");248
249 for (int s=0; s<=6; s++)250
251 {252
253 //Print out the setting names254
255 //this is being done as a case statement because256
257 //there weren't built in string arrays yet258
259 //in Arduino as of Feb. 2007260
261 switch (s) {262
263 case 0:264
265 Serial.print("Mute");266
267 break;268
269 case 1:270
271 Serial.print("Octave Shift");272
273 break;274
275 case 2:276
277 Serial.print("Delay");278
279 break;280
281 case 3:282
283 Serial.print("Reverb");284
285 break;286
287 case 4:288
289 Serial.print("Vibrato");290
291 break;292
293 case 5:294
295 Serial.print("Funkify");296
297 break;298
299 case 6:300
301 Serial.print("Dampen");302
303 break;304
305 default:306
307 // if nothing else matches, do the default308
309 Serial.println("Not Defined");310
311 }312
313 //Print Status314
315 if (settingVal[s]) {316
317 Serial.print(" On");318
319 }320
321 else {322
323 Serial.print(" Off") ;324
325 }326
327 //white space328
329 Serial.println();330
331 }332
333 }334
335 }336
337//white space338Serial.println("-------------------");339//delay so all these print statements can keep up.340delay(500);341
342}343
344//------------------------------------------------end main loop345
346////// ----------------------------------------shiftIn function347///// just needs the location of the data pin and the clock pin348///// it returns a byte with each bit in the byte corresponding349///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0350byte shiftIn(int myDataPin, int myClockPin) {351
352 int i;353
354 int temp = 0;355
356 int pinState;357
358 byte myDataIn = 0;359
360 pinMode(myClockPin, OUTPUT);361
362 pinMode(myDataPin, INPUT);363//we will be holding the clock pin high 8 times (0,..,7) at the364//end of each time through the for loop365
366//at the beginning of each loop when we set the clock low, it will367//be doing the necessary low to high drop to cause the shift368//register's DataPin to change state based on the value369//of the next bit in its serial information flow.370//The register transmits the information about the pins from pin 7 to pin 0371//so that is why our function counts down372
373 for (i=7; i>=0; i--)374
375 {376
377 digitalWrite(myClockPin, 0);378
379 delayMicroseconds(2);380
381 temp = digitalRead(myDataPin);382
383 if (temp) {384
385 pinState = 1;386
387 //set the bit to 0 no matter what388
389 myDataIn = myDataIn | (1 << i);390
391 }392
393 else {394
395 //turn it off -- only necessary for debugging396
397 //print statement since myDataIn starts as 0398
399 pinState = 0;400
401 }402
403 //Debugging print statements404
405 //Serial.print(pinState);406
407 //Serial.print(" ");408
409 //Serial.println (dataIn, BIN);410
411 digitalWrite(myClockPin, 1);412
413 }414
415 //debugging print statements whitespace416
417 //Serial.println();418
419 //Serial.println(myDataIn, BIN);420
421 return myDataIn;422}
ShftIn23
1//**************************************************************//2// Name : shiftIn Example 2.3 //3// Author : Carlyn Maw //4// Date : 25 Jan, 2007 //5// Version : 1.0 //6// Notes : Code for using a CD4021B Shift Register //7// : //8//****************************************************************9
10//define where your pins are11int latchPin = 8;12int dataPin = 9;13int clockPin = 7;14
15//Define variables to hold the data16//for each shift register.17//starting with non-zero numbers can help18//troubleshoot19byte switchVar1 = 72; //0100100020byte switchVar2 = 159; //1001111121
22//define an array that corresponds to values for each23//of the first shift register's pins24char note2sing[] = {25
26 'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};27
28//define an array that has a place for the values of29//pins 1-7 (not 0) of the second shift register's30//pins. Not 0 because that will be used as a flag value31byte settingVal[] = {32
33 0, 0, 0, 0, 0, 0, 0};34
35boolean MuteBit = 0;36boolean OctShftBit = 1;37boolean DelayBit = 2;38boolean ReverbBit = 3;39boolean VibratoBit = 4;40boolean FunkifyBit = 5;41boolean DampenBit = 6;42
43//a flag variable used to track whether the program44//is in a setting update mode or not45byte settingSwitch = 0;46
47void setup() {48
49 //start serial50
51 Serial.begin(9600);52
53 //define pin modes54
55 pinMode(latchPin, OUTPUT);56
57 pinMode(clockPin, OUTPUT);58
59 pinMode(dataPin, INPUT);60
61}62
63void loop() {64
65 //Pulse the latch pin:66
67 //set it to 1 to collect parallel data68
69 digitalWrite(latchPin,1);70
71 //set it to 1 to collect parallel data, wait72
73 delayMicroseconds(20);74
75 //set it to 0 to transmit data serially76
77 digitalWrite(latchPin,0);78
79 //while the shift register is in serial mode80
81 //collect each shift register into a byte82
83 //the register attached to the chip comes in first84
85 switchVar1 = shiftIn(dataPin, clockPin);86
87 switchVar2 = shiftIn(dataPin, clockPin);88
89 //Print out the results.90
91 //leading 0's at the top of the byte92
93 //(7, 6, 5, etc) will be dropped before94
95 //the first pin that has a high input96
97 //reading98
99 Serial.println(switchVar1, BIN);100
101 Serial.println(switchVar2, BIN);102
103 //This for-loop steps through the byte104
105 //bit by bit which holds the shift register data106
107 //and if it was high (1) then it prints108
109 //the corresponding location in the array110
111 for (int n=0; n<=7; n++)112
113 {114
115 //so, when n is 3, it compares the bits116
117 //in switchVar1 and the binary number 00001000118
119 //which will only return true if there is a120
121 //1 in that bit (ie that pin) from the shift122
123 //register.124
125 if (switchVar1 & (1 << n) ){126
127 //print the value of the array location128
129 Serial.println(note2sing[n]);130
131 }132
133 }134
135 //--- SHIFT REGISTER 2136
137 // This is a more complicated behavior138
139 //If the switch attached to pin 7 is High140
141 if (switchVar2 & (1 << 7) ){142
143 //print"Check, Check" to let us know the settings are being updated"144
145 Serial.println("Check, Check");146
147 //set a flag variable to let the program know the settings are being updated148
149 settingSwitch = 1;150
151 }152
153 //if the switch is low154
155 else {156
157 //and if it was high the very last time it came through158
159 //this if statement (indicated by the settingSwitch variable still160
161 //set to "1")162
163 if (settingSwitch) {164
165 //turn off the settingSwitch variable166
167 settingSwitch=0;168
169 //just print which settings are ON170
171 if (getBit(switchVar2, MuteBit)) {172
173 Serial.print("Mute On ");174
175 }176
177 if (getBit(switchVar2, OctShftBit)) {178
179 Serial.println("Octave Shift On ");180
181 }182
183 if (getBit(switchVar2, DelayBit)) {184
185 Serial.println("Delay On ");186
187 }188
189 if (getBit(switchVar2, ReverbBit)) {190
191 Serial.println("Reverb On ");192
193 }194
195 if (getBit(switchVar2, VibratoBit)) {196
197 Serial.println("Vibrato On ");198
199 }200
201 if (getBit(switchVar2, FunkifyBit)) {202
203 Serial.println("Funkified ");204
205 }206
207 if (getBit(switchVar2, DampenBit)) {208
209 Serial.println("Note Dampened ");210
211 }212
213 }214
215 }216
217 //white space218
219 Serial.println("-------------------");220
221 //delay so all these print statements can keep up.222
223 delay(500);224
225}226
227//------------------------------------------------end main loop228
229////// ----------------------------------------shiftIn function230///// just needs the location of the data pin and the clock pin231///// it returns a byte with each bit in the byte corresponding232///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0233byte shiftIn(int myDataPin, int myClockPin) {234
235 int i;236
237 int temp = 0;238
239 int pinState;240
241 byte myDataIn = 0;242
243 pinMode(myClockPin, OUTPUT);244
245 pinMode(myDataPin, INPUT);246
247 //we will be holding the clock pin high 8 times (0,..,7) at the248
249 //end of each time through the for loop250
251 //at the beginning of each loop when we set the clock low, it will252
253 //be doing the necessary low to high drop to cause the shift254
255 //register's DataPin to change state based on the value256
257 //of the next bit in its serial information flow.258
259 //The register transmits the information about the pins from pin 7 to pin 0260
261 //so that is why our function counts down262
263 for (i=7; i>=0; i--)264
265 {266
267 digitalWrite(myClockPin, 0);268
269 delayMicroseconds(2);270
271 temp = digitalRead(myDataPin);272
273 if (temp) {274
275 pinState = 1;276
277 //set the bit to 0 no matter what278
279 myDataIn = myDataIn | (1 << i);280
281 }282
283 else {284
285 //turn it off -- only necessary for debugging286
287 //print statement since myDataIn starts as 0288
289 pinState = 0;290
291 }292
293 //Debugging print statements294
295 //Serial.print(pinState);296
297 //Serial.print(" ");298
299 //Serial.println (dataIn, BIN);300
301 digitalWrite(myClockPin, 1);302
303 }304
305 //debugging print statements whitespace306
307 //Serial.println();308
309 //Serial.println(myDataIn, BIN);310
311 return myDataIn;312}313
314////// ----------------------------------------getBit315boolean getBit(byte myVarIn, byte whatBit) {316
317 boolean bitState;318
319 bitState = myVarIn & (1 << whatBit);320
321 return bitState;322}323
324////// A little extra function...325////// ----------------------------------------setBit326byte setBit(byte myVarIn, byte whatBit, boolean s) {327
328 boolean bitState;329
330 if (s) {331
332 myVarIn = myVarIn | (1 << whatBit);333
334 }335
336 else {337
338 myVarIn = myVarIn & ~(1 << whatBit);339
340 }341
342 return myVarIn;343}
Suggest changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.