我 第 二 個 要 講 的 顯 示 器 ,就 是 一 個 十 分 流 行 的 1602 LCD 顯 示 模 組 。1602 是 指 它 有 兩 行 ,而 每 行 可 以 顯 示 16 個 字 。
1602 LCD 比 起 七 段 數 碼 管 ,可 以 顯 示 非 常 大 量 的 資 料 ( 4 個 位 vs 32 個 位 )。而 每 個 位 可 以 顯 示 的 字 元 亦 多 得 多 ( 可 以 顯 示 英 文 大 小 寫 和 符 號 )。
我 手 頭 的 這 一 個 1602 LCD 是 有 I2C ( Inter-Integrated Circuit,IIC,所 以 正 寫 是 I2C,讀 作 I-square-C ) 介 面 的 。I2C 介 面 可 以 把 原 來 LCD 需 要 的 6 根 接 線 ,減 少 到 只 需 要 兩 根 。而 且 ,I2C 介 面 可 以 只 用 兩 根 接 線 ,就 串 聯 多 個 不 同 的 裝 置 使 用 ( 但 IIC 地 址 不 能 一 樣 )。
要 在 Arduino 上 面 使 用 I2C 裝 置 ,會 有 一 點 特 別 ,因 為 大 部 分 Arduino 主 板 都 只 有 兩 個 特 定 的 pin 支 援 I2C。在 Arduino UNO 主 板 ,這 兩 個 pin 分 別 是 A4 (SDA) 和 A5 (SCL),意 思 就 是 I2C 裝 置 是 一 定 要 接 在 這 兩 個 pin 之 上 的 。
Library 介 紹 和 下 載 :Arduino-LiquidCrystal-I2C-library
下 載 回 來 後 看 看 header 檔 ( LiquidCrystal_I2C.h ),這 個 Library 的 功 能 還 頗 多 的 ,但 好 多 地 方 都 沒 有 寫 說 明 文 字 ,也 有 某 幾 個 function 係 無 define 的 。哈 哈 ,不 過 免 費 的 東 西 就 別 嫌 三 嫌 四 了 ,能 用 就 好 。( 這 個 library 明 顯 是 改 良 自 Arduino 的 LiquidCrystal Library,並 加 入 了 I2C 支 援 ,所 以 大 家 可 以 去 讀 讀 Arduino LiquidCrystal Library 的 說 明 文 字 ,就 會 更 清 楚 各 條 function 的 用 法 。)
就 如 同 之 前 一 樣 ,我 直 接 用 Library 的 名 稱 作 為 extension 的 名 稱 。首 先 ,我 們 新 增 一 個 叫 「LiquidCrystal_I2C」的 folder,然 後 把 header 檔 和 source 檔 ( *.h 和 *.cpp ) 複 製 到 src 子 目 錄 。這 個 library 的 cpp 檔 引 用 header 檔 時 ,本 身 已 經 是 用 double quotes,所 以 就 唔 需 要 作 出 改 動 。
然 後 我 們 就 要 在 根 目 錄 建 立 一 個 s2e 檔 ( LiquidCrystal_I2C.s2e )。除 了 extensionName 之 外 ,Basic information 就 大 家 自 己 喜 歡 怎 麼 寫 就 怎 麼 寫 好 了 。
然 後 就 開 始 寫 block definition,首 先 當 然 是 Initialize,裡 面 包 含 了 include,constructor,還 有 它 必 須 要 首 先 執 行 的 begin()。
這 裡 面 特 別 要 留 意 的 是 那 條 constructor function,裡 面 有 3 個 參 數 。第 一 個 參 數 是 LCD 的 I2C 地 址 ,第 二 個 是 LCD 有 多 少 個 columns,第 三 個 參 數 是 LCD 有 多 少 個 rows。如 果 你 想 寫 一 個 general 的 extension 給 所 有 大 小 的 LCD 使 用 ,你 是 可 以 把 這 些 參 數 都 寫 成 由 使 用 者 輸 入 的 。但 為 了 簡 化 這 個 extension,所 以 我 就 把 參 數 寫 死 了 ,只 支 援 我 手 頭 上 的 LCD。所 以 ,這 個 initialize 積 木 就 沒 有 任 何 使 用 者 輸 入 的 了 。
如 果 你 的 LCD 跟 我 的 唔 一 樣 ,你 可 以 下 載 之 後 自 行 修 改 *.s2e 檔 。又 或 者 嘗 試 把 Initialize 積 木 改 寫 成 接 受 使 用 者 輸 入 。
這 條 function 裡 面 比 較 特 別 的 是 I2C 地 址 ,你 可 以 問 問 店 家 ,如 果 店 家 唔 清 楚 ,我 們 也 可 以 自 行 下 載 I2C scanner 來 找 出 手 頭 上 的 硬 體 的 I2C 地 址 的 。( 我 手 頭 上 的 就 是 0x3F )
然 後 我 寫 了 兩 個 backlight blocks,一 個 開 ,一 個 關 。兩 者 就 是 對 應 library 裡 面 的 backlight() 和 noBacklight() functions。
然 後 ,display() 和 noDisplay(),cursor() 和 noCursor(),blink() 和 noBlink(),都 可 以 採 用 完 全 相 同 的 做 法 。
然 後 就 是 scrollDisplayRight() 和 scrollDisplayLeft(),它 們 可 以 把 整 個 顯 示 的 文 字 向 左 移 一 格 又 或 向 右 移 一 格 。
最 後 ,我 寫 了 一 個 print 積 木 。但 我 希 望 簡 化 它 的 用 法 ,令 到 使 用 者 唔 需 要 操 心 cursor 的 位 置 ,亦 唔 要 操 心 方 向 ,究 竟 是 向 前 print 還 是 向 後 print 之 類 的 。
總 之 ,每 一 次 使 用 者 都 要 輸 入 兩 行 的 完 整 資 料 ,每 一 次 我 都 會 clear display 和 把 cursor 移 回 第 一 行 開 始 ( clear() 和 home() )。
這 樣 的 寫 法 ,亦 簡 化 了 extension,我 們 唔 需 要 再 寫 home(), clear(), setCursor(), leftToRight(), autoscroll() 等 等 一 大 堆 比 較 不 常 用 的 積 木 。
mBlock extension 下 載 : LiquidCrystal_I2C.zip
完 成 之 後 ,我 們 把 整 個 folder 壓 縮 成 一 個 zip 檔 ,再 在 mBlock 裡 面 add extension。之 後 當 然 寫 個 小 程 式 去 測 試 一 下 各 個 積 木 。
如 果 沒 問 題 ,我 們 就 進 入 這 一 課 的 最 後 一 個 例 子 ,一 個 使 用 74HC595 的 2 digit display。
>> Next: 自 己 寫 個 mBlock extension (三 ) 2-digit-display using 74HC595 <<
延 伸 閱 讀 :
1. Writing a Library for Arduino ;
2. Create Extensions for mBlock ;
3. Getting Start with mBlock (PDF) ;
4. The Programing Structure of an Arduino Sketch ;
5. Arduino – Wire Library ( I2C ) ;
6. Arduino Playground – I2C Scanner ;