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:

  1. Make sure the register has the latest information from its parallel inputs (i.e. that the latch pin is HIGH)

  2. Tell the register the Arduino is ready to get the information serially (latch pin LOW)

  3. 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 Arduino
6switch -> | 0 |
7switch -> | 2 |
8switch -> | 1 | <- Clock Data from Arduino
9switch -> |_____| <- 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 shftin cd4021 pins 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

ShftInExmp1 1

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.

ShftInExmp1 2

3. Add 8 Switches

ShftInExmp1 3

Diagram

ShftInExmp1 Schem

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 Arduino
6switch -> | 0 |
7switch -> | 2 | <- Clock Data from Arduino
8switch -> | 1 | <- Latch Data from Arduino
9switch -> |_____| <------
10|
11|
12|
13_______ | Serial Data Passed to First
14switch -> | | | Shift Register
15switch -> | C | |
16switch -> | D | |
17switch -> | 4 | ______|
18switch -> | 0 |
19switch -> | 2 | <- Clock Data from Arduino
20switch -> | 1 | <- Latch Data from Arduino
21switch -> |_____|

The Circuit

1. Add a second shift register.

ShftInExmp2 1

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.

ShftInExmp2 2

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.

ShftInExmp2 3

Diagram

ShftInExmp2 Schem

The Code

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 are
11int latchPin = 8;
12int dataPin = 9;
13int clockPin = 7;
14
15//Define variables to hold the data
16//for shift register.
17//starting with a non-zero numbers can help
18//troubleshoot
19byte switchVar1 = 72; //01001000
20
21void setup() {
22
23 //start serial
24
25 Serial.begin(9600);
26
27 //define pin modes
28
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 data
42
43 digitalWrite(latchPin,1);
44
45 //set it to 1 to collect parallel data, wait
46
47 delayMicroseconds(20);
48
49 //set it to 0 to transmit data serially
50
51 digitalWrite(latchPin,0);
52
53 //while the shift register is in serial mode
54
55 //collect each shift register into a byte
56
57 //the register attached to the chip comes in first
58
59 switchVar1 = shiftIn(dataPin, clockPin);
60
61 //Print out the results.
62
63 //leading 0's at the top of the byte
64
65 //(7, 6, 5, etc) will be dropped before
66
67 //the first pin that has a high input
68
69 //reading
70
71 Serial.println(switchVar1, BIN);
72
73//white space
74Serial.println("-------------------");
75//delay so all these print statements can keep up.
76delay(500);
77
78}
79
80//------------------------------------------------end main loop
81
82////// ----------------------------------------shiftIn function
83///// just needs the location of the data pin and the clock pin
84///// it returns a byte with each bit in the byte corresponding
85///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
86
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 the
101//end of each time through the for loop
102
103//at the beginning of each loop when we set the clock low, it will
104//be doing the necessary low to high drop to cause the shift
105//register's DataPin to change state based on the value
106//of the next bit in its serial information flow.
107//The register transmits the information about the pins from pin 7 to pin 0
108//so that is why our function counts down
109
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 what
125
126 myDataIn = myDataIn | (1 << i);
127
128 }
129
130 else {
131
132 //turn it off -- only necessary for debugging
133
134 //print statement since myDataIn starts as 0
135
136 pinState = 0;
137
138 }
139
140 //Debugging print statements
141
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 whitespace
153
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 are
11int latchPin = 8;
12int dataPin = 9;
13int clockPin = 7;
14
15//Define variables to hold the data
16//for shift register.
17//starting with a non-zero numbers can help
18//troubleshoot
19byte switchVar1 = 72; //01001000
20
21//define an array that corresponds to values for each
22//of the shift register's pins
23char note2sing[] = {
24
25 'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};
26
27void setup() {
28
29 //start serial
30
31 Serial.begin(9600);
32
33 //define pin modes
34
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 data
48
49 digitalWrite(latchPin,1);
50
51 //set it to 1 to collect parallel data, wait
52
53 delayMicroseconds(20);
54
55 //set it to 0 to transmit data serially
56
57 digitalWrite(latchPin,0);
58
59 //while the shift register is in serial mode
60
61 //collect each shift register into a byte
62
63 //the register attached to the chip comes in first
64
65 switchVar1 = shiftIn(dataPin, clockPin);
66
67 //Print out the results.
68
69 //leading 0's at the top of the byte
70
71 //(7, 6, 5, etc) will be dropped before
72
73 //the first pin that has a high input
74
75 //reading
76
77 Serial.println(switchVar1, BIN);
78
79 //This for-loop steps through the byte
80
81 //bit by bit which holds the shift register data
82
83 //and if it was high (1) then it prints
84
85 //the corresponding location in the array
86
87 for (int n=0; n<=7; n++)
88
89 {
90
91 //so, when n is 3, it compares the bits
92
93 //in switchVar1 and the binary number 00001000
94
95 //which will only return true if there is a
96
97 //1 in that bit (ie that pin) from the shift
98
99 //register.
100
101 if (switchVar1 & (1 << n) ){
102
103 //print the value of the array location
104
105 Serial.println(note2sing[n]);
106
107 }
108
109 }
110
111//white space
112Serial.println("-------------------");
113//delay so all these print statements can keep up.
114delay(500);
115
116}
117
118//------------------------------------------------end main loop
119
120////// ----------------------------------------shiftIn function
121///// just needs the location of the data pin and the clock pin
122///// it returns a byte with each bit in the byte corresponding
123///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
124
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 the
139//end of each time through the for loop
140
141//at the beginning of each loop when we set the clock low, it will
142//be doing the necessary low to high drop to cause the shift
143//register's DataPin to change state based on the value
144//of the next bit in its serial information flow.
145//The register transmits the information about the pins from pin 7 to pin 0
146//so that is why our function counts down
147
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 what
163
164 myDataIn = myDataIn | (1 << i);
165
166 }
167
168 else {
169
170 //turn it off -- only necessary for debugging
171
172 //print statement since myDataIn starts as 0
173
174 pinState = 0;
175
176 }
177
178 //Debugging print statements
179
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 whitespace
191
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 are
11int latchPin = 8;
12int dataPin = 9;
13int clockPin = 7;
14
15//Define variables to hold the data
16//for shift register.
17//starting with a non-zero numbers can help
18//troubleshoot
19byte switchVar1 = 72; //01001000
20
21//define an array that corresponds to values for each
22//of the shift register's pins
23char note2sing[] = {
24
25 'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};
26
27void setup() {
28
29 //start serial
30
31 Serial.begin(9600);
32
33 //define pin modes
34
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 data
48
49 digitalWrite(latchPin,1);
50
51 //set it to 1 to collect parallel data, wait
52
53 delayMicroseconds(20);
54
55 //set it to 0 to transmit data serially
56
57 digitalWrite(latchPin,0);
58
59 //while the shift register is in serial mode
60
61 //collect each shift register into a byte
62
63 //the register attached to the chip comes in first
64
65 switchVar1 = shiftIn(dataPin, clockPin);
66
67 //Print out the results.
68
69 //leading 0's at the top of the byte
70
71 //(7, 6, 5, etc) will be dropped before
72
73 //the first pin that has a high input
74
75 //reading
76
77 Serial.println(switchVar1, BIN);
78
79 //This for-loop steps through the byte
80
81 //bit by bit which holds the shift register data
82
83 //and if it was high (1) then it prints
84
85 //the corresponding location in the array
86
87 for (int n=0; n<=7; n++)
88
89 {
90
91 //so, when n is 3, it compares the bits
92
93 //in switchVar1 and the binary number 00001000
94
95 //which will only return true if there is a
96
97 //1 in that bit (ie that pin) from the shift
98
99 //register.
100
101 if (switchVar1 & (1 << n) ){
102
103 //print the value of the array location
104
105 Serial.println(note2sing[n]);
106
107 }
108
109 }
110
111//This following is a away to examine the whole
112//byte at once and create combinations
113//of settings.
114
115//By passing the switchVar1 variable to
116//a "switch" statement and comparing it against
117//a set nemerical value (written in binary)
118//you can create special cases
119
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 default
167
168 Serial.println("Play It, Joe");
169
170 }
171
172//white space
173Serial.println("-------------------");
174//delay so all these print statements can keep up.
175delay(500);
176
177}
178
179//------------------------------------------------end main loop
180
181////// ----------------------------------------shiftIn function
182///// just needs the location of the data pin and the clock pin
183///// it returns a byte with each bit in the byte corresponding
184///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
185
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 the
200//end of each time through the for loop
201
202//at the beginning of each loop when we set the clock low, it will
203//be doing the necessary low to high drop to cause the shift
204//register's DataPin to change state based on the value
205//of the next bit in its serial information flow.
206//The register transmits the information about the pins from pin 7 to pin 0
207//so that is why our function counts down
208
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 what
224
225 myDataIn = myDataIn | (1 << i);
226
227 }
228
229 else {
230
231 //turn it off -- only necessary for debugging
232
233 //print statement since myDataIn starts as 0
234
235 pinState = 0;
236
237 }
238
239 //Debugging print statements
240
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 whitespace
252
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 are
11int latchPin = 8;
12int dataPin = 9;
13int clockPin = 7;
14
15//Define variables to hold the data
16//for shift register.
17//starting with a non-zero numbers can help
18//troubleshoot
19byte switchVar1 = 72; //01001000
20
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 serial
35
36 Serial.begin(9600);
37
38 //define pin modes
39
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 data
53
54 digitalWrite(latchPin,1);
55
56 //set it to 1 to collect parallel data, wait
57
58 delayMicroseconds(20);
59
60 //set it to 0 to transmit data serially
61
62 digitalWrite(latchPin,0);
63
64 //while the shift register is in serial mode
65
66 //collect each shift register into a byte
67
68 //the register attached to the chip comes in first
69
70 switchVar1 = shiftIn(dataPin, clockPin);
71
72 //Print out the results.
73
74 //leading 0's at the top of the byte
75
76 //(7, 6, 5, etc) will be dropped before
77
78 //the first pin that has a high input
79
80 //reading
81
82 Serial.println(switchVar1, BIN);
83
84//You can get a bit state through the subfunction
85//written below by either...
86
87//setting a boolean variable
88
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 space
106Serial.println("-------------------");
107//delay so all these print statements can keep up.
108delay(500);
109
110}
111
112//------------------------------------------------end main loop
113
114////// ----------------------------------------shiftIn function
115///// just needs the location of the data pin and the clock pin
116///// it returns a byte with each bit in the byte corresponding
117///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
118
119byte shiftIn(int myDataPin, int myClockPin) {
120
121//internal function setup
122
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 the
136//end of each time through the for loop
137
138//at the beginning of each loop when we set the clock low, it will
139//be doing the necessary low to high drop to cause the shift
140//register's DataPin to change state based on the value
141//of the next bit in its serial information flow.
142//The register transmits the information about the pins from pin 7 to pin 0
143//so that is why our function counts down
144
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 what
160
161 myDataIn = myDataIn | (1 << i);
162
163 }
164
165 else {
166
167 //turn it off -- only necessary for debugging
168
169 //print statement since myDataIn starts as 0
170
171 pinState = 0;
172
173 }
174
175 //Debugging print statements
176
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 whitespace
188
189 //Serial.println();
190
191 //Serial.println(myDataIn, BIN);
192
193 return myDataIn;
194}
195
196////// ----------------------------------------getBit
197boolean 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////// ----------------------------------------setBit
208byte 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 are
11int latchPin = 8;
12int dataPin = 9;
13int clockPin = 7;
14
15//Define variables to hold the data
16//for each shift register.
17//starting with non-zero numbers can help
18//troubleshoot
19byte switchVar1 = 72; //01001000
20byte switchVar2 = 159; //10011111
21
22void setup() {
23
24 //start serial
25
26 Serial.begin(9600);
27
28 //define pin modes
29
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 data
43
44 digitalWrite(latchPin,1);
45
46 //set it to 1 to collect parallel data, wait
47
48 delayMicroseconds(20);
49
50 //set it to 0 to transmit data serially
51
52 digitalWrite(latchPin,0);
53
54 //while the shift register is in serial mode
55
56 //collect each shift register into a byte
57
58 //the register attached to the chip comes in first
59
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 byte
67
68 //(7, 6, 5, etc) will be dropped before
69
70 //the first pin that has a high input
71
72 //reading
73
74 Serial.println(switchVar1, BIN);
75
76 Serial.println(switchVar2, BIN);
77
78//white space
79Serial.println("-------------------");
80//delay so all these print statements can keep up.
81delay(500);
82
83}
84
85//------------------------------------------------end main loop
86
87////// ----------------------------------------shiftIn function
88///// just needs the location of the data pin and the clock pin
89///// it returns a byte with each bit in the byte corresponding
90///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
91
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 the
107//end of each time through the for loop
108
109//at the beginning of each loop when we set the clock low, it will
110//be doing the necessary low to high drop to cause the shift
111//register's DataPin to change state based on the value
112//of the next bit in its serial information flow.
113//The register transmits the information about the pins from pin 7 to pin 0
114//so that is why our function counts down
115
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 what
131
132 myDataIn = myDataIn | (1 << i);
133
134 }
135
136 else {
137
138 //turn it off -- only necessary for debugging
139
140 //print statement since myDataIn starts as 0
141
142 pinState = 0;
143
144 }
145
146 //Debugging print statements
147
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 whitespace
159
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 are
11int latchPin = 8;
12int dataPin = 9;
13int clockPin = 7;
14
15//Define variables to hold the data
16//for each shift register.
17//starting with non-zero numbers can help
18//troubleshoot
19byte switchVar1 = 72; //01001000
20byte switchVar2 = 159; //10011111
21
22//define an array that corresponds to values for each
23//of the first shift register's pins
24char note2sing[] = {
25
26 'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};
27
28//define an array that has a place for the values of
29//pins 1-7 (not 0) of the second shift register's
30//pins. Not 0 because that will be used as a flag value
31byte settingVal[] = {
32
33 0, 0, 0, 0, 0, 0, 0};
34
35//a flag variable used to track whether the program
36//is in a setting update mode or not
37byte settingSwitch = 0;
38
39void setup() {
40
41 //start serial
42
43 Serial.begin(9600);
44
45 //define pin modes
46
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 data
60
61 digitalWrite(latchPin,1);
62
63 //set it to 1 to collect parallel data, wait
64
65 delayMicroseconds(20);
66
67 //set it to 0 to transmit data serially
68
69 digitalWrite(latchPin,0);
70
71 //while the shift register is in serial mode
72
73 //collect each shift register into a byte
74
75 //the register attached to the chip comes in first
76
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 byte
84
85 //(7, 6, 5, etc) will be dropped before
86
87 //the first pin that has a high input
88
89 //reading
90
91 Serial.println(switchVar1, BIN);
92
93 Serial.println(switchVar2, BIN);
94
95 //This for-loop steps through the byte
96
97 //bit by bit which holds the shift register data
98
99 //and if it was high (1) then it prints
100
101 //the corresponding location in the array
102
103 for (int n=0; n<=7; n++)
104
105 {
106
107 //so, when n is 3, it compares the bits
108
109 //in switchVar1 and the binary number 00001000
110
111 //which will only return true if there is a
112
113 //1 in that bit (ie that pin) from the shift
114
115 //register.
116
117 if (switchVar1 & (1 << n) ){
118
119 //print the value of the array location
120
121 Serial.println(note2sing[n]);
122
123 }
124
125 }
126
127//This is a away to examine the whole
128//byte at once and create combinations
129//of settings.
130
131//By passing the switchVar1 variable to
132//a "switch" statement and comparing it against
133//a set nemerical value (written in binary)
134//you can create special cases
135
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 default
183
184 Serial.println("Play It, Joe");
185
186 }
187
188//--- SHIFT REGISTER 2
189// This is a more complicated behavior
190
191//If the switch attached to pin 7 is High
192
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 updated
200
201 settingSwitch = 1;
202
203 //While the switch attached to seven is high,
204
205 //take the bottom 7 bits and load them into
206
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 low
230
231 else {
232
233 //and if it was high the very last time it came through
234
235 //this if statement (indicated by the settingSwitch variable still
236
237 //set to "1")
238
239 if (settingSwitch) {
240
241 //turn off the settingSwitch variable
242
243 settingSwitch=0;
244
245 //Print out the current settings
246
247 Serial.println("___SETTINGS___");
248
249 for (int s=0; s<=6; s++)
250
251 {
252
253 //Print out the setting names
254
255 //this is being done as a case statement because
256
257 //there weren't built in string arrays yet
258
259 //in Arduino as of Feb. 2007
260
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 default
308
309 Serial.println("Not Defined");
310
311 }
312
313 //Print Status
314
315 if (settingVal[s]) {
316
317 Serial.print(" On");
318
319 }
320
321 else {
322
323 Serial.print(" Off") ;
324
325 }
326
327 //white space
328
329 Serial.println();
330
331 }
332
333 }
334
335 }
336
337//white space
338Serial.println("-------------------");
339//delay so all these print statements can keep up.
340delay(500);
341
342}
343
344//------------------------------------------------end main loop
345
346////// ----------------------------------------shiftIn function
347///// just needs the location of the data pin and the clock pin
348///// it returns a byte with each bit in the byte corresponding
349///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
350byte 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 the
364//end of each time through the for loop
365
366//at the beginning of each loop when we set the clock low, it will
367//be doing the necessary low to high drop to cause the shift
368//register's DataPin to change state based on the value
369//of the next bit in its serial information flow.
370//The register transmits the information about the pins from pin 7 to pin 0
371//so that is why our function counts down
372
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 what
388
389 myDataIn = myDataIn | (1 << i);
390
391 }
392
393 else {
394
395 //turn it off -- only necessary for debugging
396
397 //print statement since myDataIn starts as 0
398
399 pinState = 0;
400
401 }
402
403 //Debugging print statements
404
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 whitespace
416
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 are
11int latchPin = 8;
12int dataPin = 9;
13int clockPin = 7;
14
15//Define variables to hold the data
16//for each shift register.
17//starting with non-zero numbers can help
18//troubleshoot
19byte switchVar1 = 72; //01001000
20byte switchVar2 = 159; //10011111
21
22//define an array that corresponds to values for each
23//of the first shift register's pins
24char note2sing[] = {
25
26 'C', 'd', 'e', 'f', 'g', 'a', 'b', 'c'};
27
28//define an array that has a place for the values of
29//pins 1-7 (not 0) of the second shift register's
30//pins. Not 0 because that will be used as a flag value
31byte 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 program
44//is in a setting update mode or not
45byte settingSwitch = 0;
46
47void setup() {
48
49 //start serial
50
51 Serial.begin(9600);
52
53 //define pin modes
54
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 data
68
69 digitalWrite(latchPin,1);
70
71 //set it to 1 to collect parallel data, wait
72
73 delayMicroseconds(20);
74
75 //set it to 0 to transmit data serially
76
77 digitalWrite(latchPin,0);
78
79 //while the shift register is in serial mode
80
81 //collect each shift register into a byte
82
83 //the register attached to the chip comes in first
84
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 byte
92
93 //(7, 6, 5, etc) will be dropped before
94
95 //the first pin that has a high input
96
97 //reading
98
99 Serial.println(switchVar1, BIN);
100
101 Serial.println(switchVar2, BIN);
102
103 //This for-loop steps through the byte
104
105 //bit by bit which holds the shift register data
106
107 //and if it was high (1) then it prints
108
109 //the corresponding location in the array
110
111 for (int n=0; n<=7; n++)
112
113 {
114
115 //so, when n is 3, it compares the bits
116
117 //in switchVar1 and the binary number 00001000
118
119 //which will only return true if there is a
120
121 //1 in that bit (ie that pin) from the shift
122
123 //register.
124
125 if (switchVar1 & (1 << n) ){
126
127 //print the value of the array location
128
129 Serial.println(note2sing[n]);
130
131 }
132
133 }
134
135 //--- SHIFT REGISTER 2
136
137 // This is a more complicated behavior
138
139 //If the switch attached to pin 7 is High
140
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 updated
148
149 settingSwitch = 1;
150
151 }
152
153 //if the switch is low
154
155 else {
156
157 //and if it was high the very last time it came through
158
159 //this if statement (indicated by the settingSwitch variable still
160
161 //set to "1")
162
163 if (settingSwitch) {
164
165 //turn off the settingSwitch variable
166
167 settingSwitch=0;
168
169 //just print which settings are ON
170
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 space
218
219 Serial.println("-------------------");
220
221 //delay so all these print statements can keep up.
222
223 delay(500);
224
225}
226
227//------------------------------------------------end main loop
228
229////// ----------------------------------------shiftIn function
230///// just needs the location of the data pin and the clock pin
231///// it returns a byte with each bit in the byte corresponding
232///// to a pin on the shift register. leftBit 7 = Pin 7 / Bit 0= Pin 0
233byte 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 the
248
249 //end of each time through the for loop
250
251 //at the beginning of each loop when we set the clock low, it will
252
253 //be doing the necessary low to high drop to cause the shift
254
255 //register's DataPin to change state based on the value
256
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 0
260
261 //so that is why our function counts down
262
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 what
278
279 myDataIn = myDataIn | (1 << i);
280
281 }
282
283 else {
284
285 //turn it off -- only necessary for debugging
286
287 //print statement since myDataIn starts as 0
288
289 pinState = 0;
290
291 }
292
293 //Debugging print statements
294
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 whitespace
306
307 //Serial.println();
308
309 //Serial.println(myDataIn, BIN);
310
311 return myDataIn;
312}
313
314////// ----------------------------------------getBit
315boolean 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////// ----------------------------------------setBit
326byte 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}

Suggested changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. You can read more on how to contribute in the contribution policy.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.