使用 MAX7219 驅動七段顯示器

在前一篇教學裡,介紹了如何利用 74HC595 shift register 驅動七段顯示器的基本概念。在接下來的文章中,將會說明如何使用另一顆 LED 驅動 IC:MAX7219,來驅動七段顯示器 (最高支援八個七段顯示器;換句話說,相當於同時驅動 64 顆 LED)。藉由修改 74HC595 教學範例的程式,使 LinkIt 7697 得以使用八位數七段顯示器模組 (內建 MAX7219),並透過這個過程讓開發者了解 MAX7219 的主要功能及運作機制。

目錄

  • 目錄

  • 指令格式

  • 硬體接線

  • 暫存器定義

    • Decode Mode (0x09)

    • Digit 0 ~ Digit 7 data (0x01 ~ 0x08)

    • Intensity (0x0A)

    • Scan Limit (0x0B)

    • Shutdown (0x0C)

    • Display Test (0x0F)

  • 範例:顯示遞增數值

  • 結論

指令格式

在深入解析 MAX7219 前,第一步要先了解如何與 MAX7219 溝通。執行任何一項 MAX7219 的功能時,都需要對它發出指令,待 MAX7219 收到指令後,它會依指令更新其內部暫存器的值、進而觸發動作。指令格式為固定 16-bit 長度的「暫存器位址 / 資料數值」組合,各個位元的定義如下 (X 表示可為任意值):

發送指令的方式為:拉低 LOAD 訊號、在 CLK 訊號打 16 個時脈的過程中,透過 DIN 腳位依序把 16-bit 的指令送進 MAX7219,送完後拉高 LOAD 訊號即完成一筆指令的傳輸。對應的時序圖示意為:

透過使用 shiftOut() API 產生時脈訊號及傳送資料,在 Arduino 裡的實作如下:

// define pins used on LinkIt 7697
// pin 13 of MAX7219 (CLK)
const int clock_pin = 15;
// pin 12 of MAX7219 (LOAD)
const int data_latch_pin = 16;
// pin 1 of MAX7219 (DIN)
const int data_input_pin = 17;
 
// update the register value of MAX7219
void set_register(byte address, byte value)  
{
  digitalWrite(data_latch_pin, LOW);
  shiftOut(data_input_pin, clock_pin, MSBFIRST, address);
  shiftOut(data_input_pin, clock_pin, MSBFIRST, value);
  digitalWrite(data_latch_pin, HIGH);
}

硬體接線

LinkIt 7697 透過下列腳位與八位數顯示器模組相連:

  • 5V

  • GND

  • P15

  • P16

  • P17

該五隻腳位分別接到顯示模組上的:

  • VCC

  • GND

  • CLK

  • CS (即 MAX7219 的 LOAD 腳位)

  • DIN

接線示意圖為:

顯示模組需使用 5V 電源輸入,若僅供給 3.3V 則顯示器亮度會受到影響。

暫存器定義

要順利驅動 MAX7219,需正確設定對應的暫存器。在此範例中,開發者需要設定下列六類型的暫存器:

暫存器名稱位址說明

Decode Mode

0x09

開啟 / 關閉 decode 模式

Intensity

0x0A

調整顯示器亮度

Scan Limit

0x0B

設定欲啟動的顯示器數目

Shutdown

0x0C

開啟 / 關閉顯示模組

Display Test

0x0F

開啟 / 關閉測試模式 (顯示器的所有筆畫皆會亮起)

Digit 0 ~ Digit 7 data

0x01 ~ 0x08

控制位數 0 到位數 7 的顯示資料

在 Arduino 範例程式裡將它們定義為:

// the MAX7219 address map (datasheet table 2)
#define MAX7219_DECODE_REG      (0x09)
#define MAX7219_DIGIT_REG(pos)  ((pos) + 1)
#define MAX7219_INTENSITY_REG   (0x0A)
#define MAX7219_SCANLIMIT_REG   (0x0B)
#define MAX7219_SHUTDOWN_REG    (0X0C)
#define MAX7219_DISPLAYTEST_REG (0x0F)

針對各個暫存器,對應的操作說明及範例如下:

Decode Mode (0x09)

MAX7219 針對每個顯示器,皆分別支援兩種資料顯示模式:1) 原始資料模式 2) BCD 碼模式。例如:

set_register(MAX7219_DECODE_REG, B00011010);

此例中,位元 1、3、4 被設為 1,因此表示位數 1、位數 3、位數 4 被設定為 BCD 碼 decode 模式。而剩下的位數 0 / 2 / 5 / 6 / 7 則為原始資料模式

Digit 0 ~ Digit 7 data (0x01 ~ 0x08)

原始資料模式中,開發者需自行指定七段顯示器中每個筆畫的明滅資訊,就如同 74HC595 教學中提及的一樣。

舉例來說,若開發者想在位數 3 顯示數字 "7",表示七段顯示器的筆畫 "A"、"B"、"C" (參考上圖) 需要被開啟;對應到暫存器的值,即 Digit 3 暫存器的第 4、5、6 個位元 (上圖表格) 需設定為 1:

set_register(MAX7219_DIGIT_REG(3), B01110000);

雖然在原始資料模式中指定筆畫的方式較為複雜,但它提供了開發者顯示各種圖形組合的彈性:

除了原始資料模式外,MAX7219 還提供了另一種叫做 BCD 碼 decode 模式的操作方法。在 decode 模式下,每個字的筆畫構成已被事先定義、並依照 BCD 碼 B 區 (見下表) 的規範儲存在 MAX7219 當中。因此要顯示這些字時,僅需提供每個字所對應的索引編號即可。

*不論在原始資料模式或是 decode 模式中,若要顯示小數點,都需自行將 Digit 暫存器的第 7 位元 (D7) 設成 1。

也就是說,若開發者要顯示數字 "0" 到 "9"、"-"、"E"、"H"、"L"、"P" 及 " " (空格) 這十六種字元,在 decode 模式下,不需自行傳送筆畫定義資訊給 MAX7219、直接給 MAX7219 字元的索引值即可。例如,要使用 decode 模式在位數 5 顯示子母 "E",則需把 Decode Mode 暫存器的 D5 設成 1,接著把 Digit 5 data 暫存器設為 11 (也就是二進位的 B1011,見上表定義),就可以讓顯示器顯示出字母 "E"。對應的程式碼如下:

// Make Digit 5 is under BCD Code B decode mode
set_register(MAX7219_DECODE_REG, B00100000);
// Make it display character "E"
set_register(MAX7219_DIGIT_REG(5), 11);

Intensity (0x0A)

調整 LED 顯示器的亮度。值域範圍為 0x0 (最暗) 到 0xF (最亮)。

// Dimmest
set_register(MAX7219_INTENSITY_REG, 0x0);
// Brightest
set_register(MAX7219_INTENSITY_REG, 0xF);

Scan Limit (0x0B)

設定模組上要開啟的顯示器個數 (即顯示位數)。下面分別為開啟一個位數、五個位數、以及八位數全開的範例:

// Only Digit 0 are turned on
set_register(MAX7219_SCANLIMIT_REG, 0);
// Only Digit 0 ~ Digit 4 are turned on
set_register(MAX7219_SCANLIMIT_REG, 4);
// All digits (Digit 0 ~ Digit 7) are turned on
set_register(MAX7219_SCANLIMIT_REG, 7);

Shutdown (0x0C)

開啟 / 關閉顯示器模組。

#define MAX7219_OFF (0x0)
#define MAX7219_ON  (0x1)

// Turn off the display
set_register(MAX7219_SHUTDOWN_REG, MAX7219_OFF);
// Turn on the display
set_register(MAX7219_SHUTDOWN_REG, MAX7219_ON);

Display Test (0x0F)

開啟 / 關閉測試模式。開啟此模式時,顯示器的所有筆畫都會亮起。

// Enter test mode. No matter what data bytes of each digit register are, all display segments are on
set_register(MAX7219_DISPLAYTEST_REG, MAX7219_ON);
// Non-test mode. Display segments according to the data byte and decode mode for each digit
set_register(MAX7219_DISPLAYTEST_REG, MAX7219_OFF);

範例:顯示遞增數值

結合上述的暫存器說明並修改之前的 74HC595 範例,下列的 Arduino sketch 展示了如何在八位數七段顯示器模組上顯示遞增數值 (及小數點移動) 的效果。

//
// Use one MAX7219 to control 8-digit seven-segment display
// the display module: http://www.icshop.com.tw/product_info.php/products_id/20686
//
// MAX7219 datasheet: https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf
//

// the MAX7219 address map (datasheet table 2)
#define MAX7219_DECODE_REG      (0x09)
#define MAX7219_INTENSITY_REG   (0x0A)
#define MAX7219_SCANLIMIT_REG   (0x0B)
#define MAX7219_SHUTDOWN_REG    (0X0C)
#define MAX7219_DISPLAYTEST_REG (0x0F)
#define MAX7219_DIGIT_REG(pos)  ((pos) + 1)

// shutdown mode (datasheet table 3)
#define MAX7219_OFF             (0x0)
#define MAX7219_ON              (0x1)

// pin 13 of MAX7219 (CLK)
const int clock_pin = 15;
// pin 12 of MAX7219 (LOAD)
const int data_latch_pin = 16;
// pin 1 of MAX7219 (DIN)
const int data_input_pin = 17;

// digit pattern for a 7-segment display. datasheet table 5
const byte digit_pattern[16] =
{
  B01111110,  // 0
  B00110000,  // 1
  B01101101,  // 2
  B01111001,  // 3
  B00110011,  // 4
  B01011011,  // 5
  B01011111,  // 6
  B01110000,  // 7
  B01111111,  // 8
  B01111011,  // 9
  B01110111,  // A
  B00011111,  // b
  B01001110,  // C
  B00111101,  // d
  B01001111,  // E
  B01000111   // F
};

#define DP_FLAG       (B10000000)
#define NUM_OF_DIGITS (8)

unsigned int counter = 0;
unsigned int digit_base = 16;

// update the register value of MAX7219
void set_register(byte address, byte value)  
{
  digitalWrite(data_latch_pin, LOW);
  shiftOut(data_input_pin, clock_pin, MSBFIRST, address);
  shiftOut(data_input_pin, clock_pin, MSBFIRST, value);
  digitalWrite(data_latch_pin, HIGH);
}

void init_max7219()
{
  // disable test mode. datasheet table 10
  set_register(MAX7219_DISPLAYTEST_REG, MAX7219_OFF);
  // set medium intensity. datasheet table 7
  set_register(MAX7219_INTENSITY_REG, 0x8);
  // turn off display. datasheet table 3
  set_register(MAX7219_SHUTDOWN_REG, MAX7219_OFF);
  // drive 8 digits. datasheet table 8
  set_register(MAX7219_SCANLIMIT_REG, 7);
  // no decode mode for all positions. datasheet table 4
  set_register(MAX7219_DECODE_REG, B00000000);
}

void setup()  
{
  // init pin states
  pinMode(clock_pin, OUTPUT);
  pinMode(data_latch_pin, OUTPUT);    
  pinMode(data_input_pin, OUTPUT);

  // init MAX2719 states
  init_max7219();
}

void loop()  
{
  int i;
  unsigned int number;
  unsigned int digit_value;
  byte byte_data;
  
  number = counter++;
  
  // turn off display first
  set_register(MAX7219_SHUTDOWN_REG, MAX7219_OFF);

  // get every values in each position of those 8 digits based on "digit_base"
  //
  // digit_base should be <= 16
  //
  // for example, if digit_base := 2, binary values will be shown. If digit_base := 16, hexidecimal values will be shown
  //
  for (i = 0; i < NUM_OF_DIGITS; i++)
  {
    digit_value = number % digit_base;
    number /= digit_base;

    byte_data = digit_pattern[digit_value];

    if (counter % NUM_OF_DIGITS == i)
    {
      byte_data |= DP_FLAG;
    }

    set_register(MAX7219_DIGIT_REG(i), byte_data);
  }

  // turn on display
  set_register(MAX7219_SHUTDOWN_REG, MAX7219_ON);
  
  delay(50);
}

此範例的基本配置如下:

  • 以十六進位遞增數值。

  • 使用原始資料模式定義字元筆畫,

  • 使用中等顯示亮度。

可透過一些修改進行顯示效果的改變。例如,要從原本的 16 進位數值變為 10 進位 / 8 進位 / 2 進位模式時,可修改第 52 行digit_base 將之設定為 10、8 或是 2。下面的程式碼為修改成 10 進位的範例:

// change the counting mode to decimal mode
unsigned int digit_base = 10;

若要將資料解讀模式從原始資料模式改為 BCD 碼 decode 模式,則需要修改兩個地方。首先在第 74 行將八個顯示器都設定為 decode 模式:

// enable decode mode for all positions. datasheet table 4
set_register(MAX7219_DECODE_REG, B11111111);

接著在第 111 行,將送進 MAX7219 的資料從筆畫資訊改為索引索引值:

digit_value = number % digit_base;
number /= digit_base;
// no need to get the raw segment patterns. use the value directly to index the BCD code
byte_data = digit_value; // byte_data = digit_pattern[digit_value];

結論

透過本教學的內容,開發者可了解 MAX7219 的使用方法。雖然 MAX7219 的主要功能為驅動七段顯示器,但它也可用於其他的 LED 驅動場景。例如 8x8 矩陣式顯示器就是另一種常見的 MAX7219 應用:利用原始資料模式的設定方法來控制矩陣式顯示器。詳細的原理及做法,將會在下一篇教學裡進行詳細介紹。

Last updated