---
# System prepended metadata

title: '[5] Arduino講義：SPI、I²C<!--、藍芽模組(UART)~-->'
tags: [單晶片助教]

---

---
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一起輸入再一起送出)，若輸入值與密碼相同則印出     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
    ...


:::