# STM32F411 開發板 教學
## **STM32F411 開發板簡介**
STM32F411 開發板基於 **STM32F411** 微控制器(Cortex-M4 內核,最高時脈 100MHz),適用於高效能嵌入式應用。它具備豐富的 **GPIO、UART、SPI、I2C、ADC、PWM** 及 **USB OTG**,並支援 **DMA** 和 **FPU**,適合信號處理與控制應用。開發可使用 **STM32CubeIDE、Keil、IAR**,並透過 **HAL 庫或 LL 庫** 簡化開發流程。適用於 **IoT、數據處理、機器學習及低功耗應用**。
# Topic-1 GPIO
## GPIO 簡介
### 什麼是GPIO(general purpose input output)
GPIO代表通用輸入/輸出。大多數 Pin 腳都有專用用途,例如向某個元件發送訊號, GPIO腳位(Pin) 的功能可以自訂並且由軟體控制。
## 功能模式:
#### General Purpose(通用功能):
一般的控制模式,由使用者透過程式碼直接控制該 Pin 腳要輸出 High 還是 Low (輸出功能),也可以由程式碼直接讀取該 Pin 腳的電壓準位(輸入功能)。
#### Alternate Function(複用功能):
使用該 Pin 腳所擁有的特殊功能(例如:UART、PWM、I2C),使用者沒辦法用程式碼直接控制該 Pin 腳的 High 或 Low,而是由所指定之特殊功能暫存器(control register)來控制。
## 輸出電路組態:
#### Push-Pull(推挽):
由一對互補的電晶體組成,可以直接輸出 High 或 Low 電位。
#### Open-Drain(汲極開路):
FET 版的 Open-Collector。由一個 N 通道 FET 構成,只能輸出 Low(GND) 或 Open(開路)狀態,因此要外加一上拉電阻(pull-up resistor)才能使其輸出的 Open 狀態變成 High,而 High 狀態的實際電壓根據上拉電阻所接的電源而定,可以高或低於 IC 本身的電源電壓。而產生線接及閘(Wired AND)的特性。
## 輸入模式:
#### Analog(類比):
使用 ADC 讀取類比電壓數值時。需要分配爲 ADC Channel 的 Pin 腳上才能正常使用。
#### Floating(浮接):
一般的讀取模式。若不啓用 STM32 內部的上/下拉電阻,使用時外部電路應要有上/下拉電阻,否則該 Pin 腳浮接時可能無法正確讀值,使讀入值為亂碼。
## Demo (LED, 蜂鳴器, 按鍵輸入)
:::success
功能:讓LED燈按照順序跑動,按鈕按下時跑馬燈會產生變化且蜂鳴器發出聲響
:::
{%youtube P3TdjOzSB_E%}
## STM32CubeIDE設定
### 點選 File -> New -> STM32 Project

---
### 選取開發板型號:NUCLEO-F411RE

---
### 建立專案

---
### Pinout -> Clear Pinouts 移除用不到的Pin腳


---
### 設定 RCC 時鐘源

---
### Debug 設定

---
### Pin腳啟用
**按鈕1、2**:
PB0、PB1 (GPIO_Input)
**蜂鳴器**:
PC4 (GPIO_Output)
**LED**:
PA4、PA5、PA6、PA7 (GPIO_Output)

NUCLEO-F411RE Pinout

接線

---
### Pin腳設定

---
### 點擊分開其他初始化設定

### 設置完成 點選齒輪生成程式碼

---
### 沙盒模式
:::info
STM32的沙盒模式(Sandbox Mode)是一種安全防護機制,用於將應用程式執行環境隔離,防止不受信任的程式碼對系統造成損害。此模式常見於嵌入式系統中,特別是在執行敏感操作或連接網絡時。透過沙盒模式,系統能夠限制應用程式訪問硬體、記憶體或外部設備的權限,有效防止漏洞被惡意利用。此外,STM32還可以透過硬體的安全特性(如記憶體保護單元MPU)來實現沙盒環境,保障系統的穩定性與安全性。
:::
## 程式碼
::: spoiler main.c
{%gist /shiaw87/3353f55b1fdb1e3416f2b60e6e445b22 %}
:::
---
# Topic-2 Interrput TIM
## 定時器(Timer)
通常用於測量時間間隔,從零開始向上計數以測量經過的時間的計時器,它是一種從指定時間間隔開始倒計時並用於產生時間延遲的設備,例如秒錶
### 定時器用法
Interrupt:
TIMER的應用多,微處理機中常見的中斷(interrupt)讓CPU定時做一件事情,多久做一次的時間要告訴它,所以我們需要Timer。
Delay:
產生延遲會需要等待幾秒鐘,這時候就需要Timer來計算delay的時間
PWM:
產生一個週期性的信號,例如可供馬達控制

### STM32 定時器(Timer)計數週期 T 的計算公式

此公式用來計算 STM32 定時器的定時週期,也就是計時器從 0 計數到 ARR(自動重裝載值)後發生一次溢出的時間。
### Prescaler (PSC)
預分頻器值
### Period (ARR)
自動重裝載值
### PCLK 時鐘頻率
計時器的輸入時鐘頻率
### T
定時器週期( 0 到 ARR 需要的時間)
### 舉例:
設定 1 秒計時
假設:
PCLK1(APB1 時鐘)= 72MHz
PSC = 7199 (分頻 7200)
ARR = 9999 (計數範圍 0 ~ 9999)

定時器每 1 秒 產生一次溢出,觸發中斷。
### 脈波寬度調變Pulse width modulation(PWM)
PWM是將類比信號轉換為脈波,一般轉換後脈波的週期固定,但脈波的占空比會依類比信號的大小而改變。
在使用 PWM 時我們會需要控制兩種參數:頻率與 Duty Cycle(佔空比)。頻率的部分和 Timer 一樣,由 PSC 與 ARR 的值來設定,而 Duty Cycle 則由 CCR (Capture/Compare Register,捕獲/比較暫存器)來指定。
#### 佔空比(Duty Cycle)
佔空比是指輸出的PWM當中,高電位保持的時間與整個週期之比。可以看到下圖當中最上方為50%的佔空比,也就是高電位與低電位各佔50%。


Timer使用PWM輸出模式時,CNT計數值大於CCRx的時候會輸出高電位,相反的低於CCRx時則是低電位。
ARR : 主要控制的是頻率,也就是綠框的部分
CCRx : 主要為控制佔空比,也就是藍框的部分
求Duty Cycle:

## 中斷(Interrupt)
在嵌入式系統中,中斷是一個機制,用於處理各種外部事件或內部條件的發生。這些事件可以是來自硬體設備的訊號,例如按鈕按下、計時器計時完成,或是軟體內部的條件,如:數據溢出或滿足一些特定條件。當一個中斷事件發生時,MCU會中斷正在執行的程式,轉而執行相應的中斷服務程式(Interrupt Service Routine,ISR),處理該事件,然後繼續執行原來的程式。
### 中斷的類型
MCU支援多種不同類型的中斷,以下是一些常見的中斷類型:
外部中斷: 由外部硬體觸發的中斷,例如按鈕按下、感測器觸發等。
定時器中斷: 由MCU內部定時器計時完成時觸發,用於執行定時任務。
UART中斷: 用於處理串列通信中的數據接收或傳送完成事件。
ADC中斷: 用於類比數位轉換(ADC)完成時,通常用於讀取模擬數據。
內部中斷: 由MCU內部條件觸發的中斷,例如除以零的錯誤。
看門狗定時器中斷: 用於檢測系統錯誤並執行相應的動作。
### 中斷優先級
當多個中斷事件同時發生時,MCU需要確定哪個中斷應該首先處理。這就涉及到中斷優先級的概念。每個中斷都有一個優先級,通常是數字越小,優先級越高。當多個中斷事件同時發生時,MCU會首先處理優先級最高的中斷,然後再處理其他中斷,以此類推。
## 實作Demo
{%youtube Aiw47c68cww %}
### STM32CubeIDE設定
### PIN 設定

---
### GPIO設定
PA5 EXIT5 中斷開啟

---
PA7 output

---
### RCC設定

---
### SYS設定

---
### TIM設定
開啟tim3 pwn設定頻率2kHz

---
開啟tim4 設定每毫秒跑一次

---
### NVIC 設定

---
### Clock設定

---
### 外設檔案分開+生成


---
### Nucleo_Pinou

---
### 電路圖

---
### PWM 實作
### 流程圖
```mermaid
flowchart TD
A(開始)
B[初始化計時器]
C[進入主迴圈]
subgraph LED 亮度控制
D[pwm_led 函數]
D1{flag_led == 1?}
D2[調整 duty_num]
D3[更新 PWM]
D4[flag_led = 0]
end
subgraph PWM 啟動/停止
E[pwm_state 函數]
E1{flag_brk == 0?}
E2[啟動 PWM]
E3[停止 PWM]
end
subgraph 計時中斷 TIM4
F[TIM4 IRQHandler]
F1[每 5 毫秒: 更新 LED 狀態]
F2[每 5 秒: 切換 PWM 啟動/停止]
end
subgraph GPIO 中斷
G[HAL_GPIO_EXTI_Callback]
G1{PA5_Pin 低電位?}
G2[切換 PA7_Pin 狀態]
end
A --> B --> C
C --> D
D --> D1
D1 -- 是 --> D2 --> D3 --> D4
D1 -- 否 --> E
C --> E
E --> E1
E1 -- 是 --> E2
E1 -- 否 --> E3
F --> F1
F --> F2
G --> G1
G1 -- 是 --> G2
```
### 程式碼
:::spoiler main.c
{%gist /shiaw87/07463454e9dddbf86939bbed58b15442 %}
:::
:::spoiler stm32f4xx_it.c
{%gist /shiaw87/6cda9f8265aa6c4ac61c2523016e45ad %}
:::
# Topic-3 WWDG
## Watchdog簡介
看門狗(Watchdog Timer, WDT)是一種計時器,其主要功能是在 **微控制器發生異常時(如進入無窮迴圈或程式崩潰)自動重新啟動系統**,確保裝置能夠恢復運行,提升系統的可靠性。
STM32 內建兩種看門狗:
1. **獨立看門狗(IWDG,Independent Watchdog)**
2. **窗口看門狗(WWDG,Window Watchdog)**
### **獨立看門狗(IWDG)**
IWDG 的運作方式是透過 **遞減計數器倒數**,當計數器歸零時,若 MCU **沒有在期限內「餵狗」(重置計數器)**,則系統會觸發 **重置(Reset)**。
### **窗口看門狗(WWDG)**
WWDG 的機制與 IWDG 相似,但有額外的 **時間窗口限制**:
- 若 **太晚餵狗**(計數器低於下限 0x40),系統 **將重啟**。
- 若 **太早餵狗**(計數器值仍高於窗口值),系統 **也會重啟**。
這表示 **WWDG 需要在特定時間範圍內刷新計數器**,避免過早或過晚操作,這就是 **「窗口」** 機制的由來。
### **簡單對比**
| 看門狗類型 | 觸發條件 | 主要特性 |
|------------|------------|------------|
| **IWDG** | 遞減計數器歸零 | 只要在倒數結束前餵狗即可 |
| **WWDG** | 計數器超過或低於窗口 | 需在指定窗口時間內餵狗 |
---
## **窗口看門狗 (WWDG)**
## **WWDG 時序圖**
- **🔴 紅色箭頭**:如果計數器值 **大於 W[6:0]** 時刷新,**系統將觸發重置(Reset)**。
- **🟢 綠色箭頭**:要防止 WWDG 觸發重置,應在 **計數器值小於 W[6:0] 時執行刷新**。
- **🔵 藍色箭頭**:當 **計數器值從 0x40 遞減到 0x3F** 時,**系統將觸發重置(Reset)**。

---
### 1. 看門狗超時時間計算公式
$$
T_{WWDG} = \left( \frac{1}{f_{PCLK}} \right) \times 4096 \times 2^{WDGTB} \times (T - W)
$$
其中:
- \\( T_{WWDG} \\):看門狗超時時間(秒)
- \\( f_{PCLK} \\):APB 時鐘頻率(Hz),例如 48 MHz(48,000,000 Hz)
- \\( WDGTB \\):時鐘分頻器(prescaler),可能取值 \\( 0, 1, 2, 3 \\),對應 \\( 2^0, 2^1, 2^2, 2^3 \\)
- \\( T \\):窗口看門狗計數器的起始值(最大 127)
- \\( W \\):窗口值(一般比 T 小,例如 80 或 63)
---
### 2. 計算範例
假設:
- APB 時鐘頻率 \\( f_{PCLK} = 48 \\) MHz
- 分頻係數 \\( WDGTB = 3 \\)(即 \\( 2^3 = 8 \\))
- 計數器起始值 \\( T = 127 \\)
- 窗口值 \\( W = 80 \\) 或 \\( W = 63 \\)
#### 2.1 最小刷新時間(進入允許刷新區間)
$$
T_{\text{min}} = \left( \frac{1}{48000000} \right) \times 4096 \times 2^3 \times (127 - 80)
$$
$$
= \left( \frac{1}{48000000} \right) \times 4096 \times 8 \times 47
$$
$$
\approx 32 \text{ ms}
$$
#### 2.2 最大刷新時間(超時重啟前的時間)
$$
T_{\text{max}} = \left( \frac{1}{48000000} \right) \times 4096 \times 2^3 \times (127 - 63 + 1)
$$
$$
= \left( \frac{1}{48000000} \right) \times 4096 \times 8 \times 65
$$
$$
\approx 45 \text{ ms}
$$
---
### 3. 解析
- **必須在 32 ms ~ 45 ms 之間** 呼叫 `HAL_WWDG_Refresh(&hwwdg)`,否則:
- **小於 32 ms**:看門狗仍在保護區間,不允許刷新(視為非法操作,重啟)。
- **大於 45 ms**:系統超時,將觸發復位(系統重啟)。
這樣的機制可以防止 MCU 進入無限迴圈或掛起時失去監控,確保系統穩定運行。
## 實作 Demo
{%youtube a5LS9gKlels %}
## STM32CubeIDE設定
### PIN 設定

---
### GPIO設定
開啟PA5 PA6 (output)、PB0(input,pull down)

---
### RCC設定

---
### SYS設定

---
### WWDG設定

---
### TIM設定

---
### Clock設定

---
#### WWDG clock
APB1 48MHZ

---
### 外設檔案分開


---
### Nucleo_Pinout

---
### 電路圖

---
## WWDG實作
###
:::spoiler 流程圖
```mermaid
flowchart TD
subgraph LED燈閃爍
A(開始)
B[for 迴圈]
D[切換 LED1 狀態]
G{迴圈結束?}
end
subgraph
H(進入 while)
I[延遲 100ms]
J{BTN1 是否被按下?}
K[關閉TIM3]
M[切換 LED2 狀態]
end
RE(超時重啟)
A --> B --> D --> G
G -- 否 --> B
G -- 是 --> H
H --> I --> J
J -- 是 --> K --> RE
J -- 否 --> M --> I
```
:::
### 程式碼
:::spoiler main.c
{%gist /shiaw87/9a4ff2ba262a6fc1d8ecaa23e15afe42 %}
:::
:::spoiler stm32f4xx_it.c
{%gist /shiaw87/096f191b7b35a42ec5687c4e097f3005 %}
:::
---
# Topic-4 USART
## USART(universal synchronous asynchronous receiver transmitter)
通用同步/非同步收發傳輸器,常被用於一般的串列傳輸應用。

---
### Asynchronous 非同步傳輸
在傳送資料時插入額外資訊,表示資料起始、結束。好處是設定時間短、硬體成本低、機器時脈不同也能傳資料,缺點是單次傳輸的資料量較少。
---
### Synchronous 同步傳輸
額外提供時脈訊號,使兩端機器在溝通時能夠藉此同步收發資料。比起非同步傳輸,同步傳輸不需要start/stop bit,因此能夠一次傳較多的資料。同步傳輸需要解決時鐘偏移對資料傳輸造成的影響,除此之外,額外的時脈分佈網也需要大量的驅動電路,比起非同步傳輸增加了更多的耗能。一般同步系統會用阻斷時脈的方式(clock gating),來令不需運作的模組進入睡眠狀態(sleeping mode)到省電的目的,這個機制需要額外的電路及再次同步的額外延遲,不僅造成多餘的能源損耗,也增加了電路設計上的困難度。

## 實作
### Demo
{%youtube Yw_P2MaAFDQ %}
### 需準備
#### LED\*4 & 1K電阻\*4

#### CP2102 模組

[CP2102驅動](https://www.silabs.com/developer-tools/usb-to-uart-bridge-vcp-drivers?tab=downloads)
#### 串口調試助手

## STM32CubeIDE設定
### PIN 設定

---
### GPIO設定

---
### RCC設定

---
### SYS設定

---
### USART設定
#### 先設定USART1 TX跟RX接腳再開啟USART1



#### 啟用USART1中斷功能

---
### Clock設定

---
### 外設檔案分開+生成

#### 生成程式碼

---
### Nucleo_Pinout

---
### 電路圖


---
### 程式碼
:::spoiler usart.c
{%gist /shiaw87/c282151b383edad45a15f85a704ca816 %}
:::
---
# Topic-5 RTC(DS1302)
## **RTC (Real-Time Clock) 即時時鐘介紹**
### **1. RTC 概念**
RTC(Real-Time Clock,即時時鐘)是一種特殊的時鐘裝置,用於提供持續的時間計時,即使系統關機或重啟,它仍能保持計時功能。RTC 主要應用於計算機、嵌入式系統、智慧型裝置等,確保系統能夠準確地追蹤時間和日期。
### **2. RTC 的特點**
- **低功耗**:RTC 主要依靠獨立的低功耗電池 (VBAT) 運作,即使主系統電源關閉,RTC 仍能運行。
- **獨立計時**:RTC 內部包含一個 32.768 kHz 的石英晶振,用於保持時間精確度。
- **日期與時間管理**:RTC 通常具備秒、分、時、日、月、星期和年等時間信息,並支援閏年自動調整。
- **支援低功耗模式**:某些 RTC 內建低功耗模式,適用於電池供電的嵌入式系統。
### **3. RTC 的應用**
- **計算機和嵌入式系統**:確保系統開機後能獲取正確時間。
- **智慧家庭**:用於定時設備,如智慧燈光控制。
- **數據記錄器**:確保數據紀錄時間的準確性,例如工業監測設備。
- **消費性電子產品**:如智慧手錶、行動裝置、MP3 播放器等。
---
## **DS1302 RTC 晶片介紹**
DS1302 是一款低功耗、串列介面的 RTC 晶片,適用於各種微控制器應用,如 STM32、Arduino、Raspberry Pi 等。
### **1. DS1302 主要特點**
- **串列通訊介面**:使用三線 SPI (SCLK, I/O, CE) 介面與微控制器通訊,易於連接。
- **時間與日期管理**:支援秒、分、時、日、月、星期與年計時,並具備 12/24 小時格式選擇。
- **低功耗設計**:當主電源關閉時,可使用備用電池 (VBAT) 維持計時功能。
- **內建 RAM**:提供 31 個 8-bit RAM 寄存器,其中 8 個用於 RTC,其他 23 個可作為 SRAM 使用。
- **工作電壓範圍廣**:支援 2V~5.5V 工作電壓,適用於不同應用環境。
- **時鐘精準度校正**:具備時間補償功能,可透過軟體校正計時誤差。
### **2. DS1302 內部架構**
- **主時鐘電路**:由 32.768 kHz 石英晶振提供時鐘訊號,確保時間計時準確。
- **備用電池管理**:當主電源 (VCC) 斷電時,RTC 自動切換至 VBAT 電源,確保時間保持不變。
- **通訊介面**:使用簡單的三線 SPI 介面,可輕鬆與各種微控制器連接。
### **3. DS1302 應用**
- **數據記錄設備**:確保時間戳記的準確性,如溫度監測器、氣象站等。
- **智慧家居**:應用於定時開關、電器控制等場景。
- **電腦與嵌入式系統**:提供系統時間維持功能,如 BIOS 時鐘。
- **低功耗設備**:適用於需要長期運行且低能耗的電子裝置。
---
## **RTC 在 STM32F411 上的應用**
STM32F411 內建 RTC 模組,支援低功耗模式,並可使用 VBAT 保持時間資訊,因此在 STM32F411 上通常不需要外接 DS1302 等外部 RTC 晶片。內建 RTC 具有以下優勢:
- 低功耗運作,適合電池供電應用。
- 內建時鐘補償機制,提高計時準確性。
- 支援警報與定時喚醒功能,可用於節能應用。
## 實作
### Demo
{%youtube RJDkueZB_64 %}
### 需準備
#### DS1302 RTC 時鐘模組

#### CP2102 模組

[CP2102驅動](https://www.silabs.com/developer-tools/usb-to-uart-bridge-vcp-drivers?tab=downloads)
#### 串口調試助手

## STM32CubeIDE設定
### PIN 設定

---
### GPIO設定

---
### RCC設定

---
### SYS設定

---
### USART設定
#### 先設定USART1 TX跟RX接腳再開啟USART1



---
### Clock設定

---
### 外設檔案分開+生成

#### 生成程式碼

---
### Nucleo_Pinou

---
### 電路圖

---
## 實作
###
:::spoiler 流程圖
```mermaid
flowchart TD
A[啟動程式] --> B[系統初始化]
B --> C[初始化 DS1302]
C --> D{檢查初始化標記}
D -- 未初始化 --> E[設定時間]
E --> F[寫入初始化標記]
D -- 已初始化 --> G[讀取當前時間]
F --> G
G --> H["顯示時間"]
H --> L
subgraph L[while loop]
J[每秒讀取 DS1302 時間]
J --> K["顯示時間"]
end
```
:::
---
### 程式碼
:::spoiler main.c
{%gist /shiaw87/d4d88f4814441c62f4b4ef650f071140 %}
:::
:::spoiler usart.c
{%gist /shiaw87/09dec84840d9a0b98cf144d9f2969985 %}
:::
:::spoiler ds1302.h
{%gist /shiaw87/38d37860ba6695d59cc50f6bf85b84ac %}
:::
:::spoiler ds1302.c
{%gist /shiaw87/03271f9ceae503589b128a8ec9fa541d %}
:::
---
### 資料來源(驅動)
[GitHub 驅動程式來源](https://github.com/aaron-ev/driver-ds1302-stm32f4)
# Topic-6 SDIO
## 🔌 SDIO 是什麼?
**SDIO(Secure Digital Input Output)** 是一種擴充在 SD 記憶卡標準上的介面,支援 **資料儲存功能以外的 I/O 裝置**,例如:
- Wi-Fi 模組
- 藍牙模組
- GPS 模組
- 通用 I/O 模組(GPIO)
👉 在嵌入式應用中,SDIO **最常用來做為 SD 卡的資料傳輸介面**,提供比 SPI 更快的速度。
---
### 📶 SDIO 模式 vs SPI 模式
| 項目 | SDIO 模式 | SPI 模式 |
|-----------------|-------------------------|------------------------|
| 傳輸速度 | 高速(最高 50 MHz) | 低速(通常 20 MHz 以下) |
| 傳輸資料寬度 | 1-bit / 4-bit 資料線 | 單線(MOSI/MISO) |
| 效率 | 高 | 中等 |
| 實作難度 | 較高(需 DMA) | 較低 |
| 硬體資源占用 | 多(需 SDIO 外設) | 少(只要 SPI 控制器) |
🔧 若你的 MCU(例如 STM32)有內建 SDIO 介面,推薦使用 SDIO 模式搭配 **DMA(Direct Memory Access)** 傳輸,加快 SD 卡讀寫效率。
---
### 🧩 SDIO 的資料線(4-bit 模式)
| 腳位 | 功能 |
|----------|--------------------|
| CLK | 時鐘訊號 |
| CMD | 指令傳輸線 |
| D0–D3 | 資料線(1-bit / 4-bit) |
👉 實際使用中,**最少需 CMD、CLK、D0 三條線** 就能運作 1-bit 模式。若要跑 4-bit 模式,就要全部 D0~D3 都連接。
---
### 🧪 在 STM32 中使用 SDIO 的典型流程:
1. 初始化 SDIO 硬體(設定時脈、模式、腳位)
2. 掛載 FATFS 檔案系統(如使用 `f_mount()`)
3. 開啟檔案 / 寫入 / 讀取
4. 卸載檔案系統(` f_mount(NULL, "", 0); `)
🧠 STM32 HAL 提供了 `HAL_SD_Init()`、`HAL_SD_ReadBlocks()`、`HAL_SD_WriteBlocks()` 等 API
---
### 📦 實際應用場景
- 📁 使用 SD 卡記錄 Log 檔案(像是車用資料記錄器)
- 📸 儲存相機拍下的照片
- 🎮 從 SD 卡載入遊戲素材、音樂
- 📡 接 Wi-Fi 模組作資料上傳(藉由 SDIO I/O 擴充)
---
## 實作
## Demo

## STM32CubeIDE設定
### PIN 設定

---
### GPIO設定
PA5 設定INPUT

---
### RCC設定

---
### SYS設定

---
### SDIO設定
CMD D0 啟用pull up

開啟DMA

---
### USART設定

### NVIC 設定

---
### Clock設定

---
### FatFS設定

input 選PA5這是用來檢查SD卡插入的

---
### 外設檔案分開+生成

#### 生成程式碼

---
### Nucleo_Pinout

---
### 電路圖

---
## SDIO+FATFS實作
###
:::spoiler 流程圖
```mermaid
flowchart TD
A(開始)
B[掛載 SD 卡 f_mount]
C{掛載成功?}
D[printf 錯誤訊息]
E[開啟 test.txt 寫入模式]
F{開啟成功?}
G["寫入 TEST\\r\\n"]
H[關閉檔案]
I[開啟 test.txt 讀取模式]
J{開啟成功?}
K[讀取內容]
L[關閉檔案]
M[printf 輸出 buff]
Z(結束)
aa[卸載SD卡]
A --> B
B --> C
C -- 否 --> D
C -- 是 --> E
E --> F
F -- 否 --> D
F -- 是 --> G --> H --> I
I --> J
J -- 否 --> D --> aa -->Z
J -- 是 --> K --> L --> M --> aa
```
:::
---
### 程式碼
:::spoiler usart.c
{%gist /shiaw87/09dec84840d9a0b98cf144d9f2969985 %}
:::
:::spoiler main.c
{%gist /shiaw87/078036c6645318b9fdc12f6bcbf9cf67 %}
:::
:::spoiler fatfs.c
{%gist /shiaw87/3f4bbc214ec6f5a51674fb1531d103f9 %}
:::
---
### 參考資料
[📖參考資料](https://www.youtube.com/watch?v=1MxWZyayiTw)
# Topic-7 I²C
## I²C 簡介
I²C(Inter-Integrated Circuit,或稱 IIC)是一種常用的串列通訊協定,主要用於短距離設備之間的通訊。由 Philips(現為 NXP)於 1982 年設計,目的是用來在集成電路(IC)間傳輸資料。I²C 在許多嵌入式系統中被廣泛應用,適合多個設備之間的低速數據通訊。
### I²C 基本特點
1. **雙線通訊**:
- **SCL(Serial Clock Line)**:提供時鐘訊號,由主設備(Master)控制。
- **SDA(Serial Data Line)**:傳送資料和控制訊號,支持雙向通訊。
2. **多主多從架構**:
- 一條 I²C 線路可以連接多個主設備(Master)和多個從設備(Slave)。
- 主設備負責控制通訊的起始、停止和資料流向;從設備僅在主設備的控制下進行通訊。
3. **同步通訊**:
- 主設備透過 SCL 時鐘訊號與從設備同步,使多個設備能在相同時鐘訊號下準確進行資料通訊。
4. **位址分配**:
- 每個 I²C 從設備都有一個唯一的位址,由主設備透過位址碼選擇通訊的目標設備。
- 通常使用 7 位元位址,但也有擴展格式支持 10 位元位址。
### I²C 工作原理

I²C 通訊包括「起始條件」、「資料傳輸」和「停止條件」等步驟:
1. **起始條件(Start Condition)**:
- 主設備將 SDA 拉低,SCL 保持高電位,表示開始傳輸。
2. **資料傳輸**:
- 每次傳輸一個字節,I²C 會傳送 8 位元的數據,從最高位(MSB)傳送到最低位(LSB)。
- 每次傳輸結束後,從設備會回應 ACK(應答訊號),主設備根據 ACK 決定是否繼續或結束傳輸。
3. **停止條件(Stop Condition)**:
- 主設備將 SDA 拉高,SCL 也保持高電位,表示結束傳輸。
### 優缺點
**優點**:
- **雙線設計**使得硬體連接簡單且成本低。
- 支援**多主多從設備**,可連接多個設備,擴展性佳。
- 傳輸速率相對較高,適合低速或中速通訊。
**缺點**:
- **傳輸距離有限**,適合用於短距離的設備間通訊。
- 資料速率不及 SPI,通常用於需要較低傳輸速率的應用。
- I²C 協定本身是半雙工的,不能同時進行接收和傳輸。在同一條 I²C 線上,資料只能單向傳輸。
### I²C 應用範例
I²C 協定廣泛應用於嵌入式系統中,例如:
- 溫度感測器、EEPROM、RTC 時鐘、顯示驅動 IC 等設備。
- 在開發板如 Arduino、Raspberry Pi、STM32 等嵌入式控制器上都能看到 I²C 通訊的應用。
---
## AT24C02 EEPROM 介紹
**AT24C02** 是 Microchip 公司推出的一款 2Kb(256 字節)I²C EEPROM 記憶體,常用於儲存系統配置、校準數據等非揮發性數據。以下是 AT24C02 的詳細介紹。
### 基本參數
- **容量**:2Kb(256 字節)
- **介面**:I²C 通訊
- **工作電壓**:1.8V - 5.5V(支援寬電壓範圍)
- **記憶體組織**:32 頁,每頁 8 字節
### 記憶體結構
- 每頁包含 8 個字節,因此 AT24C02 擁有 32 頁。
- 每頁可以作為寫入單位,但在同一頁內的寫入數據不能超過 8 個字節。

### 通訊協定(I²C)
- **位址範圍**:AT24C02 的 I²C 7 位位址為 `0x50` 到 `0x57`(可根據 A0、A1、A2 接腳設定)。
- **傳輸速率**:支援標準模式(100kHz)和快速模式(400kHz)。
- **位址選擇**:A0、A1 和 A2 接腳可設置位址,最多支援 8 個設備在同一 I²C 線上。

### 讀寫操作
- **寫入操作**:
- 支援單字節和頁寫入,頁寫入時最多寫入 8 字節,超出頁大小的數據將覆蓋頁的開頭。
- **讀取操作**:
- 支援隨機讀取和循環讀取,可以從指定地址開始,連續讀取多字節數據。

### 特點
- **非揮發性**:斷電後數據仍保留,適合需要長期保存的配置數據。
- **壽命**:擦寫壽命達 1,000,000 次,數據保存期達 100 年。
- **低功耗**:適合低功耗應用場景。
### 應用場景
- **配置參數儲存**:儲存系統配置和校準參數。
- **紀錄數據儲存**:在物聯網、家電等設備中儲存長期保存的數據。
- **消費電子**:應用於家電和電子設備,儲存設定或狀態數據。
```c
HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
```

---
## 實作
### Demo

### STM32CubeIDE 設定
#### PIN 設定

---
#### RCC 設定

---
#### SYS 設定

---
#### I²C 設定

---
#### UART 設定

---
#### Clock 設定

---
#### 外設檔案分開+生成

##### 生成程式碼

---
#### Nucleo_Pinou

---
#### 電路圖

---
## I²C-AT24CXX 實作
### 流程圖
```mermaid
flowchart TD
A(開始)
B[讀取並顯示數據]
C[寫入 64 字節到 EEPROM]
D[再次讀取並顯示數據]
E[清空 EEPROM]
F[清空後再次讀取並顯示數據]
G[寫入 32 字節到 0x20 位置]
H(結束)
A --> B
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
```
---
### 程式碼
:::spoiler usart.c
{%gist /shiaw87/09dec84840d9a0b98cf144d9f2969985 %}
:::
:::spoiler i2c.h
{%gist /shiaw87/b71d6ed106a3852ebe20dc0a6b0d9298 %}
:::
:::spoiler i2c.c
{%gist /shiaw87/387f06012300f11e8d7167f5d5f4c14e %}
:::
:::spoiler main.c
{%gist /shiaw87/788d786e54baca6dda47c928cc27712c %}
:::
---
## SSD1306 OLED(IIC通訊)
### SSD1306 OLED 0.96''是一種點陣顯示器(Dot-matrix display),是由可亮滅的許多小單元(燈或其它結構)排成陣列,來顯示文字或圖形內容的顯示裝置。


### SSD1306這塊驅動晶片的任務是用於執行接收數據、顯示儲存數據、掃描刷新等。
驅動接口:128個SEG接腳和64個COM接腳,對應128×64像素點陣顯示屏。
圖形顯示數據RAM-Graphic Display Data RAM(GDDRAM):128×64位元(128×8位元組)SRAM。
通訊介面:8位元6800/8080並行,3/4線SPI,I2C。

SEG 引腳(Segment Pins)
SEG 引腳負責驅動顯示器上的各個像素直向排列的部分(通常是一列像素的各個點)。
SSD1306 的 SEG 引腳標籤通常是從 SEG0 到 SEG127,對應 128 列。
COM 引腳(Common Pins)
COM 引腳負責驅動顯示器上的每一行。
在 SSD1306 中,COM 引腳標籤從 COM0 到 COM63,對應 64 行。




---



## 實作
## Demo
{%youtube akr9O4ziHuY %}

## STM32CubeIDE設定
### PIN 設定

---
### RCC設定

---
### SYS設定

---
### I2C設定

---
### Clock設定

---
### 外設檔案分開+生成

#### 生成程式碼

---
### Nucleo_Pinou

---
### 電路圖

---
### 程式碼
:::spoiler codetap.h
{%gist /shiaw87/595fb6ef69a81548be1988125da4c780 %}
:::
:::spoiler oled.h
{%gist /shiaw87/0fdf353befad22229bdd8274c3210928 %}
:::
:::spoiler oled.c
{%gist /shiaw87/f95f17a65ab6842076ea1399e8a13bd2 %}
:::
::: spoiler main.c
{%gist /shiaw87/8f48ccf12d6448b3d0c7ddf32ecf2527 %}
:::
---
# Topic-8 SPI (NOR flash、ILI9341)
## SPI (Serial Peripheral Interface)
SPI(Serial Peripheral Interface)是一種常見的串列通訊協議,用於在MCU和外部設備之間進行高速數據傳輸。SPI通訊通常用於連接MCU與各種外部設備,如感測器、螢幕、儲存裝置、無線模組等。
### 基本原理
#### SPI通訊是一種同步通訊協議,它基於主從(Master-Slave)架構。以下是SPI通訊的基本原理:
**主機(Master)**:MCU當主機,生成時鐘訊號並控制數據傳輸。
**從機(Slave)**:外部設備(如感測器或儲存裝置)當從機,按照主機的時鐘訊號進行數據傳輸。
#### SPI通訊使用四條訊號線進行通訊
SCLK(Serial Clock):主機生成的時鐘訊號,用於同步數據傳輸。
MISO(Master In Slave Out):從機到主機的數據傳輸線,用於將數據從從機傳輸到主機。
MOSI(Master Out Slave In):主機到從機的數據傳輸線,用於將數據從主機傳輸到從機。
CS/SS(Chip Select/Slave Select):選擇要與主機通訊的從機的信號線。當CS/SS訊號為低電位時,表示該從機被選擇。


#### SPI(Serial Peripheral Interface)為主從式同步串列通訊,可分為單工/全雙工
單工:線路上的訊號只能做單向傳送
半雙工:線路上的訊號可以雙向傳送 , 但是不能同時傳送
全雙工:線路上的訊號可以同時雙向傳送
同步:傳送端和接收端共用同一個CLOCK
所有的傳輸都會根據一個共同的頻率訊號 , 此頻率訊號產生自”主控裝置(Master端)”, 從屬裝置(Slave端)會用此頻率訊號來對收到的位串流進行同步
如果有多個周邊晶片被連到同一個SPI介面 , 主控裝置能透過SS pin腳的電位高低來選擇接收資料的周邊裝置

SPI_CR1 中有兩個 bits 時鐘極性CPOL 和 時鐘相位CPHA 控制取值的時間關係,總共有4種組合。
CPOL(clock polarity) 決定閒置時 clock 的電位。
CPOL = 0 表閒置時為低電位。
CPOL = 1 表閒置時為高電位。
CPHA(clock phase) 決定在 clock 的哪個 edge 取值。
CPHA = 0 表示在第一個 edge (Rising,when CPOL=0.Falling,when CPOL=1.)取值。
CPHA = 1 表示在第二個 edge (Falling,when CPOL=1.Rising,when CPOL=0.)取值。

## W25Q32FV - Serial NOR Flash
快閃記憶體(NOR Flash)是一種非揮發性記憶體技術,廣泛應用於嵌入式系統和儲存設備中。
### 基本特性
非揮發性:即使在沒有電力的情況下,存儲在 NOR Flash 中的數據也不會丟失。
可擦寫性:數據可以寫入、讀取和擦除,但在操作上一般需要擦除整個扇區或區塊,而不是單個字節。
Nor Flash主要應用在程式碼的儲存,容量較小、寫入速度慢,但因隨機讀取速度快,不適合朝大容量發展,主要用在手機上,目前以16Mb、32Mb為主。


### W25Q32 記憶體結構:
W25Q32 共有 64 個block,因此總容量為 4MB。
區塊 (block):
每個block的大小為 64KB。 1 block = 16 sector。
扇區 (sector):
每個sector的大小為 4KB。1 sector = 16 page。
頁 (page):
1 page = 256byte。
字節 (byte):
1 byte = 8 bit。每個byte有唯一的address。
位 (bit):
最小的單位是bit,每個bit的值是 1 或 0。每 8 bit 構成 1 個byte。
### W25Q32 常用指令集(非所有指令)

## 實作
## Demo
{%youtube _nCUfQEKNps %}
## STM32CubeIDE設定
### PIN 設定

---
### GPIO設定

---
### RCC設定

---
### SYS設定

---
### SPI1啟用


---
### UART設定

---
### Clock設定

---
### 外設檔案分開+生成

#### 生成程式碼

---
### 建立 W25Q32.c及W25Q32.h


---
### Nucleo_Pinou

---
### 電路圖


---
## SPI + NOR flash(W25Q32) 實作
### 程式碼
####
:::spoiler usart.c
{%gist /shiaw87/09dec84840d9a0b98cf144d9f2969985 %}
:::
:::spoiler main.c
{%gist /shiaw87/b172cbb82083f4db644f06ee211c9e0f %}
:::
:::spoiler W25Q32.c
{%gist /shiaw87/3d47ed11c466c0f53215366897a76ec3 %}
:::
:::spoiler W25Q32.h
{%gist /shiaw87/5a889b19d7637e58fdc874d0cc99ef37 %}
:::
## TFT ILI9341實作
## Demo
{%youtube _0Ot_U6uRhs %}
## STM32CubeIDE設定
### PIN 設定

---
### GPIO設定

---
### RCC設定

---
### SYS設定

---
### TIM設定


---
### SPI設定
選



---
### NVIC 設定

---
### CRC設定

___
### touchGFX設定


___
### Clock設定

---
### 外設檔案分開+生成

#### 生成程式碼

---
### Nucleo_Pinou

---
### 電路圖

---
## ILI9341實作
[下載touchGFX](https://www.st.com/en/development-tools/touchgfxdesigner.html)
---
### 程式碼
:::spoiler main.c
{%gist /shiaw87/0dd6c5c81c47d50fdc3edbd5700aa713 %}
:::
:::spoiler z_displ_ILI9XXX.h
{%gist /shiaw87/c222e228084efeaa4c7390281a45a624 %}
:::
:::spoiler z_displ_ILI9XXX.c
{%gist /shiaw87/85c629b6727ed8f86417e8e40731e0eb %}
:::
:::spoiler z_touch_XPT2046.h
{%gist /shiaw87/20cb8f64c8fdcf0e66f641228f63564e %}
:::
:::spoiler z_touch_XPT2046.c
{%gist /shiaw87/cbf270d4f1dcb77e41a1c4680b26f07f %}
:::
:::spoiler STM32TouchController.cpp
{%gist /shiaw87/8ba7a2dc1d99c53064082cc37f9d6713 %}
:::
### touchGFX設定
點擊



調整UI介面

添加背景

把原本的背景刪除

可以模擬看看成效

完成後就可以生成程式碼了

##
[📖參考資料](https://www.youtube.com/watch?v=g1siKaPox88)