學完本章你將能夠:
安裝 STM32CubeIDE、接上 Nucleo、用 ST-LINK 下載第一個程式。
用 CubeMX 產生 GPIO + FreeRTOS 骨架,並理解哪些檔不可手改。
區分 HAL、LL、暫存器三級 API,知道本課程為何以 HAL 為主。
設定 UART 除錯輸出,養成「先看 log 再猜硬體」的習慣。
工具鏈是嵌入式的第一道牆。本章目標只有一個:到下課時,板上的使用者 LED 以 1 Hz 閃爍,且 UART 印出 hello voice-home。
你需要安裝的東西
STM32CubeIDE(內含 gcc-arm、CubeMX、GDB、ST-LINK)。
對應系列的 STM32CubeF4 / F7 / H7 套件(IDE 會自動拉)。
STM32CubeMX 可獨立使用,但本課程以 IDE 內建為準。
可選:STM32CubeMonitor、邏輯分析儀軟體、 STM32Cube.AI(路徑 B)。
接線:Nucleo 的 ST-LINK USB(通常標 CN1)接到電腦。Windows 需 ST-LINK 驅動;macOS / Linux 多半即插即用。若 IDE 看不到探針,先更新 ST-LINK 韌體(IDE 的 Help \(\rightarrow\) ST-LINK Upgrade)。
第一個專案:CubeMX 點選清單
新建 STM32 Project,選 NUCLEO-F429ZI(或你的板)。在 Pinout:
讓 IDE 套用板級預設,使用者 LED(F429ZI 上是 PB0 / PB7 / PB14) 會自動設為 GPIO_Output。
Connectivity \(\rightarrow\) USART3(Nucleo 的 VCP)設 Asynchronous, 115200 8N1。
Middleware \(\rightarrow\) FREERTOS \(\rightarrow\) CMSIS_V2。
在 Clock 頁把 HSE 打開(Nucleo 有 8 MHz 從 ST-LINK 進來), PLL 拉到 180 MHz。
Project Manager \(\rightarrow\) Code Generator:勾選 Generate peripheral initialization as a pair of ‘.c/.h’, 以及 Keep User Code when re-generating。
產生程式碼後,只在 /* USER CODE BEGIN */ ... /* USER CODE END */ 區塊寫你的邏輯。被 Cube 管的 |MX_*_Init| 不要手改,否則下次重新產生 會被覆寫。
HAL 怎麼看
HAL 把「設暫存器」包成有傳回值的函式。本課程常用家族:
HAL_GPIO_WritePin / TogglePin |
數位輸出 |
HAL_TIM_PWM_Start / set compare |
風扇與伺服 |
HAL_UART_Transmit / Receive_IT / DMA |
ASR 與遙測 |
HAL_I2S_Receive_DMA |
麥克風 |
HAL_IWDG_Refresh |
餵獨立看門狗 |
HAL_PWR_EnterSTOPMode |
低功耗 |
傳回 |HAL_OK| 才算成功。語音路徑上每一個 DMA 啟動都要檢查,失敗應 點亮故障 LED 並寫入 Event Group 的 FAULT 位,而不是假裝沒發生。
LL(Low Layer)更接近暫存器、較省週期。教學階段用 HAL 較易讀;若你在 I2S ISR 裡真的量到超時,再針對熱路徑改 LL。不要一開始就全專案 LL, 可讀性會崩。
實驗:1 Hz LED + UART
完整可編譯應用層見 firmware/lab01_blinky/。把該目錄的 app_main.c 內容貼進 Cube 專案的 USER CODE,或直接把檔案加入 建置。
#include "app_board.h"
void app_main(void)
uint32_t tick = 0U; char line[48];
app_log("hello voice-home̊");
for (;;) HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin); int n = snprintf(line, sizeof line, "tick (unsigned long)tick++); if (n > 0) HAL_UART_Transmit(&huart3, (uint8_t *)line, (uint16_t)n, 50); HAL_Delay(500);
用終端機(115200)應看到持續增加的 tick。若 LED 閃但沒有字, 十之八九是 USART 腳位不是 VCP 那一組,或鮑率與時鐘不一致。
除錯三板斧
SWD 斷點:看變數與週邊暫存器。不要在 I2S 熱路徑上長時 停住,DMA 會繼續跑。
UART log:模組化成 |app_log()|,之後 RTOS 裡改成 經佇列輸出,避免多任務打架。
GPIO 翻轉:在 ISR 進出各翻一次腳,用邏輯分析儀量真實 週期。這比任何 printf 都準。
printf 經 semihosting 極慢,且在未接 debugger 時可能卡死。 本課程禁止 semihosting,一律走 UART。
把閃爍週期改成 200 ms,並讓 LD2 與 LD1 相位相反。量測 UART 兩行 tick 的時間差,確認 |HAL_Delay| 與你的 SYSCLK 設定吻合。 若差超過 5%,回頭查時鐘樹。