--- tags: 單晶片助教 --- # [5] Arduino講義:SPI、I²C<!--、藍芽模組(UART)~--> ## 課程大綱 [ToC] # Serial communication-UART/I²C/SPI/(GPIO) ![](https://i.imgur.com/1z7idwK.png) # Arduino講義:Serial Communication (UART/SPI/I²C) ## Intoduction of UART * 全文為 **Universal Asynchronous Receiver/Transmitter** ,即**通用非同步收發傳輸器**,是一種硬體介面。 * 資料傳輸硬體會根據 **是否提供時脈訊號** 區分為 1. 同步傳輸 (Synchronous Receiver/Transmitter) 2. 非同步傳輸 (Asynchronous Receiver/Transmitter) 同時根據 **資料流向** 被區分為 1. 單工 (simplex) 2. 半雙工 (half-duplex) 3. 雙工 (duplex) * 而UART是一種非同步收發傳輸器,其特性為 * 全雙工 * 串列 * 非同步 * [相關動畫](http://wiki.csie.ncku.edu.tw/embedded/USART_DataTransmission.gif) --- ### 單工、半雙工與雙工 | 單工 | 半雙工 | 全雙工 | | -------- | -------- | -------- | |![](https://i.imgur.com/NkVAamw.jpg)|![](https://i.imgur.com/rICbdJp.jpg) |![](https://i.imgur.com/RBbG5hN.jpg)| |只支持信號在一個方向上傳輸(正向或反向),任何時候不能改變訊號的方向。 EX:計算機和印表機之間的通信、B.B.Call。 | 允許信號在兩個方向上傳輸,但同一時間只允許信號在一個信道上單向傳輸。EX:傳統的對講機。 |允許數據同時在兩個方向上傳輸,即有兩個信道,因此允許同時進行雙向傳輸。 EX:電話、手機、RS232。 | * 原文網址:https://kknews.cc/zh-tw/other/y2av3rj.html --- ### 非同步 (Asynchronous) v.s 同步 (Synchronous) * 非同步 ![](https://i.imgur.com/gvCSISx.jpg) * 雙方有各自的時脈, 在傳送資料時插入額外資訊,表示資料起始、結束。優點是設定時間短、硬體成本低、機器時脈不同也能傳資料,缺點是單次傳輸的資料量較少。 * EX : RS-232 (實現方式簡單低廉)、 RS-422 (較長距離的傳輸)、RS-485 (較多的裝置連接數目)。 * 同步 ![](https://i.imgur.com/cDlmMqx.jpg) * 雙方共用時脈(一次只做一件事),額外提供時脈訊號,使兩端機器在溝通時能夠藉此同步收發資料。比起非同步傳輸,同步傳輸不需要 start/stop bit ,因此能夠一次傳較多的資料。 * EX : I2C 、 SPI 。 --- ### 串列 v.s 並列 * 串列 ![](https://i.imgur.com/iR4wqGW.jpg) * 一次傳送一個 bit,傳輸速率較慢、成本較低、可遠距離傳輸。 * EX :滑鼠、鍵盤、USB、HDMI、RS-232 介面。 * 並列 ![](https://i.imgur.com/WqHNHVN.jpg) * 一次傳送多個 bit,傳輸速率快、成本高、易受雜訊干擾,僅限短距離使用。 * EX :25Pin D-Type印表機、顯卡PCI介面。 <!-- * 注意:並列傳輸的線路較多,但傳輸速度不一定比較快(因為接收端要同時將傳進來的資料整合及排列,虛耗額外的位元及處理時間)--> [參考資料](https://zh.wikipedia.org/wiki/%E6%B3%A2%E7%89%B9%E7%8E%87) --- ## Introduction of SPI * SPI 是 Serial Peripheral Interface的縮寫 ,中文叫做序列周邊介面 * 一種主從式架構的同步資料協定,用於短距離通訊 * SPI 裝置之間使用<font color="red">全雙工模式通訊</font>,包含一個<font color="red">主機(master)</font>和一個或多個<font color="red">從機(slave)</font> * **SPI** : <font color="red"> 全雙工、串列、同步</font> * 主要用以連接 ADC、DAC、EEPROM、通訊傳輸 IC...等週邊晶片 |模組名|模組外觀| |:--:|:--:| |MCP3008 ADC|![](https://i.imgur.com/EYUwaHv.png)| |PCM1794 DAC|![](https://imgur.com/1YNCARy.png)| |ILI9341觸碰液晶螢幕|![](https://i.imgur.com/BMy7ItZ.png)| |ENC28J60網路擴展模組|![](https://i.imgur.com/Jw15bb3.png)| * [模組來源](https://www.taiwaniot.com.tw/) ### SPI 接腳名稱及意義 * Arduino Uno | 接腳名稱 | 腳位 | 說明 | | -------- | :--------:|--------| | MOSI (Master Output,Slave Input)|11| master 數據輸出,slave 數據輸入(主出從入)| | MISO (Master Input,Slave Output) |12| master 數據輸入,slave 數據輸出(主入從出)| | SCLK/SCK (Serial Clock)|13| 時脈信號,由 master 產生並控制(Clock) | | SS (Slave Selected) |10| LOW(低電位)時表示裝置可以與Master通訊(Enable)| * 其他 ![](https://i.imgur.com/GVeKrCM.png) * SPI 匯流排: * 單一主機對單一從機 ![](https://i.imgur.com/Icd0Jwy.png) * 單一主機對複合從機 主機將欲操作之從機選擇線拉低(SS to LOW),再分別透過 MOSI/MISO 啟動數據發送/接收。 ![](https://i.imgur.com/Hjxqgtj.png) * SPI優點有三,一是非常簡單的硬體介面,二是完整的傳輸位協定靈活性,訊息大小、內容、目的可任意選擇,三是slave裝置直接使用master裝置的clock,不需要精密的振盪器。 * SPI也有缺點,一是隨著連接裝置數的增加,線路也是要增加的,二是通常只支援一個主裝置。 #### 傳輸方式 * 當 Master 對 Slave 做 select 之後 (連接到該 slave 的 SS 拉 low), Master 開始送出 clock, 同時 Master 的資料 (MSB, 最高位元), 也由 shift register 推出,以在 MOSI 上維持住它的值,而 Slave 的資料也是在同一時間送到 MISO,說明了 SPI 是一個全雙工同步的訊號系統。 ![](https://i.imgur.com/3FOvziL.png) --- ## Data Modes * CPOL(Clock Polarity) * 用來決定在空閒時,時脈(SCK)信號線上的電位是HIGH還是LOW * 寫入1時,時脈(SCLK)閒置時為HIGH;寫入0時,時脈(SCLK)閒置時為LOW。 write 1 ![](https://i.imgur.com/asip4a8.png) write 0 ![](https://i.imgur.com/tuS19Vb.png) | CPOL0 | Leading edge | Trailing edge | | -------- | --------| --------| | 0 | Rising | Falling | | 1 | Falling | Rising | ![](https://i.imgur.com/sttIhaD.jpg) * CPHA(Clock Phase) * 用來決定要在時脈(SCK)的前緣或後緣取樣 | CPHA0 | Leading edge | Trailing edge | | -------- | --------| --------| | 0 | Sample | Setup | | 1 | Setup | Sample | ### The Table of SPI Modes | SPI Mode | Conditions | Leading Edge |Trailing Edge| | -------- | --------| --------|--------| |0| CPOL=0, CPHA=0 | <font color="red">Sample (Rising)</font> | Setup (Falling)| |1| CPOL=0, CPHA=1 | Setup (Rising) | <font color="red">Sample (Falling)</font>| |2| CPOL=1, CPHA=0 | <font color="red">Sample (Falling)</font> | Setup (Rising)| |3| CPOL=1, CPHA=1 | Setup (Falling) |<font color="red">Sample (Rising)</font>| :::success 舉例:CPOL =0 表示 clock 原本在 low,CPHA =0 表示資料在第1個 edge 被讀取.  也就是 rising edge 被讀取。其他以此類推。 ::: {%youtube 4zx0s9ZKYZY %} <!-- * 平常使用 SPI Library 時,SPI Mode 預設值為0,SCLK 為4Mhz。 ``` c++= SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } ``` ### SPI Transfer Format with CPHA = 0 ![](https://i.imgur.com/br3jTsg.png) ### SPI Transfer Format with CPHA = 1 ![](https://i.imgur.com/uLrqhYw.png) --> --- ### 相關函數(記得include SPI.h喔~) | 函數 | 作用 | | -------- | -------- | | SPI.begin()| 通過將 SCK,MOSI 和 SS 設定為輸出,將 SCK 和 MOSI 設為LOW,SS 為HIGH來初始化 SPI 匯流排。| |SPI.end()|結束 SPI Bus| |SPI.setBitOrder(order)|設定數據在 SPI Bus 上傳送順序為低位元(`LSBFIRST`)優先或高位元(`MSBFIRST`)優先| |SPI.setClockDivider(divider)|設定 SPI 時脈的除數(Arduino硬體時脈為16Mhz),可用的分頻器為 2,4,8,16,32,64 或 128,預設設定為 SPI_CLOCK_DIV4| |SPI.transfer(val)|由 SPI 介面發送並接收 1 個 byte 資料| --- ## LAB1-1 * 實驗目的 :利用 SPI 進行 Arduino 間通訊,傳送 **Happy!** * Arduino UNO 內定 10,11,12,13 為 SPI 通信界面使用 * Pin 10 :SS chip select從設備致能信號,由主設備控制 * Pin 11 : MOSI 主設備數據輸出,從設備數據輸入 * Pin 12 : MISO 主設備數據輸入,從設備數據輸出 * Pin 13 : SCLK ,由主設備產生 * hint:[code參考連結](http://www.tastones.com/zh-tw/tutorial/arduino/arduino_serial_peripheral_interface/) * schematic ![](https://i.imgur.com/tJEPZp5.png) * 參考程式:Master example <!--https://imgur.com/aOMFjhi.png --> ```c++= #include <SPI.h> void setup (void) { Serial.begin(115200); digitalWrite(SS, HIGH); // 確保SS初始狀態為HIGH SPI.begin (); SPI.setClockDivider(SPI_CLOCK_DIV8);//設定時脈為16/8 = 2 Mhz } void loop (void) { char c; digitalWrite(SS, LOW); //開始與從機通訊 //SS pin為10 // 傳送字串 /* Do Something */ digitalWrite(SS, HIGH); // 關閉與從機的通訊 delay(2000); } ``` * Slave example <!--https://imgur.com/r3NicNc.png --> ```c++= #include <SPI.h> char buff [50]; volatile byte indx; volatile boolean process; void setup (void) { Serial.begin (115200); pinMode(MISO, OUTPUT); //設定主入從出 SPCR |= _BV(SPE); //開啟從機的SPI通訊 indx = 0; // buffer 裡頭為空 process = false; SPI.attachInterrupt(); //啟用中斷函式 } ISR (SPI_STC_vect){ //SPI中斷程序 byte c = SPDR; //從SPI Data Register獲取資料(byte) /* Do Something */ } void loop (void) { // 等待中斷函式回傳true /* Do Something */ } ``` <!-- #include <SPI.h> char buf [100]; volatile byte pos; volatile bool process_it; void setup (void) { Serial.begin (115200); SPCR |= bit (SPE); //開啟從機的SPI通訊 pinMode (MISO, OUTPUT); //設定主入從出 pos = 0; // buffer 裡頭為空 process_it = false; SPI.attachInterrupt(); //啟用中斷函式 } ISR (SPI_STC_vect) //SPI中斷程序 { byte c = SPDR; //從SPI Data Register獲取資料(byte) Do something process_it = true; } void loop (void) // 等待中斷函式回傳true { if (process_it) { Do something } } ``` --> * SPCR ![](https://imgur.com/Q5KZpPZ.png) * SPCR Register ![](https://i.imgur.com/enGoXKH.png) [1.相關暫存器程式碼參考資料](https://medium.com/%E9%96%B1%E7%9B%8A%E5%A6%82%E7%BE%8E/arduino-avr-18-spi-communication-9c9a6532a5ee) [2.參考資料](https://www.sparkfun.com/datasheets/Components/SMD/ATMega328.pdf) * ISR 介紹 [click here](http://programmermagazine.github.io/201407/htm/article1.html) * 參考結果 : {%youtube s6FiiVmn2TE %} <!-- :::info 關於中斷函式:[**點我**](http://coopermaa2nd.blogspot.tw/2011/04/attachinterrupt.html) ::: --> <!--## LAB1-2 * 實驗目標 :兩個Arduino都分別帶有一個LED和一個按鈕。按下一端的按鈕,使另一端的LED亮起,放開後熄滅, * 主機Arduino的LED可以通過從機Arduino的按鈕來控制 * 從機Arduino的LED可以通過主機Arduino的按鈕來控制 * 示範影片 : <iframe width="560" height="315" src="https://www.youtube.com/embed/W1SFkGn0vdQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>~~~~ * Master example: ```c++= #include<SPI.h> #define LED 7 #define buttonpin 2 int button; int x; void setup (void){ SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV8); //設定時脈為 16/8 = 2 Mhz digitalWrite(SS,HIGH); // 確保ss初始狀態為high Serial.begin(115200); pinMode(buttonpin,INPUT); pinMode(LED,OUTPUT); } void loop(void){ /* do something */ } ``` * Slave example ```c++= #include<SPI.h> #define LED 7 #define buttonpin 2 volatile boolean received; volatile byte Slavereceived; int button; int buttonvalue; void setup(){ Serial.begin(115200); SPCR |= bit (SPE); //開啟從機的SPI通訊 pinMode(MISO,OUTPUT); //主入從出 pinMode(buttonpin,INPUT); pinMode(LED,OUTPUT); received = false; SPI.attachInterrupt(); //啟用中斷函式 } ISR (SPI_STC_vect){ //SPI中斷程序 Slavereceived = SPDR; //從SPI Data Register獲取資料(byte) received = true; } void loop(){ if(received){ /* do something */ } } ``` <!--master code #include <SPI.h> #define button 2 int buttonvalue; int x; void setup() { digitalWrite(SS,HIGH); pinMode(button,INPUT); SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV8); } void loop() { byte Mastersend; buttonvalue=digitalRead(button); if(buttonvalue == HIGH) {x=1;} else {x=0;} digitalWrite(SS,LOW); Mastersend=x; SPI.transfer(Mastersend); digitalWrite(SS,HIGH); delay(10); // put your main code here, to run repeatedly: } slave code #include <SPI.h> #define LEDpin 7 volatile boolean received; volatile byte Slavereceived; void setup() { // put your setup code here, to run once: Serial.begin(115200); pinMode(LEDpin,OUTPUT); SPCR |= _BV(SPE); pinMode (MISO,OUTPUT); received = false; SPI.attachInterrupt(); } ISR(SPI_STC_vect) { Slavereceived = SPDR; received = true ; } void loop() { if(received) { if(Slavereceived==1) { digitalWrite(LEDpin,HIGH); Serial.println("Slave LED ON"); } else { digitalWrite(LEDpin,LOW); Serial.println("Slave LED OFF"); } ::: --> --- ## Introduction of I²C * I²為Inter-Interated Circuit的簡稱,中文名稱叫積體匯流排電路 * 一種串列通訊匯流排 * 主要應用在board-to-board,無法使用在長距離通訊上 * 被應用在各種控制架構上,Ex:系統管理匯流排、電源管理匯流排、智慧平台管理介面....等 ## I²C Bus ![](https://i.imgur.com/AV6kiJO.jpg) * I²C 使用兩條雙向 open-drain Line * SDA : Serial Data Line, holds Data or address signal * SCL : Serial Clock Line, holds Clock signal * 導通時是低電位,不導通時float,所以利用電阻(pullup resistor)將電位拉高。常用電壓為 +5 V or +3.3 V * IO 必須是 open drain (or open collector in TTL) * bus 為 wired-AND configuration ## Timing Diagram ![](https://i.imgur.com/7LnGdCG.jpg) * 當未傳輸時(IDLE 狀態) ,SCL 和 SDA 都會維持在 high 電位 * SCL 為 high 時,表示 SDA 上的資料為有效,此時 SDA 的值不能改變,以確保可以收到到正確的 SDA 狀態 * SCL 為 low 時,SDA 的狀態可以改變 * 當 SCL 為 high 時,如果 SDA 變動,只有兩種情況: * SDA由 "1" 變 "0" ---> START * SDA由 "0" 變 "1" ---> STOP ![](https://i.imgur.com/3J27FVg.jpg) ## Arbitration procedure of two masters ![](https://i.imgur.com/afrInhu.jpg) * 避免同時間有 2個以上的master (不同資料) 控制 I²C * 利用 bus wired-AND 的機制,若 Master 1 欲將 SDA logic 拉高,最後卻 SDA logic 為低,代表仲裁輸了,該 master 立即停止動作 * 輸掉的 master 寧可先放棄 (Back Off) 等候,到看見停止狀態的出現才開始傳送 {%youtube u62_Rjd5oMY %} --- ## Lab2-1: * 接線圖: ![](https://i.imgur.com/AEQGH9M.jpg) ![](https://i.imgur.com/i9OD36U.jpg) * Mirotek 1602 I²C 模組說明: * 是一個16字元乘2行LCD顯示螢幕,帶有藍色背景和白色背光 * 內置Arduino IIC / I2C接口 * 實驗影片: {%youtube 3t7jcdBhbDE %} * 程式範例: * [下載LCD_I2C模組程式庫](https://github.com/johnrickman/LiquidCrystal_I2C) * [指令參考](http://maker.tn.edu.tw/modules/tad_book3/page.php?tbsn=16&tbdsn=284) ```c++= #include <Wire.h> // I2C程式庫 #include <LiquidCrystal_I2C.h> // LCD_I2C模組程式庫 LiquidCrystal_I2C lcd(0x27, 16, 2);// LCD I2C位址,默認為0x27或0x3F,依據背板的晶片不同而有差異,16、2為LCD顯示器大小。 const int sw_up = 2; //按鈕1 const int sw_down = 3; //按鈕2 int count; void setup() { lcd.init(); lcd.backlight(); pinMode(13, OUTPUT); digitalWrite(13, HIGH);//為了下拉電阻設置5v pinMode(sw_up, INPUT_PULLUP); //內建上拉電阻 pinMode(sw_down,INPUT); } void loop() { bool swstate_up = digitalRead(sw_up); bool swstate_down = digitalRead(sw_down); if(swstate_up==LOW){ /* Do something */ } else if(swstate_down==HIGH){ /* Do something */ } lcd.setCursor(5,0);//5是空五格,0是第一行 /* Do something */ } ``` ## Bonus * 實驗目標: * title為組別人數閃爍3下,接著螢幕顯示停留在Use Serial Monitor,進入Serial Monitor,分別輸入組員號碼,lcd將顯示該組員生日 * Hint: lcd.noBacklight() 為關閉背光的指令 * 範例影片 {%youtube H4_qAhLU6ck %} * 參考程式: ```c++= #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // 設定 LCD I2C 位址 void setup() { /* do something */ Serial.begin(9600); for(int i = 0; i < 3; i++) { /* do something // 閃爍二次 */ } /* do something */ } void loop() { if(Serial.available()){ /* do something */ switch(num){ /* do something */ } } } ``` --- <!--## Bluetooth * 藍芽模組 HC-05、HC-06,使用 UART 介面與 Ardunio 溝通。 * 藍芽模組也可以視為一塊 MCU 並且可以透過 UART 介面進行設定。 * 設定方式: * 透過 USB to UART 轉換電路 ,從電腦開啟 Serial Port 做寫入動作。 * 利用 Ardunio uno 開發板本身就有的 IC 來做轉換即可寫入 AT 指令。 #### 藍芽開發環境設定: * 接線: | Arduino | 藍芽模組 | 備註 | | -------- | -------- | -------- | | 5V | VCC |注意電源不可接錯 | | GND | GND |注意電源不可接錯 | | RXD(pin10)| TXD | | | TXD(pin11)| RXD | | ![](https://i.imgur.com/pDl8ZEn.png) ![](https://i.imgur.com/IazhLIr.png) * 程式碼: ```c++= #include <SoftwareSerial.h> SoftwareSerial BTSerial(10, 11); // 宣告10腳位為Arduino的RX 、11為Arduino的 TX char val; //儲存接受到的資料變數 void setup() { Serial.begin(9600); BTSerial.begin(38400); //注意,HC-06要設定成9600(bps) } void loop() { // 若收到「序列埠監控視窗」的資料,則送到藍牙模組 if (Serial.available()) { val=Serial.read(); BTSerial.print(val); } // 若收到藍牙模組的資料,則送到「序列埠監控視窗」 if (BTSerial.available()) { val=BTSerial.read(); Serial.print(val); } } ```--> <!--### 進入AT模式的方法說明: 注意:若要進入AT模式則,要先確保不能有任何裝置與藍芽模組連線。 以下分為HC-05與HC-06說明: ### HC-05: * **同時按住紅框鈕及接上 5v 即可進入 AT 模式。** 在尚未與裝置連線之前,HC-05板子上的LED快速閃爍,成功進入AT模式後,LED將兩秒閃爍一次。 ![](https://i.imgur.com/K11ITRH.png) * **Serial Port設定:** * 打開 Serial Port。 * Serial Monitor 的鮑率選**9600**,另外一個選項要選 **NL&CR**,即可下 AT 指令。 * 輸入 AT 指令第一次會出現 ERROR:(0),第二次輸入 AT 出現 OK ,即可進入 AT 模式。 * 詳細AT指令請參考以下AT指令表。 ![](https://i.imgur.com/2QKLsch.png) ### HC-06: * HC-06與任何裝置連線之前,只要有通電,都是在AT模式的狀態。因此要進入AT模式,只須**確保HC-06沒有與其他裝置相連即可。** * **Serial Port設定:** * 打開 Serial Port。 * Serial Monitor 的鮑率選**9600**,另外一個選項要選 **沒有結尾行**,即可下 AT 指令。 * 輸入 AT 出現 OK ,即可進入 AT 模式。 * 詳細AT指令請參考以下AT指令表。 ![](https://i.imgur.com/S2VfocG.png)--> <!--### AT指令表: * **AT指令版本HC-05:** | 指令 | 序列埠回應 | 功能 | | -------- | -------- | -------- | | AT | OK | 確認藍芽與序列埠溝通正常 | |AT+UART? | +UART:XXXXX,0,0| 得知目前Baud rate設定 | |AT+ADDR? | +ADDR:98d3:b1:fd6ece| 查詢address | | AT+VERSION| 版本資訊 | 查看韌體版本 | | AT + NAME=XXXX | OK | 設定藍芽名稱 | | AT + PSWD=XXXX | OK | 設定密碼 | | AT + UART=38400,0,0 (鮑率 , 停止位元 , 同位位元) | OK |設定鮑率為38400 | | AT+ROLE=1 | OK | 設定主動模式 | | AT+BIND=XXXXXXXX | OK | 綁定藍芽位置 | | AT+CMODE=0 | OK | 指定藍芽位置連接模式 | | AT+RESET | OK | 重啟藍牙 | * **AT指令版本HC-06** : | 指令 | 序列埠回應 | 功能 | | -------- | -------- | -------- | | AT | OK | 確認藍芽與序列埠溝通正常 | | AT+VERSION| 版本資訊 | 查看韌體版本 | | AT+NAMEXXX | OKsetname | 設定藍芽名稱 | |AT+PINXXXX | OKsetPIN | 設定密碼 |--> <!--### 將兩個藍芽模組連接: * **slave 端設定:** * 設定鮑率 * 連接模式 * 設定模組的角色 * 位置查詢 * **master 端設定:** * 設定鮑率 * 連接模式 * 設定模組的角色 * 指定要連哪個位置 * 請先確認不是在AT模式,在AT模式將無法配對。 * 通訊時,baud rate 也要設為一樣。 ### 若顯示出現亂碼: * 進入AT模式設定更改鮑率設定。 * 確認Serial port 介面是否正確設定。 * 確認程式藍芽連線速率是否正確設定。 --- # Lab2-1: ### 藍芽實作 * 實驗目的:學習使用手機搭配藍芽模組 * 實驗目標:透過藍芽來控制led明滅燈。 * 輸入1:LED ON。 * 輸入0:LED OFF。 * 輸入其他:LED 閃爍2次。 * 結果: {%youtube TzQHrURN2dI %}--> <!--### Lab2-2: ### 藍芽實作 * 實驗目的:學習使用手機搭配藍芽模組來控制LED跑馬燈。 * 實驗目標:使用五顆LED燈與藍芽模組, 輸入0:停止目前動作。(除非輸入0,否則以下動作必須不斷重複執行) 輸入1:LED跑馬燈。 輸入2:LED跑馬燈每次間隔一顆暗的。 輸入3:LED由右至左依次點亮,由左至右依次熄滅。 輸入4:LED全亮。 輸入其他:LED 全部閃爍。 * 結果: {%youtube oRaqOo-qGeU %} ## Bonus: ### Bonus 1:藍芽控制碼錶 * 實驗目的:使用手機搭配藍芽模組以及四位七段顯示器,實現藍芽控制碼錶。 * 實驗目標:設計一個四位數的碼錶,第四位為小數,按下1則計時開始/暫停,按下0則計時歸0。 * 結果: {%youtube 9kJ4dHWSlLI %} ### Bonus 2:藍芽密碼鎖 * 實驗目的:使用手機搭配藍芽及密碼鎖函式庫,完善密碼鎖功能。 * 實驗目標:擁有以下功能, 1.自訂一個密碼(如1234),使用手機來輸入值,輸入完成按送出,之後再輸入A按送出代表輸入密碼(也可以數字與A一起輸入再一起送出),若輸入值與密碼相同則印出 Unlock!,錯誤則印出Wrong passwords! 2.按A為送出輸入的值,按B為重設密碼。 3.顯示剩餘可錯誤次數,若連續錯誤3次後印出需等待10秒才能再次輸入。 * 參考結果: {%youtube IeFvISNWMVI %} ::: --> ## 課後問題 (2個) :::info * **Q1.** 請簡述 SPI通訊涉及到哪些信號線?它們分別是什麼作用?<!--SPI通訊包括四條信號線:SCK(時鐘線)、MOSI(主端數據輸出、從端數據輸入)、MISO(主端數據輸入、從端數據輸出)和SS/CS(從端選擇/片選)。--> * **Q2.** 請簡述 全雙工、半雙工名詞解釋<!--全雙工:(Full Duplex)是指在發送數據的同時也能夠接收數據,兩者同步進行 半雙工:(Half Duplex),所謂半雙工是指一段時間內,只有一種動作發生,發或者收。--> * **Q3.** 在I2C裡,什麼是ACK(Acknowledge)和NACK(Not Acknowledge)位? <!--* **Q3.** 請說明 **HC-05** 作為 **master** 以及 **slave** 的功用是什麼?--> ::: :::success ## 作業繳交格式 **W5結報_第XX組.zip** 壓縮檔裡包含: 1.W(週數)結報.pdf 2.資料夾:W(週數) Lab1.ino Lab2.ino ... :::