**SSD1306控制OLED顯示螢幕**
===

###### tags: `ESP32 Tourist` `I2C` `ESP32` `MPU6050` `oled`
#### 圖片所示OLED面板內有一驅動晶片,為SSD1306,此晶片能夠支援6800、8080並串列傳輸匯流排介面,SPI和I2C串列傳輸匯流排介面,透過資料傳輸至內部GGDRAM中,根據GGDRAM中的資料,顯示於128*64的矩陣面板。
#### ESP32使用I2C來控制SSD1306來顯示圖形前,我們需要先了解如何寫入資料到SSD1306中,藉此來配置螢幕顯示參數和圖形點矩陣資料。
#### 本章節將跟大家分享如何使用ESP32 I2C通訊界面用於控制SSD1306和顯示OLED顯示螢幕的方法。
---
## **Feature**
* ### **Resolution** :
:::info
* #### 128 * 64 顯示面板.
:::
* ### **Power**:
::: info
* #### $V_{DD}$ : 1.65 $V$~3.3 $V$ , Power supply for IC logic. (用於內部數位電路邏輯運算電源供給)
* #### $V_{CC}$ : 7 $V$ ~ 15 $V$, Power supply for Panel driving.(用於面板驅動電源供給)
:::
* ### **Embedded 128 x 64 bit SRAM display buffer**
* ### **Pin selectable MCU Interfaces**:
:::info
#### SSD1306可以用於 8bit 6800/8080串並列匯流排傳輸、3線或4線SPI傳輸介面和I2C積體電路匯流排介面,本章節將著重於SSD1306 I2C應用的介紹。
* #### 8-bit 6800/8080-series parallel interface
* #### 3 /4 wire Serial Peripheral Interface
* #### "**I2C Interface**"
:::
* ### **Embedded 128 x 64 bit SRAM display buffer**
---
## **SSD1306 Block Diagram 方塊圖**

##### <center>圖片來源: SSD1306 Datasheet</center>
:::info
#### 藉由SSD1306的方塊圖,可以發現其內部有MCU在控制面板驅動的工作,MCU可藉由$D_0$ ~$D_7$來獲取命令的指令以及顯示於面板的點矩陣資料。
#### 在I2C傳輸會用到$D_0$至$D_3$接腳,用於I2C資料傳輸($SCL$、$SDA_{in}$、$SDA_{out}$).
#### BS0 ~ BS2 可選擇 SSD1306的通訊介面,如6800/8080、SPI、I2C.
:::
## **BS[0:2]選擇SSD1306傳輸介面**

##### <center>圖片來源: SSD1306 Datasheet</center>
:::info
#### RES# 為復位腳位
#### 以上為I2C回會用到的對外(輸入、輸出)接腳
:::

##### <center>圖片來源: SSD1306 Datasheet</center>
---
## **SSD1306接腳配置**
#### 綜合以上接腳資訊,我們將SSD1306接腳配置以下圖為基準:

##### <center>圖片來源: SSD1306 Datasheet</center>
:::info
#### $D_0$: I2C SCL接腳
#### $D_1$: I2C $SDA_{in}$接腳
#### $D_2$: I2C $SDA_{out}$接腳
#### D/C#: 選擇Slave address SA0配置.
#### RES#: 復位接腳,電壓準位保持高準位則重置SSD1306.
#### 其他Tie LOW
:::
## **SSD1306 for I2C Interface**
#### $SA0$接腳可以配置SSD1306在I2C的Slave address,形式如下圖$b_1$為$SA0$
#### $SA0$配置為1,則Slave為0x3D、配置為0,則為0x3C.
#### R/W# 則代表此在I2C匯流排中是用於寫入至bit[1:7]的slave還是從bit[1:7]的slave讀取資料,寫入(0)、讀取(1).

##### <center>圖片來源: SSD1306 Datasheet</center>
---
## **I2C通訊**
#### I2C通訊方式,我們須了解ESP32當Master時,我們要給SSD1306的資料格式:

##### <center>圖片來源: SSD1306 Datasheet</center>
:::info
#### ESP32作為I2C Master時,若想要與SSD1306發出命令,或寫入資料到GGDRAM時,我們需要根據上圖規範來送出Slave Address、R/W#、D/C#還有命令或者是資料位元組,藉此控制SSD1306來驅動128*64 Oled面板.
#### Slave Address: SSD1306提供固定bit[2:7]為故定位址,bit[1]為SA0,使用者根據SA0來改變SSD1306 Slave Address.
#### bit0(R/W#)則控制SSD1306是要寫入此資料至內部寄存器,還是從內部寄存器讀取資料.
:::
---
## **SSD1306 Command Decoder**
#### 根據SSD1306方塊圖所示,藉由MCU Interface D/C#訊號輸入,可決定此資料是要做為Cammand還是將此資料放置到GGDRAM用於面板顯示,如果D/C#設置為1為Data mode,0為Command mode.
#### 藉由Cammand模式,我們可以用來配置SSD1306的工作行為.
#### 在下一章節,我們將實作ESP32控制SSD1306的程式,將會介紹重要的Command來配置SSD1306用於OLED面板顯示的初始化。
---
## **SSD1306 Graphic Display Data RAM(GGDRAM)**
#### SSD1306藉由GGDRAM用於儲存顯示面板要顯示的資料.

##### <center>圖片來源: SSD1306 Datasheet</center>
#### 內部分別儲存了Page[0:7]和SEG[0:127]的資料.
#### 每個Page分別儲存了$D_O$至$D_7$的資料,用於顯示第SEG行的8列像素.
## **Ex. Page2資料分布**
#### 在Page2中,沿著y軸方向由高至低分別為8個像素點的8bit像素資訊,沿著x軸方向為COL[0:127],所以想要讓COL0全亮,我們將起始定位Page2及COL0寫入0xff就可以了。

##### <center>圖片來源: SSD1306 Datasheet</center>
---
## **Memory Addressing Mode設定寫入資料的起始位置**
### COL : 在每一個獨立的Page中,有COL[0:127]可以寫入(0、1),0為暗、1為顯示
### PAGE : 128 * 64 矩陣面板有Page[0:7]可以讀寫資料,每個Page由低到高可配置8個像素點的資料(8bit),由上圖所示。


##### <center>圖片來源: SSD1306 Datasheet</center>
:::info
#### 驅動面板顯示像素時,分別要設置COL的初始位置和Page初始位置,所以我們需要用指令來寫入COL的初始位置和Page初始位置資訊,在COL中,有2個命令用來指定COL的初始位置,分別是0x00 ~ 0x0f來處理8位元中的低4位元資料,0x10 ~ 0x1f來指定高四位元資料。
#### ex. 我們指定COL由0~127中的 0100 0010開始,地COL66開始寫入資料.
#### 下達命令: {(0100 0010b& ffff 0000b) >> 4} | 0x00 指定低4位元
#### 下達命令: (0100 0010b& ffff 0000b) | 0x00 指定高4位元
#### COL配置完資料後,並不會到下一個Page寫入資料,我們如果需要切換到下一個Page寫入資料的指令。
#### 命令0x0b為第Page0,到Page1則寫入(0x0b + 1),依此類推Pagei為(0x0b+i).
:::
---
## **Horizontal addressing mode**

##### <center>圖片來源: SSD1306 Datasheet</center>
#### 在此模式下,當資料寫到COL的最後一個,他會自動跳到下一列COL0開始寫入資料.
---
### 藉由上述介紹我們可以初步得到該怎麼用I2C來控制SSD1306,下一章節我們將來討論ESP32如何發出Command和寫入資料至GGDRAM,藉此驅動0.96吋Oled面板。