--- tags: 單晶片 --- # Arduino講義:Serial Communication (I2C) --- <!-- > **重點 or 縮寫** 請標**黑粗** 且 英文記得空格ㄚㄚㄚㄚ --> <!-- > --> <!-- > [name=YuanHaoHo][color=#c8ff05] --> ## Introduction of I2C * I2C bus 為 Inter-Integrated Circuit Bus 的縮寫,中文叫做積體電路匯流排,其功用為提供 IC 之間的連接與通訊。 * 目的:減少MCU與周邊晶片之間的腳位數 * 只有兩條訊號線,<font color="red">SCL(Serial CLock Line) 負責傳時脈,SDA(Serial Data line)負責傳資料</font>。 * **I2C** : <font color="red"> 半雙工、串列、同步</font> * 以匯流排型介接允許有多個master以及slave。 ![](https://i.imgur.com/jOQudK1.png) * 由上圖可知,所有I2C裝置皆並接(Wired-AND)在SCL及SDA兩條線路上 * 須接<font color="red">上拉電阻(Rp)</font>,將浮接狀態( float )轉變為邏輯高準位( High )狀態。 ## I2C Bus協定 * 閒置( idle )時兩者皆為高電位。 ![](https://i.imgur.com/X4RwG5W.gif) * START condition:<font color="red">SCL為 HIGH時,SDA發生下緣</font> * 先傳地址( slave address,決定跟哪個 slave 溝通),再傳資料。地址有 7bit跟 10bit兩種。 * 7bit:最大可以有 128個 slave (但實際上有16個系統擴充位址是保留的)。 * 10bit:最大可以有 1024個 slave 。(但很少見,不是所有使用 I2C 的裝置都支援 10bit mode)。 * 地址:由於地址為 7bit,因此在傳第一個 byte的時候,前 7bit(MSB 為 address,最後的 bit 為 R/W bit,指定要"讀"或"寫"資料(0:write,1:Read)。 * 只在 <font color="red">SCL 為 HIGH 時,才會對 SDA 取樣。 SCL 為 LOW 時,不會取樣,但可改變資料</font>。 * STOP condition:<font color="red">SCL為 HIGH時,SDA發生上緣</font> ## ACK/NACK機制 * 發送端在每組(8bits)訊號送出後,需讀去接收端所回應的一個ACK bit(Acknowledge bit) <font color="red">(注意:發送端不一定是master,ex:讀取資料時,發送端為slave)</font> ## 實際傳輸的狀況 * 寫入: ![](https://i.imgur.com/ThlOXjN.gif) * R/W為0時,代表 slave 端要讀取master端資料,此時 slave 會發出一個 ==acknowledge bit==(就是由 slave 把 SDA 拉低),讓 master 確認 slave 是否有收到資料。 * 讀取: ![](https://i.imgur.com/PRWtSDN.gif) * R/W 為1時,代表 master 端要讀取 slave 端資料,此時 master 為 Receiver,slave 為 transmiter,因此 acknowledge bit 會是由 master 進行發送。 :::info note:傳地址後的 acknowledge bit 必為 slave 傳送給 master;傳送 Data 後的 acknowledge bit 則須視前面 R/W 的值而定。 ::: * 當 master 讀到 ACK 回應, 即可以繼續傳輸下一個 Byte。 * 當 master 讀到 NACK 回應, 意思是 **slave 無回應**,此時 master 應送出 (結束) 訊號放棄該命令。 * 參考資料: * [資料來源1](http://i2c.info/i2c-bus-specification) * [資料來源2](http://magicjackting.pixnet.net/blog/post/173061691-i2c-bus-%E7%B0%A1%E4%BB%8B-(inter-integrated-circuit-b)) --- #### Wire函數: | 函數 | 作用 | | --- | --- | | begin()| 啟動 Wire 作為 master 或是 slave | | beginTransmission(address)| 開始對 address 的連線 | | endTransmission() |關閉之前的連線 | | write(data) | 在連線上送出 一個 byte 的資料 | |read() | 讀取連線上的一個 byte 的資料 | |available() | 檢查連線上是否有可接收的資料 | |onReceive(function) | 設定用來接收資料的函數 | :::info note:在無(address)時,Arduino 是作為I2C的 master;有(address)時,是作為 I2C 的 slave 。 ::: <!-- :::info note: Arduino 沒有 I2C ,只有**2 wire serial interface(TWI)** ,但是這個TWI**相容於飛利浦的I2C協定**。詳見 [ATmega328P datasheet](http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf) p.260。 ::: --> ## LAB1 * 實驗目標:利用I2C進行Arduino間通訊 * schematic: ![](https://lh3.googleusercontent.com/Zuw2QyEtARMvNPyQhm72J0vKZbImM-SgRYTSvgxM_vK2aZaJSFz80pgbLX-CxtcEfyTvyur7rJBPvsqy19RRLYB-49Q0CsMxrd2Ygr1VRxxlyDRu8R2J_v2MvzWFI_iLIxEEUv-ppXdPGpPDfU0j5hzEeOyPlAZy78A-5by_OYQgobjxNRHDdEkDBpoaGpu3vdg3qsbXvBQihFtwOCf9cUvcYH26-bDkTCXM_WvvChB7QyY-vsmyhk_bJTb36AbqxnTcxlTY392h-PM0fRj0Sv-d5aXFYoxPgee8KlnGzP2yVS5E0xQfTRMcWl04polf8nYHATMgbF2JqHKa_b2o5kra9LAID0sARbarG42-hMdeFmz-Y_EnAefclJ0jOMWV3S7WaRizZG3JBXi9KDz66GjlzuwSrk7w2ogbBAHqfAJGeyDOWlcabNk8JON_REXswwdF4IHfYn72Yo7fF-O5FsaeGjgFrWl9erxqvgAhX6JknX6PYhSBMZt6uXwS_OgxCZ-tz6mntN5y27mjjVSvfZkjJ6pnVemA6m9ivJfQkWeDsSzEslzneN4CiHhauXeeM1Glly42qNm973rxCADrB1KYeSR2--4ym61XbOYuDz1NEWU0bUuCyS3X95I8NH7w7eiEccBbQYGaPRd74r5GOuxTepcNqMTf1kXbydyBhvvOHbFT1pSXxrtT=w941-h740-no) * master 把串口收到的資料,發送給 slave: ![](https://i.imgur.com/DlWNGZv.png) * slave 端直接處理接收回來的資料: ![](https://i.imgur.com/jZSH5V9.png) :::warning 若使用的 Arduino IDE 版本不能同時開兩個 Serial Monitor,請[點此](http://ttssh2.osdn.jp/)下載Tera Term後,點選設定做為第二個Serial Monitor。 使用方法:開啟Tera Term後,點選**設定** -->**連接埠** -->**更改端口與鮑率** ::: # Arduino講義:LCD ## LCD介紹 * 目前市面上的 LCD 模組可分文字型及繪圖型兩種。文字型 LCD 模組常見的規格有16 字x1 行,20 字x1 行,40 字x1 行,16 字x2 行,20 字x2 行,40 字x2行等多種。 * 文字型 LCD 顯示器內部具有字元產生器,因此可以接受 ASCII 字元碼,並將字元顯示在 LCD 上。 ## LCD架構 * LCD 模組的結構如圖所示,由 LCD 控制器、LCD 驅動器及 LCD 顯示器所組成。目前市售 LCD 模組所採用的 LCD 控制器都相容,使用方法也相同,因此幾乎所有的 LCD 模組都具有相同的控制方法。 ## I2C 16x2 LCD介紹 ![](https://i.imgur.com/AOFuvA4.png) * SDA – 接 Arduino 的 Analog Pin 4 (Arduino Mega 為 Pin 20) * SCL – 接 Arduino 的 Analog Pin 5 (Arduino Mega 為 Pin 21) * GND – 接 GND * VCC – 接 +5V ## LCD接法 ![](https://i.imgur.com/1YCyEvb.png) ## 學習使用LCD貼出字串 * LCD I2C Libraries下載:[here](https://drive.google.com/file/d/11hV6xfWycVe5Hg2bahq_UgWgoPMLBCK9/view?usp=sharing) * Keypad Libraries下載:[here](https://drive.google.com/file/d/1mnzf--VuktjYytxyOUm0J5sxz0J_YV6g/view?usp=sharing) --> 解壓縮後將資料夾放進Arduino libraries當中 * code: ![](https://i.imgur.com/VnLFbL9.png) ## LAB2 * 實驗目標:將上面的字串改成自己的學號,使其以如下影片的跑馬燈方式繞行。 * #### LiquidCrystal_I2C: | 函數 | 作用 | | --- | --- | | lcd.begin(cols, rows); | 定義LCD的長寬(n列×n行) | | lcd.clear() | 清空LCD | | lcd.setCursor(col, row); | 設定輸入值起始位置 | | lcd.print(data); | 在螢幕上顯示資料 | | lcd.scrollDisplayRight(); | 將畫面向右捲動 | | lcd.scrollDisplayLeft(); | 將畫面向左捲動 | * 參考影片: <iframe width="800" height="600" src="https://www.youtube.com/embed/5w0y1xAFMtc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ## LAB3 ### 簡易計算機 * 實驗目標:利用薄膜鍵盤與LCD實現簡易計算機 * 實驗要求: * A 鍵為加號、B 鍵為減號、C 為乘號、D 為除號、# 為等於、* 為清除鍵。 * 由薄膜鍵盤輸入數字後,LCD 第一列顯示運算式,第二列顯示等號與運算結果。 * 示範影片: <iframe width="800" height="600" src="https://www.youtube.com/embed/-bGQgrrkhio" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ## LAB4 ### 四則運算計算機 * 實驗目標:加強計算機的功能,使其能進行四則運算 * 示範影片: <iframe width="800" height="600" src="https://www.youtube.com/embed/6is9SvDOb7o" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ### 加分LAB1 - 實驗目的:在LAB4電算機加上括號以及累加的功能,使其更完整 - 實驗要求: * A 鍵為加號、B 鍵為乘號、C 為左括號、D 為右括號、# 為等於、* 為清除鍵。 * 增加累加功能 - 示範影片:<iframe width="956" height="538" src="https://www.youtube.com/embed/CLHd56h99rY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> ### 加分LAB2 - 實驗目的:以I2C實現master端與兩個slave端的溝通 - 實驗目標:在master端設定讀取鍵盤並將訊號傳至LCD以及另一台arduino以顯示在Serial monitor上。 - Schematic:請參照I2C與GPIO講義自行接腳。 * 參考: <iframe width="600" height="400" src="https://www.youtube.com/embed/BRSA_OBHWZI" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> * master ![](https://i.imgur.com/hhEft8d.png) ![](https://i.imgur.com/6vWFhvi.png) * Slave ![](https://i.imgur.com/qQb8GgQ.png) ## 課後問題 :::info Q1.簡述 I2C 如何藉由 SCL 與 SDA 傳送資料 ? Q2.上課的時候提到可以有多個master,請問若同時有兩個以上的master送出訊號會發生什麼事?並且描述該如何解決。 Q3.電算機為何總和超過 32767 時字串會溢位?如何解決 ? :::