こんにちは、あろっちです。
シフトレジスタ(74HC595)を使って7セグメントディスプレイを表示してみます。
マイコンはRaspberry Pi Picoを使います。
本記事はArduinoやMicroPythonの環境設定などは準備済みであることを前提としています。
MicroPython
ファームウェアのインストール手順は以下の記事を参照してください。
Arduino
Raspberry Pi Pico/RP2040ボード(Arduino-Pico)を使用します。
シフトレジスタ(74HC595)とは?
74HC595は、少ないピンで複数の信号を制御できるICです。マイコンからのデータを1ビットずつ送信(シリアル)し、それをまとめて出力(パラレル)することで、7セグメントディスプレイやLEDを効率よく操作できます。
これにより、マイコンの出力ピンを節約しながら、7セグメントディスプレイの各セグメント(8ピン)をまとめて制御できるのが特徴です。今回は7セグメントディスプレイの制御を中心に解説しますが、74HC595はLEDの制御やその他のデジタル出力の拡張にも活用できます。
74HC595の操作手順

1. データ送信 → クロック信号送信
最初に、1ビットのデータをDS(データ入力)ピンに送信し、SH_CPピンにクロック信号を送ります。クロック信号が立ち上がると、そのビットがシフトレジスタに格納されます。この操作を1回目のデータ転送とし、次のビットに進みます。
2. 次のビット送信 → クロック信号送信
2番目のビットを送信し、再度クロック信号を送ります。この操作を繰り返し、計8回の「データ送信 → クロック信号送信」を行い、8ビットすべてがシフトレジスタに格納されます。
3. すべてのビットをセット
8ビットすべてがシフトレジスタに格納された後、ST_CPピンをHIGHにします。これにより、シフトレジスタ内のデータがパラレル出力(Q0〜Q7)に転送され、実際の出力が反映されます。
この操作で、7セグメントディスプレイやLEDなどを制御できます。
準備
使用するもの

配線について
配線図

7セグメントディスプレイの各ピンと74HC595の間は330Ωの抵抗を入れています。抵抗は220Ωでもよいと思います。(ご使用の7セグメントディスプレイのデータシートをご確認ください。)
5161BSの場合、データシートによると、Vfは1.8V、IF(max)は30mAです。この場合、オームの法則から50Ω以上の抵抗を入れればよいことになります。
$$ R = \frac{V_{\text{cc}} – V_f}{I} $$
$$ R = \frac{3.3V – 1.8V}{0.03A} = \frac{1.5V}{0.03A} = 50Ω $$
配線の対応表
74HC595 | 7セグ | Raspberry Pi Pico |
---|---|---|
Q0 | a | |
Q1 | b | |
Q2 | c | |
Q3 | d | |
Q4 | e | |
Q5 | f | |
Q6 | g | |
Q7 | dp (decimal point…小数点) | |
com (VCC) | 3.3V | |
VCC | 3.3V | |
GND | GND | |
OE (Output Enable) (LOWで有効) | GND | |
MR (クリア) (LOWでクリア HIGHでクリアを無効) | 3.3V | |
DS | 28 | |
ST_CP (ラッチ) | 27 | |
SH_CP (クロック) | 26 |
グリフコード (0から9までの数字の表示パターン)
最下位ビット (LSB) が a、最上位ビット (MSB) が dp
並び順: dp, g, f, e, d, c, b, a
表示対象のビットが1
数字 | バイナリーコード | ヘックスコード |
---|---|---|
0 | 00111111 | 0x3f |
1 | 00000110 | 0x06 |
2 | 01011011 | 0x5b |
3 | 01001111 | 0x4f |
4 | 01100110 | 0x66 |
5 | 01101101 | 0x6d |
6 | 01111101 | 0x7d |
7 | 00000111 | 0x07 |
8 | 01111111 | 0x7f |
9 | 01101111 | 0x6f |
このパターンは、通常カソードコモン型7セグメントディスプレイ(5161ASなど)に対応しています。
今回使用する7セグメントディスプレイはアノードコモン型のため(アノードとカソードが逆)、上記で示したビットを反転してシフトレジスタに書き込みます。
プログラム
7セグに0から9を順番に表示する
0から9を順番に7セグメントディスプレイに表示します。
MicroPython
import machine
import time
# Define the segment code for a common anode 7-segment display
SEGCODE = [0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f]
# Initialize the pins for the 74HC595 shift register
sdi = machine.Pin(28, machine.Pin.OUT) # DS
rclk = machine.Pin(27, machine.Pin.OUT) # STcp
srclk = machine.Pin(26, machine.Pin.OUT) # SHcp
# Define the hc595_shift function to shift data into the 74HC595 shift register
def hc595_shift(dat):
# Set the RCLK pin to low
rclk.off()
# Iterate through each bit (from 7 to 0)
for bit in range(7, -1, -1):
# Extract the current bit from the input data
value = 1 & (dat >> bit)
# Set the SRCLK pin to low
srclk.off()
# Set the value of the SDI pin
sdi.value(value)
# Clock the current bit into the shift register by setting the SRCLK pin to high
srclk.on()
# Latch the data into the storage register by setting the RCLK pin to high
rclk.on()
# Continuously loop through the numbers 0 to 9 and display them on the 7-segment display
while True:
for num in range(10):
# 7セグがアノードコモンの場合、SEGCODEをビット反転する
hc595_shift(~SEGCODE[num]) # Shift the segment code for the current number into the 74HC595
# 7セグがカソードコモンの場合はSEGCODEをそのまま渡す
# hc595_shift(SEGCODE[num]) # Shift the segment code for the current number into the 74HC595
time.sleep_ms(500) # Wait 500 milliseconds before displaying the next number
SEGCODEに0から9の表示パターンを16進数で定義しています。
hc595_shift関数は、シフトレジスタに表示パターンを書き込む関数です。
書き込む際に、SEGCODEのパターンに対してnotをとることでビット列を反転しています。この処理によりアノードコモン型の7セグメントディスプレイで正しく数字が表示されるようにしています。
カソードコモン型の7セグメントディスプレイを使用する場合は、SEGCODEのパターンをhc595_shift関数にそのまま渡せばOKです。(コメントアウトされているhc595_shiftのロジックを適用すれば動作します。)
Arduino
const int STcp = 27; //ST_CP
const int SHcp = 26; //SH_CP
const int DS = 28; //DS
int datArray[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };
void setup() {
//set pins to output
pinMode(STcp, OUTPUT);
pinMode(SHcp, OUTPUT);
pinMode(DS, OUTPUT);
}
void loop() {
for (int num = 0; num < 10; num++) {
digitalWrite(STcp, LOW); //ground ST_CP and hold low for as long as you are transmitting
// shiftOut(DS, SHcp, MSBFIRST, datArray[num]);
// 7セグがアノードコモンの場合はビットを反転する
shiftOut(DS, SHcp, MSBFIRST, ~datArray[num]);
digitalWrite(STcp, HIGH); //pull the ST_CPST_CP to save the data
delay(500);
}
}
dataArrayに0から9の表示パターンを16進数で定義しています。
shiftOut関数を使って、シフトレジスタに表示パターンのビット列を書き込みます。
書き込む際に、dataArrayのパターンに対してnotをとることでビット列を反転させています。この処理によりアノードコモン型の7セグメントディスプレイで正しく数字が表示されるようにしています。
カソードコモン型の7セグメントディスプレイを使用する場合は、dataArrayのパターンをそのまま書き込めばOKです。(コメントアウトされているshiftOutのロジックを適用すれば動作します。)
数字(0から9)の表示にアニメーションを加える
応用編として、上記のプログラムにアニメーションを加えてみました。
MicroPython
import machine
import time
# Define the segment code for a common anode 7-segment display
SEGCODE = [0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F]
ANIMEPATTERN = [0x5F, 0x1E, 0x5C, 0x58, 0x50, 0x70, 0x21, 0x23]
# Initialize the pins for the 74HC595 shift register
sdi = machine.Pin(28, machine.Pin.OUT) # DS
rclk = machine.Pin(27, machine.Pin.OUT) # STcp
srclk = machine.Pin(26, machine.Pin.OUT) # SHcp
# Define the hc595_shift function to shift data into the 74HC595 shift register
def hc595_shift(dat):
# Set the RCLK pin to low
rclk.off()
# Iterate through each bit (from 7 to 0)
for bit in range(7, -1, -1):
# Extract the current bit from the input data
value = 1 & (dat >> bit)
# Set the SRCLK pin to low
srclk.off()
# Set the value of the SDI pin
sdi.value(value)
# Clock the current bit into the shift register by setting the SRCLK pin to high
srclk.on()
# Latch the data into the storage register by setting the RCLK pin to high
rclk.on()
while True:
for segcode in SEGCODE:
for pattern in ANIMEPATTERN:
# 7セグがアノードコモンの場合、SEGCODEをビット反転する
hc595_shift(~pattern)
# 7セグがカソードコモンの場合はそのまま渡す
# hc595_shift(pattern)
time.sleep_ms(50)
hc595_shift(~segcode)
# 7セグがカソードコモンの場合はそのまま渡す
# hc595_shift(segcode)
time.sleep(1)
# 非表示
hc595_shift(~0)
# 7セグがカソードコモンの場合はそのまま渡す
# hc595_shift(0)
time.sleep(3)
数字のパターンを表示する前にアニメーションを表示するループを加えています。
アニメーションの表示パターンはANIMEPATTERN配列で定義しています。
Arduino
const int STcp = 27; //ST_CP
const int SHcp = 26; //SH_CP
const int DS = 28; //DS
// 数字(0から9)のパターン
int datArray[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };
// アニメーションパターン
int animePattern[] = { 0x5F, 0x1E, 0x5C, 0x58, 0x50, 0x70, 0x21, 0x23 };
// 74HC595のST_CPのLOW、HIGH処理(ラッチ)を加えた関数
void hc595_shift(int data) {
digitalWrite(STcp, LOW);
shiftOut(DS, SHcp, MSBFIRST, data);
digitalWrite(STcp, HIGH);
}
void setup() {
//set pins to output
pinMode(STcp, OUTPUT);
pinMode(SHcp, OUTPUT);
pinMode(DS, OUTPUT);
}
void loop() {
for (int num = 0; num < 10; num++) {
for (int i = 0; i < sizeof(animePattern) / sizeof(animePattern[0]); i++) {
// アニメーションのパターンを表示
hc595_shift(~animePattern[i]);
// 7セグがカソードコモンの場合はそのまま渡す
// hc595_shift(animePattern[i]);
delay(50);
}
// 数字のパターンを表示
hc595_shift(~datArray[num]);
// 7セグがカソードコモンの場合はそのまま渡す
// hc595_shift(datArray[i]);
delay(1000);
}
// 非表示
hc595_shift(~0);
// 7セグがカソードコモンの場合はそのまま渡す
// hc595_shift(0);
delay(3000);
}
数字のパターンを表示する前にアニメーションを表示するループを加えています。
アニメーションの表示パターンはanimePattern配列で定義しています。
7セグのaからdpを順番に点灯させて逆順に消灯させる
MicroPython
import machine
import time
# Initialize the pins for the 74HC595 shift register
sdi = machine.Pin(28, machine.Pin.OUT) # DS
rclk = machine.Pin(27, machine.Pin.OUT) # STcp
srclk = machine.Pin(26, machine.Pin.OUT) # SHcp
# Define the hc595_shift function to shift data into the 74HC595 shift register
def hc595_shift(dat):
# Set the RCLK pin to low
rclk.off()
# Iterate through each bit (from 7 to 0)
for bit in range(7, -1, -1):
# Extract the current bit from the input data
value = 1 & (dat >> bit)
# Set the SRCLK pin to low
srclk.off()
# Set the value of the SDI pin
sdi.value(value)
# Clock the current bit into the shift register by setting the SRCLK pin to high
srclk.on()
# Latch the data into the storage register by setting the RCLK pin to high
rclk.on()
ledPattern = 0
hc595_shift(~ledPattern)
time.sleep_ms(500)
while True:
for num in range(16):
if num < 8:
ledPattern = (ledPattern << 1) | 1
else:
ledPattern >>= 1
# 7セグがアノードコモンの場合、ビット反転(not)する
hc595_shift(~ledPattern)
# 7セグがカソードコモンの場合はそのまま渡す
# hc595_shift(ledPattern)
time.sleep_ms(500) # Wait 500 milliseconds before displaying the next number
このプログラムでは、アノードコモン型の7セグメントディスプレイで正しく表示するためのビット反転処理にnot(~ledPattern)を使っています。
Arduino
const int STcp = 27; //ST_CP
const int SHcp = 26; //SH_CP
const int DS = 28; //DS
void setup() {
//set pins to output
pinMode(STcp, OUTPUT);
pinMode(SHcp, OUTPUT);
pinMode(DS, OUTPUT);
// 7セグを非表示にする
digitalWrite(STcp, LOW);
shiftOut(DS, SHcp, MSBFIRST, ~0);
digitalWrite(STcp, HIGH);
delay(500); // 非表示の状態を500ms作る
}
void loop() {
static int i;
uint8_t ledPattern = 0;
// 7セグのaからdpまで順番に点灯させ、反対にdpからaまで順番に消灯させる
for (i = 0; i < 8 * 2; i++) {
if (i < 8) {
ledPattern = (ledPattern << 1) | 1;
} else {
ledPattern >>= 1;
}
digitalWrite(STcp, LOW);
shiftOut(DS, SHcp, MSBFIRST, ~ledPattern);
digitalWrite(STcp, HIGH);
delay(500);
}
}
このプログラムでは、アノードコモン型の7セグメントディスプレイで正しく表示するためのビット反転処理にnot(~ledPattern)を使っています。
ビットシフトの解説
このプログラムのビットシフト処理は以下のようになっています。
• 0~7回目
ledPattern = (ledPattern << 1) | 1 により、右端(Q0)から 1 を入れながら左にシフトする
• 8~15回目
ledPattern >>= 1 により、左端(Q7)から 0 になりながら右にシフトしていく
ビットの遷移
回数 | Q7 (dp) | Q6 (g) | Q5 (f) | Q4 (e) | Q3 (d) | Q2 (c) | Q1 (b) | Q0 (a) |
---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
2 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
3 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
4 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
5 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
6 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
7 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
8 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
9 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
10 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
11 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
12 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
13 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
14 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
【対応関係】
Q7~Q0 → 74HC595の出力ピン
dp, g, f, e, d, c, b, a → 7セグメントディスプレイのセグメント
シフト演算と論理演算をうまく組み合わせることで、7セグ表示用のビットパターンを一つ一つ用意しなくても、簡単に表示できるようになります。これによって、コードがシンプルになり、管理もしやすくなります。
まとめ
今回は、Raspberry Pi Picoとアノードコモン型の7セグメントディスプレイ、シフトレジスタ(74HC595)を使って、0から9の数字を表示しました。
アノードコモン型の7セグメントディスプレイでは、表示パターンのビット列をカソードコモンとは逆にする必要があり、少し考え方のコツが要ります。
「ON/OFFの関係が反転する」 と意識すると分かりやすいかもしれません。
関連記事
当ブログのマイコン記事です。ぜひご覧ください。
コメント