最近打算接駁幾個顯示器,顯示一些資料
但單單是一個 8x8點陣顯示器 便要用 16支引腳,引腳使用量非常多
因此尋找一些類似使用 I2C 或 SPI 不需要太多引腳便可以模擬多位元的 擴展器
但單單是一個 8x8點陣顯示器 便要用 16支引腳,引腳使用量非常多
因此尋找一些類似使用 I2C 或 SPI 不需要太多引腳便可以模擬多位元的 擴展器
MCP23017 與 在下之前介紹的 PCF8574 都是一種 I2C 的 擴展器
而且 MCP23017 是 16位元 擴展器,比 PCF8574 多8位元
由於 I2C 只需要 2支引腳 便可以讓 Slave 裝置運作,如果成本相約的話, MCP23017 擴充效果會更好
因此在下簡單比較 PCF8574* 及 MCP23017
而且 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 |
用途 | VCC | SDA | SCL | INT | D7 | D6 | D5 | D4 |
A0 | A1 | A2 | D0 | D1 | D2 | D3 | GND |
編號 | 描述 | 方向 | 用途 |
---|---|---|---|
1 | A0 | 輸入 | 第0位地址 |
2 | A1 | 輸入 | 第1位地址 |
3 | A2 | 輸入 | 第2位地址 |
4 | D0 | 輸入/輸出 | 第0位元資料 |
5 | D1 | 輸入/輸出 | 第1位元資料 |
6 | D2 | 輸入/輸出 | 第2位元資料 |
7 | D3 | 輸入/輸出 | 第3位元資料 |
8 | GND | 接地 | |
9 | DB4 | 輸入/輸出 | 第4位元資料 |
10 | DB5 | 輸入/輸出 | 第5位元資料 |
11 | DB6 | 輸入/輸出 | 第6位元資料 |
12 | DB7 | 輸入/輸出 | 第7位元資料 |
13 | INT | 輸入 | 中斷訊號 |
14 | SCL | 輸入 | 序列時脈 |
15 | SDA | 輸入 | 序列資料 |
16 | VCC | 電源 (接受 1.8V 至 5.5V) |
PCF8574* 地址
PCF8574 及 PCF8574A 的地址範圍並不相同
類型 | 地址 | 讀/寫 | ||||||
---|---|---|---|---|---|---|---|---|
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
PCF8574 | 0 | 1 | 0 | 0 | # | # | # | * |
PCF8574A | 0 | 1 | 1 | 1 | # | # | # | * |
PCF8574地址 | 讀/寫 | 十六進制地址 | |||||||
---|---|---|---|---|---|---|---|---|---|
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 寫 | 讀 |
0 | 1 | 0 | 0 | 0 | 0 | 0 | * | 0x40 | 0x41 |
0 | 1 | 0 | 0 | 0 | 0 | 1 | * | 0x42 | 0x43 |
0 | 1 | 0 | 0 | 0 | 1 | 0 | * | 0x44 | 0x45 |
0 | 1 | 0 | 0 | 0 | 1 | 1 | * | 0x46 | 0x47 |
0 | 1 | 0 | 0 | 1 | 0 | 0 | * | 0x48 | 0x49 |
0 | 1 | 0 | 0 | 1 | 0 | 1 | * | 0x4A | 0x4B |
0 | 1 | 0 | 0 | 1 | 1 | 0 | * | 0x4C | 0x4D |
0 | 1 | 0 | 0 | 1 | 1 | 1 | * | 0x4E | 0x4F |
PCF8574A地址 | 讀/寫 | 十六進制地址 | |||||||
---|---|---|---|---|---|---|---|---|---|
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 寫 | 讀 |
0 | 1 | 1 | 1 | 0 | 0 | 0 | * | 0x70 | 0x71 |
0 | 1 | 1 | 1 | 0 | 0 | 1 | * | 0x72 | 0x73 |
0 | 1 | 1 | 1 | 0 | 1 | 0 | * | 0x74 | 0x75 |
0 | 1 | 1 | 1 | 0 | 1 | 1 | * | 0x76 | 0x77 |
0 | 1 | 1 | 1 | 1 | 0 | 0 | * | 0x78 | 0x79 |
0 | 1 | 1 | 1 | 1 | 0 | 1 | * | 0x7A | 0x7B |
0 | 1 | 1 | 1 | 1 | 1 | 0 | * | 0x7C | 0x7D |
0 | 1 | 1 | 1 | 1 | 1 | 1 | * | 0x7E | 0x7F |
PCF8574* 電路
電路原型
使用 PCF8574 及 PCF8574A 來測試電路
測試效果
即使只顯示 1格 LED 都很暗,如果 64格 LED 全亮著接近沒有光度
即使只顯示 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
原因是 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 |
用途 | DA7 | DA6 | DA5 | DA4 | DA3 | DA2 | DA1 | DA0 | INTA | INTB | RST | A2 | A1 | A0 |
DB0 | DB1 | DB2 | DB3 | DB4 | DB5 | DB6 | DB7 | VCC | GND | NC0 | SCL | SDA | NC1 |
編號 | 描述 | 方向 | 用途 |
---|---|---|---|
1 | DB0 | 輸入/輸出 | Port B 第0位元資料 |
2 | DB1 | 輸入/輸出 | Port B 第1位元資料 |
3 | DB2 | 輸入/輸出 | Port B 第2位元資料 |
4 | DB3 | 輸入/輸出 | Port B 第3位元資料 |
5 | DB4 | 輸入/輸出 | Port B 第4位元資料 |
6 | DB5 | 輸入/輸出 | Port B 第5位元資料 |
7 | DB6 | 輸入/輸出 | Port B 第6位元資料 |
8 | DB7 | 輸入/輸出 | Port B 第7位元資料 |
9 | VCC | 電源 (接受 1.8V 至 5.5V) | |
10 | GND | 接地 | |
11 | NC0 | 無效 | |
12 | SCL | 輸入 | 序列時脈 |
13 | SDA | 輸入 | 序列資料 |
14 | NC1 | 無效 | |
15 | A0 | 輸入 | 第0位地址 |
16 | A1 | 輸入 | 第1位地址 |
17 | A2 | 輸入 | 第2位地址 |
18 | RST | 輸入 | 高電位時重設,低電位時運作 |
19 | INTB | 輸出 | 中斷 Port B 訊號 |
20 | INTA | 輸出 | 中斷 Port A 訊號 |
21 | DA0 | 輸入/輸出 | Port A 第0位元資料 |
22 | DA1 | 輸入/輸出 | Port A 第1位元資料 |
23 | DA2 | 輸入/輸出 | Port A 第2位元資料 |
24 | DA3 | 輸入/輸出 | Port A 第3位元資料 |
25 | DA4 | 輸入/輸出 | Port A 第4位元資料 |
26 | DA5 | 輸入/輸出 | Port A 第5位元資料 |
27 | DA6 | 輸入/輸出 | Port A 第6位元資料 |
28 | DA7 | 輸入/輸出 | 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)
|
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
雖然有很多指令,但在下最常用主要只是 IODIR 及 GPIO
雖然有很多指令,但在下最常用主要只是 IODIR 及 GPIO
8位元模式
8位元模式 使用第4位元區分,低電位 為 Port A ,高電位 為 Port B
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Port A | Port B | 指令 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | # | 0 | 0 | 0 | 0 | 0x00 | 0x10 | IODIR |
0 | 0 | 0 | # | 0 | 0 | 0 | 1 | 0x01 | 0x11 | IPOL |
0 | 0 | 0 | # | 0 | 0 | 1 | 0 | 0x02 | 0x12 | GPINTEN |
0 | 0 | 0 | # | 0 | 0 | 1 | 1 | 0x03 | 0x13 | DEFVAL |
0 | 0 | 0 | # | 0 | 1 | 0 | 0 | 0x04 | 0x14 | INTCON |
0 | 0 | 0 | # | 0 | 1 | 0 | 1 | 0x05 | 0x15 | IOCON |
0 | 0 | 0 | # | 0 | 1 | 1 | 0 | 0x06 | 0x16 | GPPU |
0 | 0 | 0 | # | 0 | 1 | 1 | 1 | 0x07 | 0x17 | INTF |
0 | 0 | 0 | # | 1 | 0 | 0 | 0 | 0x08 | 0x18 | INTCAP |
0 | 0 | 0 | # | 1 | 0 | 0 | 1 | 0x09 | 0x19 | GPIO |
0 | 0 | 0 | # | 1 | 0 | 1 | 0 | 0x0A | 0x1A | OLAT |
16位元模式
16位元模式 使用第0位元區分,低電位 為 Port A ,高電位 為 Port B
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | Port A | Port B | 指令 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | # | 0x00 | 0x01 | IODIR |
0 | 0 | 0 | 0 | 0 | 0 | 1 | # | 0x02 | 0x03 | IPOL |
0 | 0 | 0 | 0 | 0 | 1 | 0 | # | 0x04 | 0x05 | GPINTEN |
0 | 0 | 0 | 0 | 0 | 1 | 1 | # | 0x06 | 0x07 | DEFVAL |
0 | 0 | 0 | 0 | 1 | 0 | 0 | # | 0x08 | 0x09 | INTCON |
0 | 0 | 0 | 0 | 1 | 0 | 1 | # | 0x0A | 0x0B | IOCON |
0 | 0 | 0 | 0 | 1 | 1 | 0 | # | 0x0C | 0x0D | GPPU |
0 | 0 | 0 | 0 | 1 | 1 | 1 | # | 0x0E | 0x0F | INTF |
0 | 0 | 0 | 1 | 0 | 0 | 0 | # | 0x10 | 0x11 | INTCAP |
0 | 0 | 0 | 1 | 0 | 0 | 1 | # | 0x12 | 0x13 | GPIO |
0 | 0 | 0 | 1 | 0 | 1 | 0 | # | 0x14 | 0x15 | OLAT |
MCP23017 電路
電路原型
使用 MCP23017 來測試電路
測試效果
光度非常充足,即使 64格 LED 全亮著都有合理的光度
光度非常充足,即使 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* 的訊號及操作比較簡單
但 PCF8574* 比較佔據空間,共有32支引腳,亦需要較多線路接駁,還要保存兩組控制地址
不過 PCF8574* 成本則比較少,而且 PCF8574 很多模組板或測試板,使用上亦比較方便
而且 PCF8574* 的訊號及操作比較簡單
MCP23017 最高速度為 1.7Mhz ,而 PCF8574* 只有 100Khz ,快 17倍
而且只需要 8個地址,便可以擴展至 128位元,較少地址亦可以減少電路數量
另外還可以保持電壓穩定,對於控制輸出顯示等電子裝置效果更好
如果正式作為擴展器使用,在下建議使用 MCP23017
而且只需要 8個地址,便可以擴展至 128位元,較少地址亦可以減少電路數量
另外還可以保持電壓穩定,對於控制輸出顯示等電子裝置效果更好
如果正式作為擴展器使用,在下建議使用 MCP23017
沒有留言 :
張貼留言