Basic Tutorial for Arduino, 入門篇, 顯示器模組

【Arduino入門教學】第21篇:8×8 LED Matrix 點陣屏(16 Pin 裸件接線圖、矩陣掃描原理與多維陣列動畫設計)

前言:什麼是 8×8 LED Matrix 點陣屏?

在 Arduino 專案中,8×8 LED Matrix(點陣屏) 是學習 多維陣列(Multi-dimensional Arrays)動態掃描(Multiplexing) 最經典的顯示元件。

一個 8×8 點陣屏內部包含 64 顆 LED。如果每顆 LED 都需要獨立接線,將會消耗大量的腳位;但透過 列(Row)與行(Column)交叉矩陣結構,只需要 16 支引腳(上排 8 腳、下排 8 腳) 就能控制整組 64 顆 LED 的亮滅!

一、 8×8 LED 點陣屏工作原理與矩陣掃描

8x8 LED 點陣屏內部矩陣網格架構圖,展示 Row 1 至 Row 8 與 Col 1 至 Col 8 的行列交叉 LED 掃描控制原理

1. 矩陣網格(Row & Column)

8×8 點陣屏由 8 條「列線(Row)」與 8 條「行線(Column)」相交而成:

  • 當某個交叉點的 列(Row)給予高電位(HIGH)行(Column)給予低電位(LOW) 時,該位置的 LED 就會被點亮!

2. 視覺暫留與動態掃描(Multiplexing)

因為行列交叉會相互影響,我們無法一次性把不規則的圖形全部點亮。實務上是透過程式進行 「高速逐列掃描」

  • 每次只點亮第 1 列需要的點 熄滅 點亮第 2 列 熄滅 … 直到第 8 列。

  • 只要掃描速度高於每秒 30 次(利用人眼視覺暫留 POV 特性),看起來就像是一個完整的靜止圖案或動畫!

二、 實驗材料與電路接線圖

🛠️ 所需材料清單

  • Arduino Uno R3 開發板 × 1

  • 8×8 LED Matrix 點陣屏(16 Pin 裸件) × 1

  • 實驗麵包板 × 1~2 塊

  • 單芯線 / 杜邦線 × 16 根

🛍️ 準備好你的硬體工具了嗎?

推薦選購:米羅科技 – Arduino 程式學習爆款套件組(包含 8×8 點陣屏、各式基礎與進階電子元件)

🔌 精確引腳對照表 (1088AS 點陣屏 Arduino)

點陣屏腳位 (Pin)Arduino 腳位內部功能對應 (1088AS)腳位性質說明
1D5R5 (Row 5)下排第 1 腳
2D4R7 (Row 7)下排第 2 腳
3D3C2 (Column 2)下排第 3 腳
4D2C3 (Column 3)下排第 4 腳
5A0 (D14)R8 (Row 8)下排第 5 腳
6A1 (D15)C5 (Column 5)下排第 6 腳
7A2 (D16)R6 (Row 6)下排第 7 腳
8A3 (D17)R3 (Row 3)下排第 8 腳
9D13R1 (Row 1)上排右側第 1 腳
10D12C4 (Column 4)上排右側第 2 腳
11D11C6 (Column 6)上排右側第 3 腳
12D10R4 (Row 4)上排右側第 4 腳
13D9C1 (Column 1)上排右側第 5 腳
14D8R2 (Row 2)上排右側第 6 腳
15D7C7 (Column 7)上排右側第 7 腳
16D6C8 (Column 8)上排右側第 8 腳

1088AS 8x8 LED 點陣屏實物引腳圖與 Arduino GPIO、Row/Column 矩陣對照表

 

🛠️ 前置準備:安裝 FrequencyTimer2 程式庫

在本實作中,我們需要透過 FrequencyTimer2 函式庫 來驅動 Arduino 內部的硬體計時器(Timer2),以實現背景自動掃描點陣屏的功能。請先完成以下程式庫安裝步驟:

  1. 下載 FrequencyTimer2 函式庫

  2. 將 FrequencyTimer2 匯入 Arduino IDE

    • 打開 Arduino IDE 整合開發環境。

    • 在上方功能表點選:草稿碼 匯入程式庫 加入 .ZIP 程式庫...

    • 選擇剛下載的 FrequencyTimer2.zip 檔案即可完成安裝。

三、 多維陣列與動態掃描動畫程式實作

在本範例中,我們利用 FrequencyTimer2 函式庫 的硬體定時器中斷(Timer Interrupt)技術,讓 Arduino 在背景自動進行 8×8 點陣屏的高速動態掃描;而主程式 loop() 則專心處理動畫頁面的切換邏輯,實現流暢且無殘影的非阻塞式(Non-blocking)動畫顯示。

1. 完整標準排版程式碼(帶詳細註解)

將以下程式碼下載至Arduino,並觀察運行情況,你會發現通過 Arduino 你完成了一個酷炫廣告動畫跑馬燈。此範例依序顯示字母『H、I』,接著顯示愛心 ♥️符號的位移,最後再顯示一個⬆箭頭符號,並反覆依序的顯示。
#include <FrequencyTimer2.h> 

#define SPACE { \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}  \
}

#define H { \
    {0, 1, 0, 0, 0, 0, 1, 0}, \
    {0, 1, 0, 0, 0, 0, 1, 0}, \
    {0, 1, 0, 0, 0, 0, 1, 0}, \
    {0, 1, 1, 1, 1, 1, 1, 0}, \
    {0, 1, 0, 0, 0, 0, 1, 0}, \
    {0, 1, 0, 0, 0, 0, 1, 0}, \
    {0, 1, 0, 0, 0, 0, 1, 0}, \
    {0, 1, 0, 0, 0, 0, 1, 0}  \
}

#define I  { \
    {0, 1, 1, 1, 1, 1, 1, 0}, \
    {0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 1, 1, 1, 1, 1, 1, 0}  \
}

#define heart1 { \
    {0, 1, 1, 0, 0, 1, 1, 0}, \
    {1, 1, 1, 1, 1, 1, 1, 1}, \
    {1, 1, 1, 1, 1, 1, 1, 1}, \
    {0, 1, 1, 1, 1, 1, 1, 0}, \
    {0, 0, 1, 1, 1, 1, 0, 0}, \
    {0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}  \
}
#define heart2 { \
    {0, 0, 0, 0, 0, 0, 0, 0}, \
    {0, 1, 1, 0, 0, 1, 1, 0}, \
    {1, 1, 1, 1, 1, 1, 1, 1}, \
    {1, 1, 1, 1, 1, 1, 1, 1}, \
    {0, 1, 1, 1, 1, 1, 1, 0}, \
    {0, 0, 1, 1, 1, 1, 0, 0}, \
    {0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 0, 0}  \
}

#define heart3 { \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 1, 1, 0, 0, 1, 1, 0}, \
     {1, 1, 1, 1, 1, 1, 1, 1}, \
     {1, 1, 1, 1, 1, 1, 1, 1}, \ 
     {0, 1, 1, 1, 1, 1, 1, 0}, \
     {0, 0, 1, 1, 1, 1, 0, 0}, \
     {0, 0, 0, 1, 1, 0, 0, 0}  \
}

#define Arrow { \
     {0, 0, 0, 0, 1, 0, 0, 0}, \
     {0, 0, 0, 1, 1, 1, 0, 0}, \
     {0, 0, 1, 1, 1, 1, 1, 0}, \
     {0, 1, 1, 1, 1, 1, 1, 1}, \
     {0, 0, 0, 1, 1, 1, 0, 0}, \ 
     {0, 0, 0, 1, 1, 1, 0, 0}, \
     {0, 0, 0, 1, 1, 1, 0, 0}, \
     {0, 0, 0, 1, 1, 1, 0, 0}  \
}


byte col = 0;
byte leds[8][8];

// pin[xx] on led matrix connected to nn on Arduino (-1 is dummy to make array start at pos 1)
int pins[17]= {-1, 5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};

// col[xx] of leds = pin yy on led matrix
int cols[8] = {pins[13], pins[3], pins[4], pins[10], pins[06], pins[11], pins[15], pins[16]};

// row[xx] of leds = pin yy on led matrix
int rows[8] = {pins[9], pins[14], pins[8], pins[12], pins[1], pins[7], pins[2], pins[5]};

const int numPatterns = 8;
byte patterns[numPatterns][8][8] = {
  H,I,heart1,heart2,heart3,Arrow,SPACE
};

int pattern = 0;

void setup() {
  // sets the pins as output
  for (int i = 1; i <= 16; i++) {
    pinMode(pins[i], OUTPUT);
  }

  // set up cols and rows
  for (int i = 1; i <= 8; i++) {
    digitalWrite(cols[i - 1], LOW);
  }

  for (int i = 1; i <= 8; i++) {
    digitalWrite(rows[i - 1], LOW);
  }

  clearLeds();

  // Turn off toggling of pin 11
  FrequencyTimer2::disable();
  // Set refresh rate (interrupt timeout period)
  FrequencyTimer2::setPeriod(2000);
  // Set interrupt routine to be called
  FrequencyTimer2::setOnOverflow(display);

}

void loop() {
  for (int i = 0; i < numPatterns; i++) {
    setPattern(i);
    delay(1000);
  }
}

void clearLeds() {
  // Clear display array
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      leds[i][j] = 1;
    }
  }
}

void setPattern(int pattern) {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      leds[i][j] = patterns[pattern][i][j];
    }
  }
}

// Interrupt routine
void display() {
  digitalWrite(cols[col], LOW);  
  col++;
  if (col == 8) {
    col = 0;
  }
  for (int row = 0; row < 8; row++) {
    if (leds[col][7 - row] == 1) {
      digitalWrite(rows[row], LOW);  
    }
    else {
      digitalWrite(rows[row], HIGH); 
    }
  }
  digitalWrite(cols[col], HIGH); 
}

💡 核心技術剖析與亮點解讀

1. 三維陣列 patterns[numPatterns][8][8] 的結構

  • 第一維 [numPatterns] (頁碼):代表動畫總共有多少張連續畫面(動畫幀)。本範例共有 8 幀(H, I, heart1, heart2, heart3, Arrow, SPACE)。

  • 第二維與第三維 [8][8] (點陣圖案):每一幀都是由 8 列 8 行的 01 矩陣組成。

    • 1:代表亮點(或熄滅,取決於邏輯判斷)。

    • 0:代表背景。

2. 為什麼要使用 FrequencyTimer2 中斷掃描?

在傳統掃描程式中,我們常會在 loop() 裡面寫 for 迴圈搭配 delay()。但這會導致兩個致命缺點:

  1. 畫面閃爍 (Flicker):如果 loop() 中有複雜的邏輯計算或 delay(1000),掃描就會停頓。

  2. CPU 被死綁:為了維護掃描,微控制器無法處理其他任務(例如讀取按鈕、感測器)。

FrequencyTimer2::setOnOverflow(display) 解決了這個問題!它利用晶片內部的Timer2,每隔 2000 微秒(2 毫秒)就會硬體強制暫停 loop(),自動進去執行 display() 掃描一格 Column,執行完後秒返回 loop()。這意味著:

  • 掃描頻率,完全超越人眼視覺暫留極限,絕無閃爍!

  • 主程式解套loop() 裡面的 delay(1000) 只影響「動畫換頁的速度」,完全不會卡到「畫面點亮與掃描」!

3. 1088AS 點陣屏腳位映射陣列

程式中的 pins[17]cols[8]rows[8] 巧妙地將 1088AS 的腳位(1~16)轉換為 Arduino 的 GPIO,讓複雜的交叉接線在程式庫內輕鬆實現軟體定序。

四、 常見問題與除錯 (FAQ)

Q1:點陣屏顯示圖案上下或左右顛倒?

  • 解答: 1088AS 有方向性。請確認 Pin 1 位置,或直接在 display() 程式碼中將 7 - row 改為 row 即可修正。

Q2:編譯時出現 FrequencyTimer2.h 找不到的錯誤?

  • 解答: 代表尚未安裝函式庫。請至 Arduino IDE 「工具」「管理函式庫」 搜尋 FrequencyTimer2並點擊安裝。

Q3:畫面出現殘影(Ghosting)或亮度太暗?

  • 解答: 請確認 FrequencyTimer2::setPeriod() 設定在 1000~3000 微秒之間(刷新率過低會閃爍),並確保切換 Column 前有先將前一列關閉。

🔗 延伸閱讀與推薦課程

 

相關文章