# 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 ![image](https://hackmd.io/_uploads/SkfRDudt1g.png) --- ### 選取開發板型號:NUCLEO-F411RE ![image](https://hackmd.io/_uploads/BkyJTUyelx.png) --- ### 建立專案 ![image](https://hackmd.io/_uploads/SkFkBKOK1e.png) --- ### Pinout -> Clear Pinouts 移除用不到的Pin腳 ![image](https://hackmd.io/_uploads/SkDmytuKkx.png) ![image](https://hackmd.io/_uploads/rJeByKuFkx.png =30%x) --- ### 設定 RCC 時鐘源 ![image](https://hackmd.io/_uploads/HJtTpuOYyg.png) --- ### Debug 設定 ![image](https://hackmd.io/_uploads/Bk5kC__Kyx.png) --- ### Pin腳啟用 **按鈕1、2**: PB0、PB1 (GPIO_Input) **蜂鳴器**: PC4 (GPIO_Output) **LED**: PA4、PA5、PA6、PA7 (GPIO_Output) ![image](https://hackmd.io/_uploads/S1BLngzqye.png) NUCLEO-F411RE Pinout ![nucleo_pinout_13](https://hackmd.io/_uploads/B1gl-zz9yl.png) 接線 ![GPIO](https://hackmd.io/_uploads/BJ10T_Bjye.png) --- ### Pin腳設定 ![image](https://hackmd.io/_uploads/HJwK2xGqJe.png) --- ### 點擊分開其他初始化設定 ![image](https://hackmd.io/_uploads/rkD5ieGcyl.png) ### 設置完成 點選齒輪生成程式碼 ![image](https://hackmd.io/_uploads/B11qzFOFkl.png) --- ### 沙盒模式 :::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: 產生一個週期性的信號,例如可供馬達控制 ![tim](https://hackmd.io/_uploads/SkG63TY5yx.png) ### STM32 定時器(Timer)計數週期 T 的計算公式 ![time](https://hackmd.io/_uploads/rkOa36Kqyx.png) 此公式用來計算 STM32 定時器的定時週期,也就是計時器從 0 計數到 ARR(自動重裝載值)後發生一次溢出的時間。 ### Prescaler (PSC) 預分頻器值 ### Period (ARR) 自動重裝載值 ### PCLK 時鐘頻率 計時器的輸入時鐘頻率 ### T 定時器週期( 0 到 ARR 需要的時間) ### 舉例: 設定 1 秒計時 假設: PCLK1(APB1 時鐘)= 72MHz PSC = 7199 (分頻 7200) ARR = 9999 (計數範圍 0 ~ 9999) ![image](https://hackmd.io/_uploads/rJ3nSD3qkx.png) 定時器每 1 秒 產生一次溢出,觸發中斷。 ### 脈波寬度調變Pulse width modulation(PWM) PWM是將類比信號轉換為脈波,一般轉換後脈波的週期固定,但脈波的占空比會依類比信號的大小而改變。 在使用 PWM 時我們會需要控制兩種參數:頻率與 Duty Cycle(佔空比)。頻率的部分和 Timer 一樣,由 PSC 與 ARR 的值來設定,而 Duty Cycle 則由 CCR (Capture/Compare Register,捕獲/比較暫存器)來指定。 #### 佔空比(Duty Cycle) 佔空比是指輸出的PWM當中,高電位保持的時間與整個週期之比。可以看到下圖當中最上方為50%的佔空比,也就是高電位與低電位各佔50%。 ![image](https://hackmd.io/_uploads/ryhwAP25yl.png) ![image](https://hackmd.io/_uploads/SkK3Cv25Jx.png) Timer使用PWM輸出模式時,CNT計數值大於CCRx的時候會輸出高電位,相反的低於CCRx時則是低電位。 ARR : 主要控制的是頻率,也就是綠框的部分 CCRx : 主要為控制佔空比,也就是藍框的部分 求Duty Cycle: ![image](https://hackmd.io/_uploads/rJINQ_2ckx.png) ## 中斷(Interrupt) 在嵌入式系統中,中斷是一個機制,用於處理各種外部事件或內部條件的發生。這些事件可以是來自硬體設備的訊號,例如按鈕按下、計時器計時完成,或是軟體內部的條件,如:數據溢出或滿足一些特定條件。當一個中斷事件發生時,MCU會中斷正在執行的程式,轉而執行相應的中斷服務程式(Interrupt Service Routine,ISR),處理該事件,然後繼續執行原來的程式。 ### 中斷的類型 MCU支援多種不同類型的中斷,以下是一些常見的中斷類型: 外部中斷: 由外部硬體觸發的中斷,例如按鈕按下、感測器觸發等。 定時器中斷: 由MCU內部定時器計時完成時觸發,用於執行定時任務。 UART中斷: 用於處理串列通信中的數據接收或傳送完成事件。 ADC中斷: 用於類比數位轉換(ADC)完成時,通常用於讀取模擬數據。 內部中斷: 由MCU內部條件觸發的中斷,例如除以零的錯誤。 看門狗定時器中斷: 用於檢測系統錯誤並執行相應的動作。 ### 中斷優先級 當多個中斷事件同時發生時,MCU需要確定哪個中斷應該首先處理。這就涉及到中斷優先級的概念。每個中斷都有一個優先級,通常是數字越小,優先級越高。當多個中斷事件同時發生時,MCU會首先處理優先級最高的中斷,然後再處理其他中斷,以此類推。 ## 實作Demo {%youtube Aiw47c68cww %} ### STM32CubeIDE設定 ### PIN 設定 ![image](https://hackmd.io/_uploads/SyOag_n9ke.png) --- ### GPIO設定 PA5 EXIT5 中斷開啟 ![image](https://hackmd.io/_uploads/SkSEpPhc1x.png) --- PA7 output ![image](https://hackmd.io/_uploads/BJsw6D2q1g.png) --- ### RCC設定 ![image](https://hackmd.io/_uploads/BJk0pw3qkl.png) --- ### SYS設定 ![image](https://hackmd.io/_uploads/H1U-Rv2q1x.png) --- ### TIM設定 開啟tim3 pwn設定頻率2kHz ![image](https://hackmd.io/_uploads/HksZ6Ih91x.png) --- 開啟tim4 設定每毫秒跑一次 ![image](https://hackmd.io/_uploads/ryPUaL291l.png) --- ### NVIC 設定 ![image](https://hackmd.io/_uploads/H1JNCwn9yx.png) --- ### Clock設定 ![image](https://hackmd.io/_uploads/S1_W1uhqkg.png) --- ### 外設檔案分開+生成 ![image](https://hackmd.io/_uploads/HJMkxu29yl.png) ![image](https://hackmd.io/_uploads/ryhExd2qJe.png) --- ### Nucleo_Pinou ![nucleo_pinout](https://imgur.com/pW4VU4f.png) --- ### 電路圖 ![bse202536](https://hackmd.io/_uploads/HJvSyAUskx.png) --- ### 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)**。 ![WWDG 時序圖](https://hackmd.io/_uploads/Hy-1KSEoke.png) --- ### 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 設定 ![image](https://hackmd.io/_uploads/SyOag_n9ke.png) --- ### GPIO設定 開啟PA5 PA6 (output)、PB0(input,pull down) ![image](https://hackmd.io/_uploads/BJqLFS4jye.png) --- ### RCC設定 ![image](https://hackmd.io/_uploads/BJk0pw3qkl.png) --- ### SYS設定 ![image](https://hackmd.io/_uploads/H1U-Rv2q1x.png) --- ### WWDG設定 ![image](https://hackmd.io/_uploads/S1Ew0SVs1g.png) --- ### TIM設定 ![image](https://hackmd.io/_uploads/SksqvT0oJx.png) --- ### Clock設定 ![image](https://hackmd.io/_uploads/HkvxVL4jkx.png) --- #### WWDG clock APB1 48MHZ ![image](https://hackmd.io/_uploads/ryIdQ84o1e.png) --- ### 外設檔案分開 ![image](https://hackmd.io/_uploads/HJMkxu29yl.png) ![image](https://hackmd.io/_uploads/ryhExd2qJe.png) --- ### Nucleo_Pinout ![nucleo_pinout_13](https://hackmd.io/_uploads/H1V4ROSs1x.png) --- ### 電路圖 ![132 (2)](https://hackmd.io/_uploads/Bku7684ikx.png) --- ## 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) 通用同步/非同步收發傳輸器,常被用於一般的串列傳輸應用。 ![image](https://hackmd.io/_uploads/BJW-G9c2yl.png) --- ### Asynchronous 非同步傳輸 在傳送資料時插入額外資訊,表示資料起始、結束。好處是設定時間短、硬體成本低、機器時脈不同也能傳資料,缺點是單次傳輸的資料量較少。 --- ### Synchronous 同步傳輸 額外提供時脈訊號,使兩端機器在溝通時能夠藉此同步收發資料。比起非同步傳輸,同步傳輸不需要start/stop bit,因此能夠一次傳較多的資料。同步傳輸需要解決時鐘偏移對資料傳輸造成的影響,除此之外,額外的時脈分佈網也需要大量的驅動電路,比起非同步傳輸增加了更多的耗能。一般同步系統會用阻斷時脈的方式(clock gating),來令不需運作的模組進入睡眠狀態(sleeping mode)到省電的目的,這個機制需要額外的電路及再次同步的額外延遲,不僅造成多餘的能源損耗,也增加了電路設計上的困難度。 ![image](https://hackmd.io/_uploads/HyHdW5c3Je.png) ## 實作 ### Demo {%youtube Yw_P2MaAFDQ %} ### 需準備 #### LED\*4 & 1K電阻\*4 ![image](https://hackmd.io/_uploads/rkn0exhnyl.png) #### CP2102 模組 ![S__258564101_0](https://hackmd.io/_uploads/HJXbBmt3Jg.jpg) [CP2102驅動](https://www.silabs.com/developer-tools/usb-to-uart-bridge-vcp-drivers?tab=downloads) #### 串口調試助手 ![image](https://hackmd.io/_uploads/rkEBVxhn1x.png) ## STM32CubeIDE設定 ### PIN 設定 ![PinoutClear](https://imgur.com/VJNPOvV.png) --- ### GPIO設定 ![image](https://hackmd.io/_uploads/rkEkh0j2yl.png) --- ### RCC設定 ![RccSet](https://imgur.com/7kPTJ9A.png) --- ### SYS設定 ![SysSet](https://imgur.com/rNjjVDv.png) --- ### USART設定 #### 先設定USART1 TX跟RX接腳再開啟USART1 ![image](https://hackmd.io/_uploads/S1YZj0snye.png) ![image](https://hackmd.io/_uploads/BJ5MoCsnJe.png) ![image](https://hackmd.io/_uploads/BkRojCi2kx.png) #### 啟用USART1中斷功能 ![image](https://hackmd.io/_uploads/SyTpjCshye.png) --- ### Clock設定 ![ClockSet](https://imgur.com/SlT0y70.png) --- ### 外設檔案分開+生成 ![GeneratorSet](https://imgur.com/Lo1x0Fc.png) #### 生成程式碼 ![CodeGenerator](https://imgur.com/LDLzPZb.png) --- ### Nucleo_Pinout ![nucleo_pinout](https://imgur.com/pW4VU4f.png) --- ### 電路圖 ![image](https://hackmd.io/_uploads/S1wUuAihkx.png) ![image](https://hackmd.io/_uploads/Sk4P_Ao3Jl.png) --- ### 程式碼 :::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 時鐘模組 ![S__258564100_0](https://hackmd.io/_uploads/By1-HQt2kl.jpg) #### CP2102 模組 ![S__258564101_0](https://hackmd.io/_uploads/HJXbBmt3Jg.jpg) [CP2102驅動](https://www.silabs.com/developer-tools/usb-to-uart-bridge-vcp-drivers?tab=downloads) #### 串口調試助手 ![image](https://hackmd.io/_uploads/rkEBVxhn1x.png) ## STM32CubeIDE設定 ### PIN 設定 ![PinoutClear](https://imgur.com/VJNPOvV.png) --- ### GPIO設定 ![image](https://hackmd.io/_uploads/B1ZKsRP3yg.png) --- ### RCC設定 ![RccSet](https://imgur.com/7kPTJ9A.png) --- ### SYS設定 ![SysSet](https://imgur.com/rNjjVDv.png) --- ### USART設定 #### 先設定USART1 TX跟RX接腳再開啟USART1 ![image](https://hackmd.io/_uploads/S1YZj0snye.png) ![image](https://hackmd.io/_uploads/BJ5MoCsnJe.png) ![image](https://hackmd.io/_uploads/BkRojCi2kx.png) --- ### Clock設定 ![ClockSet](https://imgur.com/SlT0y70.png) --- ### 外設檔案分開+生成 ![GeneratorSet](https://imgur.com/Lo1x0Fc.png) #### 生成程式碼 ![CodeGenerator](https://imgur.com/LDLzPZb.png) --- ### Nucleo_Pinou ![nucleo_pinout](https://imgur.com/pW4VU4f.png) --- ### 電路圖 ![DS1302_circult](https://hackmd.io/_uploads/Hk1u4yO3yl.png) --- ## 實作 ### :::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 ![image](https://hackmd.io/_uploads/ryAdUsqnyl.png) ## STM32CubeIDE設定 ### PIN 設定 ![PinoutClear](https://imgur.com/VJNPOvV.png) --- ### GPIO設定 PA5 設定INPUT ![image](https://hackmd.io/_uploads/HJxin95h1l.png) --- ### RCC設定 ![RccSet](https://imgur.com/7kPTJ9A.png) --- ### SYS設定 ![SysSet](https://imgur.com/rNjjVDv.png) --- ### SDIO設定 CMD D0 啟用pull up ![image](https://hackmd.io/_uploads/B1gasq9hyl.png) 開啟DMA ![image](https://hackmd.io/_uploads/SkSWnq5nke.png) --- ### USART設定 ![image](https://hackmd.io/_uploads/Skw4nc531x.png) ### NVIC 設定 ![image](https://hackmd.io/_uploads/r1RSh552kl.png) --- ### Clock設定 ![ClockSet](https://imgur.com/SlT0y70.png) --- ### FatFS設定 ![image](https://hackmd.io/_uploads/HkcbTc5hJx.png) input 選PA5這是用來檢查SD卡插入的 ![image](https://hackmd.io/_uploads/S1v769chkg.png) --- ### 外設檔案分開+生成 ![GeneratorSet](https://imgur.com/Lo1x0Fc.png) #### 生成程式碼 ![CodeGenerator](https://imgur.com/LDLzPZb.png) --- ### Nucleo_Pinout ![nucleo_pinout](https://imgur.com/pW4VU4f.png) --- ### 電路圖 ![bse2025321](https://hackmd.io/_uploads/H1dT1s5hJx.png) --- ## 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 工作原理 ![image](https://hackmd.io/_uploads/SkN1qiwR1g.png =80%x) 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 個字節。 ![AT24C02](https://hackmd.io/_uploads/ryRg9iDRJe.png) ### 通訊協定(I²C) - **位址範圍**:AT24C02 的 I²C 7 位位址為 `0x50` 到 `0x57`(可根據 A0、A1、A2 接腳設定)。 - **傳輸速率**:支援標準模式(100kHz)和快速模式(400kHz)。 - **位址選擇**:A0、A1 和 A2 接腳可設置位址,最多支援 8 個設備在同一 I²C 線上。 ![image](https://hackmd.io/_uploads/HkUzcsPRkg.png) ### 讀寫操作 - **寫入操作**: - 支援單字節和頁寫入,頁寫入時最多寫入 8 字節,超出頁大小的數據將覆蓋頁的開頭。 - **讀取操作**: - 支援隨機讀取和循環讀取,可以從指定地址開始,連續讀取多字節數據。 ![image](https://hackmd.io/_uploads/BkMEqiwCkg.png) ### 特點 - **非揮發性**:斷電後數據仍保留,適合需要長期保存的配置數據。 - **壽命**:擦寫壽命達 1,000,000 次,數據保存期達 100 年。 - **低功耗**:適合低功耗應用場景。 ### 應用場景 - **配置參數儲存**:儲存系統配置和校準參數。 - **紀錄數據儲存**:在物聯網、家電等設備中儲存長期保存的數據。 - **消費電子**:應用於家電和電子設備,儲存設定或狀態數據。 ```c HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) ``` ![image](https://hackmd.io/_uploads/B1NB9oDAkg.png) --- ## 實作 ### Demo ![螢幕擷取畫面 2025-04-09 145958](https://hackmd.io/_uploads/BJMr2qm0Jx.png) ### STM32CubeIDE 設定 #### PIN 設定 ![PinoutClear](https://imgur.com/VJNPOvV.png) --- #### RCC 設定 ![RccSet](https://imgur.com/7kPTJ9A.png) --- #### SYS 設定 ![SysSet](https://imgur.com/rNjjVDv.png) --- #### I²C 設定 ![image](https://hackmd.io/_uploads/SyeO29X0ye.png) --- #### UART 設定 ![UartSet](https://hackmd.io/_uploads/ry4_sc7CJe.png) --- #### Clock 設定 ![ClockSet](https://imgur.com/SlT0y70.png) --- #### 外設檔案分開+生成 ![GeneratorSet](https://imgur.com/Lo1x0Fc.png) ##### 生成程式碼 ![CodeGenerator](https://imgur.com/LDLzPZb.png) --- #### Nucleo_Pinou ![nucleo_pinout](https://imgur.com/pW4VU4f.png) --- #### 電路圖 ![IIC](https://hackmd.io/_uploads/S1D2eiXCJl.png) --- ## 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),是由可亮滅的許多小單元(燈或其它結構)排成陣列,來顯示文字或圖形內容的顯示裝置。 ![image](https://hackmd.io/_uploads/SJJtXUcAkx.png) ![image](https://hackmd.io/_uploads/S18lVUqC1e.png) ### 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。 ![image](https://hackmd.io/_uploads/ryvMVI9Cyl.png) SEG 引腳(Segment Pins) SEG 引腳負責驅動顯示器上的各個像素直向排列的部分(通常是一列像素的各個點)。 SSD1306 的 SEG 引腳標籤通常是從 SEG0 到 SEG127,對應 128 列。 COM 引腳(Common Pins) COM 引腳負責驅動顯示器上的每一行。 在 SSD1306 中,COM 引腳標籤從 COM0 到 COM63,對應 64 行。 ![image](https://hackmd.io/_uploads/SkHNV85Ryx.png) ![image](https://hackmd.io/_uploads/BJIrV85Rkl.png) ![image](https://hackmd.io/_uploads/Sk3IVI90Je.png) ![image](https://hackmd.io/_uploads/B1GPV89Ryl.png) --- ![image](https://hackmd.io/_uploads/rJtjVU5Rke.png) ![image](https://hackmd.io/_uploads/Hkw3NUcAye.png) ![image](https://hackmd.io/_uploads/SJf6ELq0ke.png) ## 實作 ## Demo {%youtube akr9O4ziHuY %} ![image](https://hackmd.io/_uploads/Bka4SI501e.png) ## STM32CubeIDE設定 ### PIN 設定 ![PinoutClear](https://imgur.com/VJNPOvV.png) --- ### RCC設定 ![RccSet](https://imgur.com/7kPTJ9A.png) --- ### SYS設定 ![SysSet](https://imgur.com/rNjjVDv.png) --- ### I2C設定 ![image](https://hackmd.io/_uploads/ryovSUq01x.png) --- ### Clock設定 ![ClockSet](https://imgur.com/SlT0y70.png) --- ### 外設檔案分開+生成 ![GeneratorSet](https://imgur.com/Lo1x0Fc.png) #### 生成程式碼 ![CodeGenerator](https://imgur.com/LDLzPZb.png) --- ### Nucleo_Pinou ![nucleo_pinout](https://imgur.com/pW4VU4f.png) --- ### 電路圖 ![image](https://hackmd.io/_uploads/HklPPIc01e.png) --- ### 程式碼 :::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訊號為低電位時,表示該從機被選擇。 ![image](https://hackmd.io/_uploads/SJjAhxER1x.png) ![image](https://hackmd.io/_uploads/HyxeagVAJx.png) #### SPI(Serial Peripheral Interface)為主從式同步串列通訊,可分為單工/全雙工 單工:線路上的訊號只能做單向傳送 半雙工:線路上的訊號可以雙向傳送 , 但是不能同時傳送 全雙工:線路上的訊號可以同時雙向傳送 同步:傳送端和接收端共用同一個CLOCK 所有的傳輸都會根據一個共同的頻率訊號 , 此頻率訊號產生自”主控裝置(Master端)”, 從屬裝置(Slave端)會用此頻率訊號來對收到的位串流進行同步 如果有多個周邊晶片被連到同一個SPI介面 , 主控裝置能透過SS pin腳的電位高低來選擇接收資料的周邊裝置 ![image](https://hackmd.io/_uploads/BJQWTx4Rkx.png) 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.)取值。 ![image](https://hackmd.io/_uploads/HyVdbLigkx.png) ## W25Q32FV - Serial NOR Flash 快閃記憶體(NOR Flash)是一種非揮發性記憶體技術,廣泛應用於嵌入式系統和儲存設備中。 ### 基本特性 非揮發性:即使在沒有電力的情況下,存儲在 NOR Flash 中的數據也不會丟失。 可擦寫性:數據可以寫入、讀取和擦除,但在操作上一般需要擦除整個扇區或區塊,而不是單個字節。 Nor Flash主要應用在程式碼的儲存,容量較小、寫入速度慢,但因隨機讀取速度快,不適合朝大容量發展,主要用在手機上,目前以16Mb、32Mb為主。 ![image](https://hackmd.io/_uploads/H1u9UUslke.png) ![image](https://hackmd.io/_uploads/By6a5Usl1g.png) ### 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 常用指令集(非所有指令) ![image](https://hackmd.io/_uploads/S1akR2jxJx.png) ## 實作 ## Demo {%youtube _nCUfQEKNps %} ## STM32CubeIDE設定 ### PIN 設定 ![PinoutClear](https://imgur.com/VJNPOvV.png) --- ### GPIO設定 ![image](https://hackmd.io/_uploads/rJP5Ee4CJe.png) --- ### RCC設定 ![RccSet](https://imgur.com/7kPTJ9A.png) --- ### SYS設定 ![SysSet](https://imgur.com/rNjjVDv.png) --- ### SPI1啟用 ![image](https://hackmd.io/_uploads/Hy8nNxVRJe.png) ![image](https://hackmd.io/_uploads/H1ja4xVRye.png) --- ### UART設定 ![UartSet](https://hackmd.io/_uploads/ry4_sc7CJe.png) --- ### Clock設定 ![ClockSet](https://imgur.com/SlT0y70.png) --- ### 外設檔案分開+生成 ![GeneratorSet](https://imgur.com/Lo1x0Fc.png) #### 生成程式碼 ![CodeGenerator](https://imgur.com/LDLzPZb.png) --- ### 建立 W25Q32.c及W25Q32.h ![image](https://hackmd.io/_uploads/B1hHBlE0ke.png) ![image](https://hackmd.io/_uploads/B1z8BlERkg.png) --- ### Nucleo_Pinou ![nucleo_pinout](https://imgur.com/pW4VU4f.png) --- ### 電路圖 ![image](https://hackmd.io/_uploads/S1wUuAihkx.png) ![image](https://hackmd.io/_uploads/HJs0DgN0yx.png ) --- ## 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 設定 ![PinoutClear](https://imgur.com/VJNPOvV.png) --- ### GPIO設定 ![image](https://hackmd.io/_uploads/S1v2Erwyll.png) --- ### RCC設定 ![RccSet](https://imgur.com/7kPTJ9A.png) --- ### SYS設定 ![SysSet](https://imgur.com/rNjjVDv.png) --- ### TIM設定 ![image](https://hackmd.io/_uploads/BkLH78klxe.png) ![image](https://hackmd.io/_uploads/HkbOmUylee.png) --- ### SPI設定 選 ![image](https://hackmd.io/_uploads/BJKrBBvkxl.png) ![image](https://hackmd.io/_uploads/rJNQrSP1gx.png) ![image](https://hackmd.io/_uploads/S1_NrrvJgl.png) --- ### NVIC 設定 ![image](https://hackmd.io/_uploads/HJLtSrvJgl.png) --- ### CRC設定 ![image](https://hackmd.io/_uploads/SkSP0Bw1gx.png) ___ ### touchGFX設定 ![image](https://hackmd.io/_uploads/rkcM0SP1lg.png) ![image](https://hackmd.io/_uploads/Bkc40SPkeg.png) ___ ### Clock設定 ![ClockSet](https://imgur.com/SlT0y70.png) --- ### 外設檔案分開+生成 ![GeneratorSet](https://imgur.com/Lo1x0Fc.png) #### 生成程式碼 ![CodeGenerator](https://imgur.com/LDLzPZb.png) --- ### Nucleo_Pinou ![nucleo_pinout](https://imgur.com/pW4VU4f.png) --- ### 電路圖 ![image](https://hackmd.io/_uploads/SJPcPLyeeg.png) --- ## 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設定 點擊 ![image](https://hackmd.io/_uploads/H1i6ABvJll.png) ![image](https://hackmd.io/_uploads/rk4H1UvJex.png) ![image](https://hackmd.io/_uploads/SJRSyLD1gg.png) 調整UI介面 ![image](https://hackmd.io/_uploads/H1IuJIDkgg.png) 添加背景 ![image](https://hackmd.io/_uploads/SJPqkLw1eg.png) 把原本的背景刪除 ![image](https://hackmd.io/_uploads/HkFTy8Pklx.png) 可以模擬看看成效 ![image](https://hackmd.io/_uploads/rkiWeLPyxl.png) 完成後就可以生成程式碼了 ![image](https://hackmd.io/_uploads/HJGEeUDyle.png) ## [📖參考資料](https://www.youtube.com/watch?v=g1siKaPox88)