Note
Hello, welcome to the SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts Community on Facebook! Dive deeper into Raspberry Pi, Arduino, and ESP32 with fellow enthusiasts.
Why Join?
Expert Support: Solve post-sale issues and technical challenges with help from our community and team.
Learn & Share: Exchange tips and tutorials to enhance your skills.
Exclusive Previews: Get early access to new product announcements and sneak peeks.
Special Discounts: Enjoy exclusive discounts on our newest products.
Festive Promotions and Giveaways: Take part in giveaways and holiday promotions.
👉 Ready to explore and create with us? Click [here] and join today!
28. Show Number with 74hc595¶
In the previous lesson, you may have noticed that the 74HC595 and the 7-segment display make a perfect pair. The 74HC595 can simultaneously output 8-bit signals, while the 7-segment display is controlled by 8 electrical signals (including the decimal point LED segment, i.e., the dp segment).
So, can the 74HC595 be used to control the 7-segment display? The answer is yes.
In this lesson, we will use the 74HC595 to control the 7-segment display and make it show different numbers.
In this lesson, you will able to:
Understand how to use the 74HC595 shift register to drive a 7-segment display.
Learn the binary representations of digits 0 to 9 and how to convert them to decimal and hexadecimal formats.
Understand how to use the Serial Monitor to input data and display it on the 7-segment display.
Building the Circuit¶
Components Needed
1 * Arduino Uno R3 |
1 * 7-segment Display |
1 * 220Ω Resistor |
1 * 74HC595 |
1 * Breadboard |
Jumper Wires |
1 * USB Cable |
|
Building Step-by-Step
Follow the wiring diagram, or the steps below to build your circuit.
Insert the 7-segment display into the breadboard with the decimal point at the bottom right corner.
Connect the negative (-) terminal of the 7-segment display to the ground rail of the breadboard using a jumper wire.
Locate the 74HC595 chip and insert it into the breadboard. Ensure that the chip spans the middle gap.
Connect the VCC and MR pins of the 74HC595 to the positive rail on the breadboard.
Connect the CE and GND pins of the 74HC595 to the negative rail on the breadboard.
Connect Q0 of the 74HC595 to the ‘a’ pin of the 7-segment display, Q1 to the ‘b’ pin, Q2 to the ‘c’ pin, Q3 to the ‘d’ pin, and Q4 to the ‘e’ pin.
Connect Q5 of the 74HC595 to the ‘f’ pin of the 7-segment display, Q6 to the ‘g’ pin, and Q7 to the ‘dp’ pin.
Connect the DS pin of the 74HC595 to pin 11 of the Arduino Uno R3.
Connect the ST_CP pin of the 74HC595 to pin 12 of the Arduino Uno R3.
Connect the SH_CP pin of the 74HC595 to pin 8 of the Arduino Uno R3.
Finally, connect the GND and 5V pins of the Arduino Uno R3 to the negative and positive rails on the breadboard, respectively.
The following tables shows the pin connections between the 74HC595, the Arduino Uno R3, the 7-segment Display.
74HC595 |
Arduino UNO R3 |
---|---|
VCC |
5V |
DS |
11 |
CE |
GND |
ST_CP |
12 |
SH_CP |
8 |
MR |
5V |
GND |
GND |
74HC595 |
7-segment Display |
---|---|
Q0 |
a |
Q1 |
b |
Q2 |
c |
Q3 |
d |
Q4 |
e |
Q5 |
f |
Q6 |
g |
Q7 |
dp |
Binary Numbers for Digits 0 to 9¶
In this project, we use the 74HC595 shift register to drive the 7-segment display to show different numbers. However, the 74HC595 receives binary numbers, so before programming, we need to know the corresponding binary numbers for digits 0 to 9.
Assuming we want to display a digit 2 on the 7-segment display, we need to turn off segments f and c and turn on the remaining segments.
According to the wiring diagram, the output pins Q0 to Q7 of the 74HC595 correspond to the respective pins of the 7-segment display, as shown in the diagram. In binary, 0 represents off (closed), and 1 represents on (open). To display the digit 2, dp, f, and c should be 0, while the other segments should be 1, resulting in the binary number B01011011
.
Note
When you only have one 7-segment display, the DP pin is always set to 0. When you have multiple 7-segment displays in a daisy-chain configuration, you can use the DP pin to indicate the decimal point.
To display the digit 0, dp and g should be 0, and all other segments should be 1, giving the binary number B00111111
.
Question
Now that we know the binary representations for digits 0 and 2, please fill in the binary numbers for the remaining digits in the table below.
Number |
Binary |
---|---|
0 |
B00111111 |
1 |
|
2 |
B01011011 |
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
Code Creation - Displaying Numbers¶
Open the sketch you saved earlier,
Lesson28_Flowing_Light
. Hit “Save As…” from the “File” menu, and rename it toLesson28_Show_Number_Binary
. Click “Save”.Change the
datArray[]
to display the binary numbers corresponding to digits 0 to 9.
const int STcp = 12; //Pin connected to ST_CP of 74HC595
const int SHcp = 8; //Pin connected to SH_CP of 74HC595
const int DS = 11; //Pin connected to DS of 74HC595
//display 0,1,2,3,4,5,6,7,8,9
int datArray[] = { B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00000111, B01111111, B01101111 };
Since the
datArray[]
array contains 10 elements, modify the range of the variablenum
tonum <= 9
.
void loop() {
for (int num = 0; num <= 9; num++) {
digitalWrite(STcp, LOW); // Ground ST_CP and hold low while transmitting
shiftOut(DS, SHcp, MSBFIRST, datArray[num]); // Shift out the data, MSB first
digitalWrite(STcp, HIGH); // Pull ST_CP high to save the data
delay(1000); // Wait for a second
}
}
Your complete code should look like the following. At this point, you can upload the code to the Arduino Uno R3, and you’ll see the 7-segment display scrolling through digits 0 to 9.
const int STcp = 12; //Pin connected to ST_CP of 74HC595
const int SHcp = 8; //Pin connected to SH_CP of 74HC595
const int DS = 11; //Pin connected to DS of 74HC595
//display 0,1,2,3,4,5,6,7,8,9
int datArray[] = { B00111111, B00000110, B01011011, B01001111, B01100110, B01101101, B01111101, B00000111, B01111111, B01101111 };
void setup() {
//set pins to output
pinMode(STcp, OUTPUT);
pinMode(SHcp, OUTPUT);
pinMode(DS, OUTPUT);
}
void loop() {
for (int num = 0; num <= 9; num++) {
digitalWrite(STcp, LOW); // Ground ST_CP and hold low while transmitting
shiftOut(DS, SHcp, MSBFIRST, datArray[num]); // Shift out the data, MSB first
digitalWrite(STcp, HIGH); // Pull ST_CP high to save the data
delay(1000); // Wait for a second
}
}
Binary Conversion¶
In practical applications, writing binary numbers can more clearly express the state of each bit in the data. However, for general numerical representation, writing decimal numbers is more convenient.
Note
Writing binary, decimal, or even hexadecimal numbers does not affect the program’s result but only the code’s readability. For example, writing the decimal number 91
will be internally converted to binary form B01011011
.
Let’s see how to convert binary numbers to decimal.
Conversion to Decimal
In the binary system, each bit represents a corresponding place value. The place value is a power of 2, such as 2^0, 2^1, 2^2…, etc. By multiplying each bit by its corresponding place value and adding all the results together, we get the decimal number.
For example, the binary number B01011011
converts to the decimal number 91.
Using a Calculator
In practical applications, you can use the calculator on your computer. Switch to Programmer mode, and you can easily convert between binary, decimal, and hexadecimal.
Search for “Calculator” on your computer, then switch to Programmer mode.
If you already know the binary number and want to convert it to another base, select BIN.
Now, you can start entering the binary number.
The effective bits in binary refer to the range from the most significant bit (leftmost non-zero bit) to the least significant bit (rightmost non-zero bit).
So for the binary number
B00111111
, the effective bits are111111
.Now, enter
111111
into the calculator to get the corresponding decimal and hexadecimal numbers.
Question
Please convert the binary numbers representing digits 0 to 9 into decimal and hexadecimal numbers using a calculator, and fill in the table. This will give you a quick reference guide for base conversions.
Number |
Binary |
Decimal |
Hexadecimal |
---|---|---|---|
0 |
B00111111 |
63 |
0x3F |
1 |
B00000110 |
||
2 |
B01011011 |
||
3 |
B01001111 |
||
4 |
B01100110 |
||
5 |
B01101101 |
||
6 |
B01111101 |
||
7 |
B00000111 |
||
8 |
B01111111 |
||
9 |
B01101111 |
Modify the Sketch
Now, open your Lesson28_Show_Number_Binary
sketch in the Arduino IDE. Click “File” -> “Save As…”, name the file Lesson28_Show_Number_Decimal
. Click “Save”.
Change all the elements of datArray[]
to decimal, as shown in the code. Once modified, you can upload the code to the Arduino Uno R3 to see the effect.
const int STcp = 12; //Pin connected to ST_CP of 74HC595
const int SHcp = 8; //Pin connected to SH_CP of 74HC595
const int DS = 11; //Pin connected to DS of 74HC595
//display 0,1,2,3,4,5,6,7,8,9
int datArray[] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111 };
void setup() {
//set pins to output
pinMode(STcp, OUTPUT);
pinMode(SHcp, OUTPUT);
pinMode(DS, OUTPUT);
}
void loop() {
for (int num = 0; num <= 9; num++) {
digitalWrite(STcp, LOW); // Ground ST_CP and hold low while transmitting
shiftOut(DS, SHcp, MSBFIRST, datArray[num]); // Shift out the data, MSB first
digitalWrite(STcp, HIGH); // Pull ST_CP high to save the data
delay(1000); // Wait for a second
}
}
Code Creation - Serial Input¶
The Serial Monitor is a powerful tool provided by the Arduino IDE for communication with the Arduino board. We have used it to monitor data output from the Arduino, such as reading analog values from a photoresistor. It can also be used to send data to the Arduino, allowing it to perform actions based on received data.
In this activity, we will write a number between 0 and 9 into the Serial Monitor to display it on the 7-segment display.
Open your
Lesson28_Show_Number_Decimal
sketch in the Arduino IDE. Click “File” -> “Save As…”, name the fileLesson28_Show_Number_Serial
. Click “Save”.In
void setup()
, start the serial monitor and set its baud rate to 9600.
void setup() {
//set pins to output
pinMode(STcp, OUTPUT);
pinMode(SHcp, OUTPUT);
pinMode(DS, OUTPUT);
Serial.begin(9600); // Serial communication setup at 9600 baud
}
When using the Serial Monitor, you can read data entered into it through Arduino code. Here, you need to understand two functions:
Serial.available()
: Get the number of bytes (characters) available for reading from the serial port. This is data that’s already arrived and stored in the serial receive buffer (which holds 64 bytes).Serial.read()
: Returns the ASCII code of the character received via the serial input.
Now, use an if
statement in void loop()
to check if data has been read from the port, then print it.
Note
Temporarily comment out the for statement in void loop()
that displays characters on the 7-segment display to avoid affecting the printing process.
void loop() {
if (Serial.available() > 0) {
//Print the character received from the serial port
Serial.println(Serial.read());
}
// for (int num = 0; num <= 9; num++) {
// digitalWrite(STcp, LOW); // Ground ST_CP and hold low while transmitting
// shiftOut(DS, SHcp, MSBFIRST, datArray[num]); // Shift out the data, MSB first
// digitalWrite(STcp, HIGH); // Pull ST_CP high to save the data
// delay(1000); // Wait for a second
// }
}
Your complete code is shown below. At this point, you can upload the code to the Arduino Uno R3.
const int STcp = 12; //Pin connected to ST_CP of 74HC595
const int SHcp = 8; //Pin connected to SH_CP of 74HC595
const int DS = 11; //Pin connected to DS of 74HC595
//display 0,1,2,3,4,5,6,7,8,9
int datArray[] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111 };
void setup() {
//set pins to output
pinMode(STcp, OUTPUT);
pinMode(SHcp, OUTPUT);
pinMode(DS, OUTPUT);
Serial.begin(9600); // Serial communication setup at 9600 baud
}
void loop() {
if (Serial.available() > 0) {
//Print the character received from the serial port
Serial.println(Serial.read());
}
// for (int num = 0; num <= 9; num++) {
// digitalWrite(STcp, LOW); // Ground ST_CP and hold low while transmitting
// shiftOut(DS, SHcp, MSBFIRST, datArray[num]); // Shift out the data, MSB first
// digitalWrite(STcp, HIGH); // Pull ST_CP high to save the data
// delay(1000); // Wait for a second
// }
}
After uploading, open the Serial Monitor. In the input box, enter the number
0
(or any digit between 0-9) and press enter. At this moment, you will find that the Serial outputs a number48
.
Note
If “Newline” is selected in the line ending option of the serial monitor, you can also see a
10
.10
is the ASCII code for a newline character (also called LF - Line Feed).
So, where did our input of 0
go? Where did that 48
come from? Is it possible that 0
is 48
?
This is because the 0
we input in the Serial Monitor is considered a “character,” not a “number.”
The character transfer follows a coding standard known as ASCII (American Standard Code for Information Interchange).
ASCII includes common characters like uppercase letters (A-Z), lowercase letters (a-z), digits (0-9), and punctuation marks (such as periods, commas, exclamation marks, etc.). It also defines some control characters used to control devices and communication protocols. These control characters typically do not display on the screen but are used to control the behavior of devices like printers, terminals, etc., such as line feed, backspace, carriage return, etc.
Here is an ASCII table:
When you type the character 0
in the Serial Monitor, the ASCII code for the character 0
is sent to the Arduino.
In ASCII, the code for the character 0
is 48
in decimal.
Before you continue coding, you need to comment out the previous code that prints the ASCII code to avoid conflicts with the following code.
void loop() {
if (Serial.available() > 0) {
// Print the character received from the serial port
// Serial.println(Serial.read());
}
// for (int num = 0; num <= 9; num++) {
// digitalWrite(STcp, LOW); // Ground ST_CP and hold low while transmitting
// shiftOut(DS, SHcp, MSBFIRST, datArray[num]); // Shift out the data, MSB first
// digitalWrite(STcp, HIGH); // Pull ST_CP high to save the data
// delay(1000); // Wait for a second
// }
}
You need to create a new
char
variable to store the character read from the Serial Monitor.
void loop() {
if (Serial.available() > 0) {
// Print the character received from the serial port
// Serial.println(Serial.read());
// Read the character received from the serial port
char receivedChar = Serial.read();
}
}
Now, convert the character to a number. In ASCII, the value for the character
'0'
is48
,'1'
is49
, and so on. Therefore, by subtracting the ASCII code for'0'
, we can get the corresponding numeric value.
void loop() {
if (Serial.available() > 0) {
//Print the character received from the serial port
Serial.println(Serial.read());
// Read the character received from the serial port
char receivedChar = Serial.read();
// Convert the character to a digit
int digit = receivedChar - '0';
}
}
In this example, we assume the input is numeric characters
'0'
to'9'
. Therefore, we only care if the input character is within this range. Hence, you need to check if the number is within the valid range:
Select the previously commented-out
for
loop statement and pressCtrl + /
to uncomment it.Then modify the
for
statement to anif
statement to check if the input character is within the range of'0'
to'9'
. If it is, let the 7-segment display show the corresponding number.
void loop() {
if (Serial.available() > 0) {
// Print the character received from the serial port
// Serial.println(Serial.read());
// Read the character received from the serial port
char receivedChar = Serial.read();
// Convert the character to a digit
int digit = receivedChar - '0';
if (digit >= 0 && digit <= 9) {
digitalWrite(STcp, LOW); // Ground ST_CP and hold low while transmitting
shiftOut(DS, SHcp, MSBFIRST, datArray[digit]); // Shift out the data, MSB first
digitalWrite(STcp, HIGH); // Pull ST_CP high to save the data
delay(1000); // Wait for a second
}
}
}
Your complete code should be as follows. You can now upload the code to the Arduino Uno R3 and open the Serial Monitor. Enter any number between 0 and 9 to see if the 7-segment display shows the corresponding number.
const int STcp = 12; //Pin connected to ST_CP of 74HC595
const int SHcp = 8; //Pin connected to SH_CP of 74HC595
const int DS = 11; //Pin connected to DS of 74HC595
//display 0,1,2,3,4,5,6,7,8,9
int datArray[] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111 };
void setup() {
//set pins to output
pinMode(STcp, OUTPUT);
pinMode(SHcp, OUTPUT);
pinMode(DS, OUTPUT);
Serial.begin(9600); // Serial communication setup at 9600 baud
}
void loop() {
if (Serial.available() > 0) {
// Print the character received from the serial port
// Serial.println(Serial.read());
// Read the character received from the serial port
char receivedChar = Serial.read();
// Convert the character to a digit
int digit = receivedChar - '0';
if (digit >= 0 && digit <= 9) {
digitalWrite(STcp, LOW); // Ground ST_CP and hold low while transmitting
shiftOut(DS, SHcp, MSBFIRST, datArray[digit]); // Shift out the data, MSB first
digitalWrite(STcp, HIGH); // Pull ST_CP high to save the data
delay(1000); // Wait for a second
}
}
}
Finally, remember to save your code and tidy up your workspace.
Summary
In this lesson, you learned how to use the 74HC595 shift register to drive a 7-segment display and reduce the number of pins required on the Arduino Uno R3. You also explored the binary representations for digits to be displayed and understood how to convert binary numbers to decimal and hexadecimal formats, making the code more readable.
Additionally, you learned how to use the Serial Monitor for serial input and how the input characters are internally converted to ASCII codes. By understanding this conversion, you could map characters to their numeric equivalents, enabling accurate display on the 7-segment display.
Overall, this lesson provided a comprehensive understanding of using shift registers, controlling 7-segment displays, and handling serial communication for interactive projects.