ラズパイとMAX7219でスマートにLチカ!3本の信号線で8個のLEDを自在に操る-プログラム・アドレス制御編-

ハードウェアの準備が整ったら、次はRP2040からMAX7219へ「点灯の指示」を送るプログラムを作成します。

MAX7219を使いこなす鍵は、3本の信号線(DIN, CLK, LOAD/CS)を使って送る16ビットのデータパケットの理解にあります。

前回 配線と回路設計 MAX7219でLチカするまで

MAX7219でLEDを順次制御する方法を紹介した記事のサムネイル

ラズパイとMAX7219でスマートにLチカ!3本の信号線で8個のLEDを自在に操る

マイコンのピン不足を解消するLEDドライバ「MAX7219」を徹底解説!MAX7221との違いやラズパイ(RP2040)での回路設計、ノイズ対策のコツまで紹介します。あえてデコード機能を使わず、アドレス指定でLEDを1つずつ制御する「流れるLチカ」の実践ガイド。マトリクス表示への第一歩に最適です。

1. MAX7219の「共通言語」:16ビットパケットの構造

MAX7219への命令は、常に16ビット(2バイト)を1つの単位として送信します 。この16個のビットには、それぞれ役割が決まっています 22

  • D15~D12:使用しないビット(任意の値でOK) 。
  • D11~D8レジスタアドレス(命令を届ける「住所」) 。
  • D7~D0データ(光らせるパターンなどの「内容」) 。

データは最上位ビット(MSB)であるD15から順番に送るのがルールです 。


2. 制御を始める前の「4つの初期化命令」

MAX7219は、電源を入れた直後は全ての表示が消えた「シャットダウンモード」になっています 。LEDを光らせる前に、まず以下の4つのレジスタに設定値を送る「儀式」が必要です。

設定項目アドレス(HEX)設定値(HEX)理由・効果
シャットダウン解除0x0C0x01デバイスを通常動作モードに移行させます 。
デコードモード0x090x00今回は7セグ数字ではなく、LEDを個別に制御するため「デコードなし」に設定します 。
輝度(明るさ)0x0A0x0316段階で明るさを調整できます。今回はテスト用に低めに設定します 。
スキャン制限0x0B0x00表示する桁数を指定します。今回は「Digit 0」の1桁分(LED8個)だけを使用します 。

3. アドレス直接指定でLEDを操作する

「デコードなしモード」に設定した場合、各桁のレジスタに書き込むデータの各ビットが、接続された8個のLEDと1対1で対応します 。

今回は「Digit 0(アドレス 0x01)」を使用しているため、このレジスタに送るデータの各ビットとLED(セグメントピン)の対応は以下の通りです 。

  • 対応関係(D7〜D0)
    • D7: DP(ドット)
    • D6: SEG A
    • D5: SEG B
    • D4: SEG C
    • D3: SEG D
    • D2: SEG E
    • D1: SEG F
    • D0: SEG G

例えば、Digit 0に接続したLEDのうち「SEG A」と「SEG B」だけを光らせたい場合は、D6とD5を 1 にしたバイナリデータ 0b01100000 をアドレス 0x01 へ送信します。


4. RP2040での実装ロジック

RP2040でプログラムを書く際のポイントは、SPI通信のタイミングとデータの合成です。

データの合成

アドレス(8ビット)とデータ(8ビット)を合体させて、16ビットの数値を作ります。

# 例:アドレス0x01(Digit0)に、データ0xFF(全点灯)を送る場合
spi.write(bytes([0x01, 0xFF]))

LOAD(CS)ピンの制御

MAX7219は、LOAD(またはCS)ピンが立ち上がった瞬間にデータを内部レジスタにラッチ(保持)します 。

  1. 通信開始前に LOADピンをLow にする 。
  2. SPIで 16ビット分 のデータを送り出す。
  3. 送信完了後、 LOADピンをHigh に戻す 。

この手順を守ることで、狙った通りのタイミングでLEDが点灯します。

ウェーブ発光のプログラムサンプル

circuitpytyhon で書き込んだ、spi通信でウェーブ発行させるプログラムの例です。

import board
import busio
import digitalio
import analogio
import time

# --- 1. SPI/CSの初期化 ---
spi = busio.SPI(board.GP2, MOSI=board.GP3)
while not spi.try_lock():
    pass
spi.configure(baudrate=1000000, polarity=0, phase=0)
spi.unlock()

cs = digitalio.DigitalInOut(board.GP4)
cs.direction = digitalio.Direction.OUTPUT
cs.value = True

def write_reg(reg, data):
    while not spi.try_lock():
        pass
    try:
        cs.value = False
        time.sleep(0.001)
        spi.write(bytes([reg, data]))
        time.sleep(0.001)
        cs.value = True
        time.sleep(0.001)
    finally:
        spi.unlock()

# --- 2. MAX7219 初期化シーケンス ---
print("Initializing MAX7219...")
write_reg(0x0F, 0x00) # ディスプレイテストOFF
write_reg(0x0C, 0x01) # 通常動作モード
write_reg(0x09, 0x00) # デコードモード: 無効
write_reg(0x0B, 0x00) # スキャンリミット: Digit 0 のみ
write_reg(0x0A, 0x03) # 輝度設定 (0x00 - 0x0F)

# 一旦すべて消灯 (Digit 0)
write_reg(0x01, 0x00)

print("Starting Sequential Lighting (A to G)...")

# 点灯させたいセグメントのリスト (A, B, C, D, E, F, G)
segments = [
    0x01, # A
    0x02, # B
    0x04, # C
    0x08, # D
    0x10, # E
    0x20, # F
    0x40,  # G
    0x80  # DP
]

# --- 3. メインループ ---
try:
    while True:
        for seg_data in segments:
            # 指定したセグメントのみを点灯
            write_reg(0x01, seg_data)
            
            time.sleep(0.3) # 0.3秒間隔で切り替え

except KeyboardInterrupt:
    # 終了時に消灯
    write_reg(0x01, 0x00)
    write_reg(0x0C, 0x00)
    print("Program stopped.")

まとめ:これで自由自在!

一度初期設定を済ませてしまえば、あとはループ処理の中で「Digit 0」レジスタに送るビットをずらしていくだけで、小気味よく流れるLチカが実現できます。

2列以上の操作をしたいときは、spi.write(bytes([0x01, 0xFF]))のアドレス を変更すればよく、2列めは0x02、3列目は0X03、8列目は0x08とすることで列を指定できます。

# 2行3列目(7SEGなら2桁目の3つ目のセグメント)を光らせたいとき
write_reg(0x02, 0x04)

# 5行8列目の場合
write_reg(0x05, 0x80)

# 5行目の3から8番目全部点灯させたいとき
# data 0b11111100 -> 0xfc
write_reg(0x05, 0xfc)

アドレス直接指定の仕組みを理解すると、マトリクスLEDを使った複雑なアニメーションや、独自のアイコン表示など、活用の幅がぐっと広がります。ぜひ、色々な点灯パターンを試してみてください!

MAX7219でLEDを順次制御する方法を紹介した記事のサムネイル 2 記事
シリーズ

ラズパイでLED制御(max7219)

マトリクスLEDや複数行の7セグのLED制御が出来るチップMAX7219をラズパイを用いたSPI通信で制御します。

ここまで読んでいただきありがとうございます。

では、次の記事で。 lumenHero