2021-04-01

PCF8574* VS MCP23017

最近打算接駁幾個顯示器,顯示一些資料
但單單是一個 8x8點陣顯示器 便要用 16支引腳,引腳使用量非常多
因此尋找一些類似使用 I2C 或 SPI 不需要太多引腳便可以模擬多位元的 擴展器
MCP23017 與 在下之前介紹的 PCF8574 都是一種 I2C 的 擴展器
而且 MCP23017 是 16位元 擴展器,比 PCF8574 多8位元
由於 I2C 只需要 2支引腳 便可以讓 Slave 裝置運作,如果成本相約的話, MCP23017 擴充效果會更好
因此在下簡單比較 PCF8574* 及 MCP23017

PCF8574* 外觀

見下文
PCF8574 及 PCF8574A 的正面

見下文
PCF8574 或 PCF8574A 的背面

PCF8574* 引腳

PCF8574* 具有 雙列直插封裝 (Dual In-line Package (DIP)) ,共有 16支引腳
引腳16引腳15引腳14引腳13引腳12引腳11引腳10引腳9
引腳1引腳2引腳3引腳4引腳5引腳6引腳7引腳8
用途VCCSDASCLINTD7D6D5D4
A0A1A2D0D1D2D3GND

編號描述方向用途
1A0輸入第0位地址
2A1輸入第1位地址
3A2輸入第2位地址
4D0輸入/輸出第0位元資料
5D1輸入/輸出第1位元資料
6D2輸入/輸出第2位元資料
7D3輸入/輸出第3位元資料
8GND接地
9DB4輸入/輸出第4位元資料
10DB5輸入/輸出第5位元資料
11DB6輸入/輸出第6位元資料
12DB7輸入/輸出第7位元資料
13INT輸入中斷訊號
14SCL輸入序列時脈
15SDA輸入序列資料
16VCC電源 (接受 1.8V 至 5.5V)

PCF8574* 地址

PCF8574 及 PCF8574A 的地址範圍並不相同
類型地址讀/寫
D7D6D5D4D3D2D1D0
PCF85740100###*
PCF8574A0111###*

PCF8574地址讀/寫十六進制地址
D7D6D5D4D3D2D1D0
0100000*0x400x41
0100001*0x420x43
0100010*0x440x45
0100011*0x460x47
0100100*0x480x49
0100101*0x4A0x4B
0100110*0x4C0x4D
0100111*0x4E0x4F

PCF8574A地址讀/寫十六進制地址
D7D6D5D4D3D2D1D0
0111000*0x700x71
0111001*0x720x73
0111010*0x740x75
0111011*0x760x77
0111100*0x780x79
0111101*0x7A0x7B
0111110*0x7C0x7D
0111111*0x7E0x7F

PCF8574* 電路

見下文
電路原型

見下文
見下文
見下文
見下文
使用 PCF8574 及 PCF8574A 來測試電路

見下文
測試效果
即使只顯示 1格 LED 都很暗,如果 64格 LED 全亮著接近沒有光度

在下使用 Arduino 預設的 Wire.h 函式庫測試
#include <Wire.h>

byte anodeAddress = 0x20;
byte cathodeAddress = 0x38;

void set(byte address, byte data) {
    Wire.beginTransmission(address);
    Wire.write(data);
    Wire.endTransmission();
}

void setup() {
    Wire.begin();
}

void loop() {
    for (byte r = 0; r < 8; r++) {
        // anodes
        set(cathodeAddress, ~0x00);
        set(anodeAddress, 1 << r);
        for (byte c = 0; c < 8; c++) {
            // cathodes
            set(cathodeAddress, ~(1 << c));
            delay(100);
        }
    }
}

閣下可能會發現 Wire.h 設定地址分別是 0x20 及 0x38 並不是 PCF8574 及 PCF8574A 的範圍
原因是 Wire.h 設定地址時,並不理會讀寫的位元
即是如果要指定 0x40 的地址時,會向右偏移 1位元,所以 0x40 >> 1 即是 0x20
同樣,如果要指定 0x70 的地址時,會向右偏移 1位元,所以 0x70 >> 1 即是 0x38

MCP23017 外觀

見下文
MCP23017 的正面

見下文
MCP23017 的背面

MCP23017 引腳

MCP23017 同樣具有 雙列直插封裝 (Dual In-line Package (DIP)) ,共有 28支引腳,數量與 ATmega328P* 相同
引腳28引腳27引腳26引腳25引腳24引腳23引腳22引腳21引腳20引腳19引腳18引腳17引腳16引腳15
引腳1引腳2引腳3引腳4引腳5引腳6引腳7引腳8引腳9引腳10引腳11引腳12引腳13引腳14
用途DA7DA6DA5DA4DA3DA2DA1DA0INTAINTBRSTA2A1A0
DB0DB1DB2DB3DB4DB5DB6DB7VCCGNDNC0SCLSDANC1

編號描述方向用途
1DB0輸入/輸出Port B 第0位元資料
2DB1輸入/輸出Port B 第1位元資料
3DB2輸入/輸出Port B 第2位元資料
4DB3輸入/輸出Port B 第3位元資料
5DB4輸入/輸出Port B 第4位元資料
6DB5輸入/輸出Port B 第5位元資料
7DB6輸入/輸出Port B 第6位元資料
8DB7輸入/輸出Port B 第7位元資料
9VCC電源 (接受 1.8V 至 5.5V)
10GND接地
11NC0無效
12SCL輸入序列時脈
13SDA輸入序列資料
14NC1無效
15A0輸入第0位地址
16A1輸入第1位地址
17A2輸入第2位地址
18RST輸入高電位時重設,低電位時運作
19INTB輸出中斷 Port B 訊號
20INTA輸出中斷 Port A 訊號
21DA0輸入/輸出Port A 第0位元資料
22DA1輸入/輸出Port A 第1位元資料
23DA2輸入/輸出Port A 第2位元資料
24DA3輸入/輸出Port A 第3位元資料
25DA4輸入/輸出Port A 第4位元資料
26DA5輸入/輸出Port A 第5位元資料
27DA6輸入/輸出Port A 第6位元資料
28DA7輸入/輸出Port A 第7位元資料

MCP23017 地址

MCP23017地址 與 PCF8574地址 相同,地址範圍為 0x20 至 0x27

MCP23017 暫存器

MCP23017 暫存器 共有 11個指令,區分 Port A 及 Port B 即是總共 22個指令
指令用途
IODIR輸入輸出方向暫存器 (Input/Output Direction Register)
控制 Port 的方向,高電位為輸入,低電位為輸出
例如:0x03 表示第7至第2引腳為輸出,第1至第0引腳為輸入
IPOL輸入極性暫存器 (Input Polarity Register)
當 Port 的設定為輸入時,改變輸入的極性為相反訊號,即是高電位改變為低電位,反之亦然
例如:0xC0 表示第7至第6引腳極性會反轉,第5至第0引腳極性為正常
GPINTEN通用目的輸入輸出中斷啟動暫存器 (General Purpose Input/Output Interrupt Enable Register)
指定 Port 引腳為中斷,高電位為啟動,低電位為取消
例如:0x0F 表示第7至第4引腳為取消,第3至第0引腳為啟動
啟動 Interrupt on Change 的引腳,必須設定 DEFVAL 及 INTCON 功能
DEFVAL預設值暫存器 (Default Value Register)
設定 Port 引腳的預設值
當引腳的狀態與引腳的預設值為相反時,中斷操作
INTCON中斷控制暫存器 (Interrupt Control Register)
設定 Port 引腳的比較狀態
高電位為與 DEFVAL 比較,低電位為與 Port 引腳上次電位比較
IOCON輸入輸出設置暫存器 (Input/Output Configuration Register)
  • 第7位元,設定 BANK
    高電位 為 8位元模式
    低電位 為 16位元模式
  • 第6位元,設定 MIRROR
    高電位 為 INT*引腳 內部連接
    低電位 為 INTA引腳 對應 Port A ,INTB引腳 對應 Port B
  • 第5位元,設定 SEQOP
    高電位 為 取消順序操作,地址指針不遞增
    低電位 為 啟動順序操作,地址指針遞增
  • 第4位元,設定 DISSLW
    高電位 為 取消迴轉率
    低電位 為 啟動迴轉率
  • 第3位元,設定 HAEN (只適合 MCP23S17)
    高電位 為 啟動硬件地址
    低電位 為 取消硬件地址
  • 第2位元,設定 ORD
    高電位 為 使用 Open Drain (取代 INTPOL)
    低電位 為 使用 Active Driver (必須設定 INTPOL)
  • 第1位元,設定 INTPOL
    高電位 為 上升沿
    低電位 為 下降沿
  • 第0位元,無效
GPPU通用目的輸入輸出上拉電阻暫存器 (General Purpose Input/Output Pull-Up Resistor Register)
當 Port引腳 設定為 輸入時,可以啟動 100KΩ 的上拉電阻
高電位 為 啟動上拉電阻,低電位 為 取消上拉電阻
INTF中斷標示暫存器 (Interrupt Flag Register)
反映 Port引腳 的中斷條件
高電位 為 引起中斷,低電位 為 未指定中斷條件
INTCAP中斷擷取暫存器 (Interrupt Captured Register)
反映中斷擷取的邏輯電位
GPIO通用目的輸入輸出暫存器 (General Purpose Input/Output Register)
當 Port引腳 為輸入時,啟動內部上拉電阻連接
當 Port引腳 為輸出時,便會透過 Port引腳 輸出電位訊號
OLAT輸出鎖存暫存器 (Output Latch Register)
反映輸出鎖存的邏輯電位
眾多指令中,唯一 IOCON 不需要區分 Port A 及 Port B
雖然有很多指令,但在下最常用主要只是 IODIRGPIO

8位元模式
8位元模式 使用第4位元區分,低電位 為 Port A ,高電位 為 Port B
D7D6D5D4D3D2D1D0Port APort B指令
000#00000x000x10IODIR
000#00010x010x11IPOL
000#00100x020x12GPINTEN
000#00110x030x13DEFVAL
000#01000x040x14INTCON
000#01010x050x15IOCON
000#01100x060x16GPPU
000#01110x070x17INTF
000#10000x080x18INTCAP
000#10010x090x19GPIO
000#10100x0A0x1AOLAT

16位元模式
16位元模式 使用第0位元區分,低電位 為 Port A ,高電位 為 Port B
D7D6D5D4D3D2D1D0Port APort B指令
0000000#0x000x01IODIR
0000001#0x020x03IPOL
0000010#0x040x05GPINTEN
0000011#0x060x07DEFVAL
0000100#0x080x09INTCON
0000101#0x0A0x0BIOCON
0000110#0x0C0x0DGPPU
0000111#0x0E0x0FINTF
0001000#0x100x11INTCAP
0001001#0x120x13GPIO
0001010#0x140x15OLAT

MCP23017 電路

見下文
電路原型

見下文
見下文
使用 MCP23017 來測試電路

見下文
測試效果
光度非常充足,即使 64格 LED 全亮著都有合理的光度

測試程式碼
#include <Wire.h>

byte address = 0x20;

void set(byte address, byte reg, byte data) {
    Wire.beginTransmission(address);
    Wire.write(reg);
    Wire.write(data);
    Wire.endTransmission();
}

void setup() {
    Wire.begin();
    set(address, 0x00, 0x00);
    set(address, 0x01, 0x00);
}
 
void loop() {
    for (byte r = 0; r < 8; r++) {
        // anodes
        set(address, 0x13, ~0x00);
        set(address, 0x12, 1 << r);
        for (byte c = 0; c < 8; c++) {
            // cathodes
            set(address, 0x13, ~(1 << c));
            delay(100);
        }
    }
}

總結

2粒 PCF8574* 理論上與 1粒 MCP23017 同樣提供 16位元 輸入輸出
但 PCF8574* 比較佔據空間,共有32支引腳,亦需要較多線路接駁,還要保存兩組控制地址
不過 PCF8574* 成本則比較少,而且 PCF8574 很多模組板或測試板,使用上亦比較方便
而且 PCF8574* 的訊號及操作比較簡單

MCP23017 最高速度為 1.7Mhz ,而 PCF8574* 只有 100Khz ,快 17倍
而且只需要 8個地址,便可以擴展至 128位元,較少地址亦可以減少電路數量
另外還可以保持電壓穩定,對於控制輸出顯示等電子裝置效果更好
如果正式作為擴展器使用,在下建議使用 MCP23017

參考資料

沒有留言 :

張貼留言