
很多朋友一聽到嵌入式入門第一反應就是得先買一塊開發(fā)板。但現(xiàn)實情況是有人在外讀書不方便帶設備有人只是想先試試水并不確定自己要不要投入硬件這個坑還有人純粹是被板子買回來卻不知道從哪下手這個經(jīng)典開局勸退過。我先前也是這么糾結過來的后來自己把完整的STM32入門流程用純軟件方案跑了一遍發(fā)現(xiàn)只要核心思路對了不花錢買板子一樣能扎扎實實把外設一個個吃透。這篇文章就聊聊我怎么搭出這套純軟件版的STM32學習環(huán)境以及這里面真正有價值的經(jīng)驗。這套方案能做哪些事用一句話概括靠一個能在電腦上模擬STM32運行的軟件工具配合標準開發(fā)環(huán)境把點燈、按鍵掃描、定時器中斷、串口通信這類最常遇到的外設功能以純軟件的形態(tài)完整跑通。它最大的賣點不是省錢而是整個學習過程的即時反饋和可調試性很多在真實板子上需要反復拔線、甚至要借用示波器才能看清的信號狀態(tài)在軟件模擬環(huán)境里可以直接用鼠標點出來看。適合誰來參考如果你是零基礎想入門STM32但暫時沒有硬件在手或者你是學生黨手頭板子不在身邊又或者你已經(jīng)在玩硬件但想找個快速驗證外設邏輯的方式這篇文章都值得掃一遍。我不會只丟一個結論而是把從環(huán)境搭建到外設調試的整套邏輯都拆開講清楚順帶把我在仿真過程中踩過的幾個不明顯的坑也一并交代出來。讀這篇文章之前你不需要有開發(fā)板也不需要提前裝任何軟件。跟著我的步驟走一個多小時就能把環(huán)境跑起來然后你會對程序怎么控制硬件這件事產(chǎn)生跟對著板子燒錄完全不一樣的體感。1. 為什么純軟件路線值得走先說清楚價值邊界我說這套方案能跑通外設不代表它在所有方面都能替代真實硬件。了解它的適用范圍你才不會被仿真能跑誤導成程序上板必能跑。1.1 軟件模擬到底模擬了什么STM32的開發(fā)鏈路本質上分兩條線一是寫代碼二是看硬件反應。代碼寫的再漂亮最終都要落實到引腳電平變化、定時器計數(shù)器累加、串口數(shù)據(jù)收發(fā)這些物理行為上。純軟件模擬器的核心能力就是把這些物理行為在電腦里虛擬化呈現(xiàn)。比如你把某個引腳配置成推挽輸出并拉高模擬器不會真的點亮一顆LED但它會在外設窗口里把這個引腳的顏色改變并且更新電平狀態(tài)寄存器你配置了一個定時器中斷模擬器會在設定的時間點打斷主循環(huán)帶你去查看中斷服務程序的執(zhí)行情況。這意味著程序執(zhí)行邏輯、寄存器配置結果、外設狀態(tài)的聯(lián)動關系全部可以逐一驗證。這正是入門階段最需要的認知閉環(huán)——你在代碼里寫的每一個寄存器位都能在軟件界面上看到它實際統(tǒng)治了什么。1.2 哪些外設適合仿真哪些必須上板我整理一個實際結論外設類型仿真可用度說明GPIO點燈/按鍵輸入極高完全適合電平狀態(tài)可實時觀察定時器中斷/計數(shù)高時序邏輯清晰調試比硬件還方便PWM波形高可以在邏輯分析窗里直接看占空比變化串口UART收發(fā)高支持虛擬串口終端連接收發(fā)可回環(huán)測試外部中斷EXTI高通過鼠標點擊模擬引腳電平跳變ADC采樣中能模擬電壓變化過程但不接真實傳感器I2C/SPI與真實傳感器通信低傳感器芯片行為模擬有限上板更真實功耗/CAN總線等復雜外設低更依賴硬件真實環(huán)境從學習順序來看入門階段最關鍵的也就是GPIO、定時器、串口、中斷這幾樣恰恰是仿真支持得最好的部分。所以我的結論是純軟件路線完全覆蓋STM32入門的主干內(nèi)容直到你開始搞復雜的傳感器驅動或通信協(xié)議對接再上板也不遲。1.3 這套方案的隱藏紅利調試習慣我提一個可能有爭議的觀點仿真反而是養(yǎng)成調試習慣的好方式。拿真實板子調程序時新手最常見的操作是改一行代碼→燒錄→看現(xiàn)象不對→再改一行這其實是在碰運氣。而用軟件模擬器你能在代碼里斷點能逐行執(zhí)行能在某個外設狀態(tài)變化瞬間暫停整個系統(tǒng)去觀察寄存器。這種看見中間過程的能力會讓你的排查思路從猜謎變成真正的推理。2. 搭建純軟件開發(fā)環(huán)境選型與關鍵配置既然要純軟件第一步不是寫代碼而是先把手頭工具鏈理清楚。這里涉及兩個獨立軟件的組合很多人栽跟頭就栽在不知道兩者各管什么。2.1 開發(fā)環(huán)境與模擬器的分工邏輯我用的是Keil MDK做代碼編寫與編譯搭配STM32CubeMX做初始化代碼生成再打開軟件自帶的模擬器進行運行調試。這幾樣東西經(jīng)常被混為一談其實分工很明確CubeMX負責把你想要的引腳功能、外設參數(shù)轉換成初始化C代碼省去查寄存器的功夫Keil負責編譯這些代碼并生成可在處理器上執(zhí)行的程序文件模擬器則是Keil內(nèi)置的一個調試組件它模擬了STM32處理器的運行狀態(tài)不用連接實際芯片也能加載并執(zhí)行程序。三者串起來就是CubeMX生成工程 → Keil打開工程并編譯 → 進入調試模式啟動模擬 → 在模擬器里觀察外設行為。很多朋友裝好軟件后不知道怎么把模擬器調出來這里有個關鍵菜單項在Keil里點擊魔術棒圖標Options for Target切到Debug頁在右側選擇Use Simulator選項模擬功能才會被激活。這個細節(jié)不設置插不插開發(fā)板都會去連真實調試器純軟件環(huán)境自然跑不起來。2.2 一個容易忽略的時鐘配置純軟件模式下代碼燒不進任何實體芯片所有執(zhí)行都靠電腦的CPU去模擬STM32的處理過程。這里就牽扯到一個大家容易忽略但入坑必遇的問題時鐘頻率影響模擬速度。STM32內(nèi)部默認使用內(nèi)部高速時鐘而CubeMX生成工程時經(jīng)常會幫你配置成外部晶振方案。但仿真環(huán)境根本不存在外部晶振信號如果工程配置強制要求外部晶振模擬器可能在啟動后卡住或運行極慢。我的建議是在CubeMX的時鐘配置頁面把時鐘源明確選為內(nèi)部時鐘并把系統(tǒng)主頻設置到一個標準值。這個操作本身很簡單但不提前做的話后面所有仿真體驗都會因為運行緩慢而大打折扣。這個經(jīng)驗是我一開始沒注意后來發(fā)現(xiàn)模擬器里單步執(zhí)行像蝸牛爬反復排查后才意識到是時鐘源配置跟模擬環(huán)境不匹配導致的。2.3 從CubeMX到模擬器的完整搭建清單別急著上手按照這個順序走一遍基本不會出亂子安裝Java運行環(huán)境CubeMX依賴它運行安裝STM32CubeMX選擇自己的芯片型號創(chuàng)建新工程安裝Keil MDK并添加對應芯片型號的設備支持包在Keil中打開Options → Debug勾選Use Simulator模式進入調試環(huán)境的Peripherals菜單打開GPIO、TIM、USART等外設觀察窗口。提示CubeMX生成代碼時工具鏈選項要選擇MDK-ARM V5版本否則生成的工程Keil有可能打不開。3. 第一課仿真環(huán)境里點燈以及背后比點燈更重要的事點燈之所以叫嵌入式入門的第一課不只是因為它簡單而是它能在最簡單的前提下把代碼如何作用到引腳物理狀態(tài)這個核心鏈條走通。3.1 用CubeMX配置一個輸出引腳以下步驟基于標準流程新建工程、選定型號、在芯片圖上用鼠標點擊某個引腳并選擇GPIO_Output模式。這個操作模擬的是你決定使用這個引腳去控制一顆外部LED燈。值得注意的一個細節(jié)是GPIO Output level選項這里可以選擇初始化時默認拉高還是拉低。LED電路設計不同亮滅邏輯就不同低電平點亮負極接引腳和正極接電源的情況正好相反。所以選擇一個默認狀態(tài)本質上是為后續(xù)代碼里的置高置低操作預設了一個初始對照。實際做硬件時這個選擇由電路原理圖決定純軟件階段先隨便選一個知道有這個參數(shù)就行。配置完成后切到GPIO設置頁還能看到Pull-up/Pull-down、Maximum output speed這些參數(shù)。仿真階段影響不大但Maximum output speed這個選項值得留個印象——它決定了引腳翻轉的最高速率后續(xù)研究高速通信時會用上。3.2 主代碼與模擬器觀察CubeMX生成好工程后在main函數(shù)里補一段經(jīng)典的翻轉代碼while (1) { HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); HAL_Delay(200); HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); HAL_Delay(200); }這段代碼做的事情很簡單讓引腳輸出低電平、等200毫秒、輸出高電平、等200毫秒。編譯通過后進入調試模式打開Peripherals菜單里的GPIO窗口你會看到你配置的那個引腳對應的一行其中電平狀態(tài)在一高一低地變化著。這里插一個非常重要的經(jīng)驗純軟件模擬的環(huán)境里沒有實際電器參數(shù)約束代碼執(zhí)行完設置引腳電平的那一瞬間GPIO窗口里的狀態(tài)就會立刻變化。但真實板子上電平變化需要時間LED亮滅延時也要考慮電氣特性。仿真里看的是邏輯正確性硬件上看的是物理實現(xiàn)結果兩者之間的差異是正?,F(xiàn)象不必擔心自己配置錯了。3.3 進階玩法不用物理按鍵也能觀察輸入狀態(tài)點燈只是輸出方向。輸入方向就是讀按鍵狀態(tài)了這個在模擬器里觀察起來甚至比真實板子還方便。舉個例子在CubeMX里追加配置一個引腳為GPIO_Input模式然后在主循環(huán)里讀取它的電平根據(jù)電平?jīng)Q定LED引腳的狀態(tài)。在模擬器調試過程中你不需要真的去按一顆物理按鍵直接打開GPIO窗口找到對應輸入引腳那一行手動修改它的輸入電平值。把這個值從高改成低就相當于用手指按下了按鍵——程序會在下一次循環(huán)檢測到這個變化然后從代碼分支里走出你預期的反應。這個過程讓我覺得特別有價值的地方在于你在真實板子上按按鍵按鍵抖動、接觸電阻、引腳浮空這些真實因素都會干擾你的判斷但剛入門時根本不知道還有這些干擾存在。用模擬器把邏輯先玩明白之后碰到真實硬件至少能確定程序邏輯沒問題問題出在物理層面這是很關鍵的排查分界線。4. 定時器入門在仿真里看見時間這件事很多初學者學定時器最大的障礙來自于看不到時間流動。你在代碼里設置了一個中斷周期腦子里知道1毫秒會到一次但沒有示波器沒有邏輯分析儀的話你很難確認真實世界是不是按你的預期在執(zhí)行。仿真環(huán)境恰好把這個痛點治得服服帖帖。4.1 定時器中斷的初始化邏輯這里我用TIM2舉例。在CubeMX里啟用TIM2時鐘源選擇Internal Clock將預分頻器Prescaler設置為72-1自動重裝載值Counter Period設置為1000-1打開全局中斷。這樣配置出來的是什么效果前提是系統(tǒng)主頻運行在72MHz。定時器的計數(shù)時鐘等于主頻除以預分頻系數(shù)1。我的預分頻器設置為71那么計數(shù)時鐘就是 72MHz / 72 1MHz也就是每1微秒計數(shù)值加1。自動重裝載值設置為999意味著計數(shù)器從0數(shù)到999后溢出觸發(fā)一次更新事件。這樣算下來中斷周期恰好是1000微秒也就是1毫秒。這個計算過程我建議別偷懶自己認真推導一遍。很多朋友在真實板子上一次點亮流水燈看不出問題但一到做精確時鐘時就開始出bug根源就是預分頻系數(shù)跟自動重裝載值之間差的那個1沒有理解透。這兩個值寫進寄存器里的都是計數(shù)次數(shù)-1這是一個極其經(jīng)典的新手坑仿真時反而容易看出來——因為你可以暫停程序查看計數(shù)寄存器當前值確認它是不是從0一直加到設定的值。4.2 中斷回調與仿真觀察技巧初始化完成后真正的運行邏輯寫在定時器中斷回調函數(shù)里。調用HAL_TIM_Base_Start_IT啟動定時器后每當計數(shù)周期達到程序會停下主線任務跳進中斷回調執(zhí)行一次標記操作。void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { toggle_flag 1; } }在主循環(huán)里檢測這個標記并翻轉LED狀態(tài)最終效果就是每1毫秒產(chǎn)生一次中斷但LED以2毫秒為周期翻轉一次。仿真時你有兩個觀察窗口一個是定時器的寄存器窗口可以看到計數(shù)器實時累加一個是打斷點驗證中斷服務程序是否按預期頻率被喚醒。我自己實測時習慣在中斷回調第一行下一個斷點然后看右下角Call Stack窗口里的調用路徑。當程序每次從main函數(shù)跳到中斷回調這種主線被打斷的體感對理解CPU的中斷響應機制特別有幫助。純靠語言描述不如親眼看到一次。4.3 用邏輯分析窗口看PWM輸出定時器還有一個重要應用方向就是生成PWM波。CubeMX配置TIM2的某個通道為PWM生成模式設置好占空比初始值。代碼里只需要調一個函數(shù)修改比較寄存器值就可以改變占空比__HAL_TIM_SET_COMPARE(htim2, TIM_CHANNEL_1, 500);在真實板子上想看到PWM波形有條件可以上示波器沒有的話用萬用表只能讀到平均電壓根本看不到脈沖形態(tài)。而Keil的模擬器里自帶一個邏輯分析窗口添加變量后可以直接看到PWM信號的波形曲線。把比較值調成250、500、750波形圖上占空比的變化一目了然這比自己對著寄存器文檔腦補信號形態(tài)靠譜太多。不過要提醒一句邏輯分析窗口看到的波形是基于引腳電平變化狀態(tài)模擬出來的波形質量比真實示波器要粗糙但用于理解占空比概念和驗證代碼邏輯完全足夠。5. 串口通信在虛擬世界里聯(lián)調數(shù)據(jù)串口是STM32和外設、上位機、其他控制器打交道最常用的門戶也是很多同學入門時感覺玄乎的部分。仿真環(huán)境其實能把這個環(huán)節(jié)做得相當真實關鍵在于配置好之后要進行一次收發(fā)閉環(huán)驗證。5.1 printf重定向的兩種做法串口最常見的使用場景就是printf打印調試信息。在STM32上直接調printf不會輸出到任何地方因為標準庫的底層輸出函數(shù)沒有跟串口硬件建立連接需要把底層輸出重定向到串口發(fā)數(shù)據(jù)的接口上。主流做法有兩種一種是用MDK的微庫重寫fputc函數(shù)#include stdio.h int fputc(int ch, FILE *f) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 0xFFFF); return ch; }另一種是配合編譯器選項重寫底層函數(shù)寫法因工具鏈而異。入門階段用第一種就夠了。注意調用HAL_UART_Transmit最后一個參數(shù)是超時時間如果設置太短數(shù)據(jù)來不及被模擬器接收打印會顯得斷續(xù)設置成0xFFFF這種較大值能保證傳輸完成。5.2 虛擬串口終端與回環(huán)驗證純軟件模式下你的電腦上沒有真實的串口硬件怎么看到發(fā)出來的數(shù)據(jù)答案是使用Keil模擬器自帶的串口窗口。進入調試模式后打開串口窗口Serial Window選擇對應的串口編號#1。程序運行到printf語句時字符串會直接顯示在這個窗口里。要驗證接收功能直接在串口窗口的輸入框里鍵入一個字符程序里配置好的UART接收中斷服務程序就會被觸發(fā)在回調里可以讀取到這個字符并做出回應。我第一次在這個環(huán)境里做收發(fā)回環(huán)測試的時候心里還挺感嘆的虛擬世界里STM32串口把那一個字節(jié)收進了芯片內(nèi)部再從另一個狀態(tài)里送出來整個過程不需要任何物理連線但寄存器、中斷、數(shù)據(jù)緩沖區(qū)的處理邏輯跟真機沒有差別。把這一套流程走通后以后真機上接USB轉串口模塊也好、對接藍牙模塊也好至少你不會對數(shù)據(jù)流動的邏輯感到發(fā)怵。5.3 串口調試要注意的波特率一致性很多人第一次被串口通信折騰就是波特率不一致。仿真環(huán)境雖然省去了真實電平轉換的環(huán)節(jié)但雙方使用的波特率參數(shù)仍然需要匹配。為什么因為接收端是依據(jù)預設波特率來對數(shù)據(jù)進行采樣的兩邊速率不同接收方解析出的字節(jié)就會錯亂。Keil模擬器串口窗口本質上模擬了一個收發(fā)的邏輯端配置的是CubeMX里UART初始化的波特率參數(shù)。實際項目里PC端上位機軟件設置的波特率必須跟單片機里的配置一致這是鐵律。仿真階段記住這一點以后上板會省掉好多無謂的排查。注意仿真的串口數(shù)據(jù)流不經(jīng)過物理電平變化所以即便波特率不匹配程序可能不會報錯但你收到的數(shù)據(jù)內(nèi)容會是亂碼或丟失。兩者行為差異值得記在心里。6. 把外設組合在一起一個完整的小實驗單獨點燈、單獨定時器、單獨打印每個都很簡單但真正的入門成就感來自于把它們組合起來實現(xiàn)一個像那么回事的小功能。我自己在仿真環(huán)境里搭了一個經(jīng)典的復合實驗供你參考復現(xiàn)。6.1 實驗目標與配置清單我搭的是這樣一個場景一個按鍵決定系統(tǒng)進入運行模式LED以一定頻率閃爍同時通過串口每200毫秒打印一次狀態(tài)信息再按一次按鍵則退出運行模式。這個目標就要同時使用到GPIO輸出LED、GPIO輸入按鍵、定時器定期翻轉、UART打印信息四個外設。整個配置階段非常順理成章CubeMX里打開四樣外設生成工程。關鍵是在回調函數(shù)里做好互斥——不能用按鍵掃描阻塞定時器翻轉也不能在打印期間卡住主線太久。6.2 主程序邏輯這是我在調試過程中不斷調整后形成的版本去掉了無關緊要的部分只保留核心思路uint8_t running 0; uint8_t led_state 0; void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin KEY_Pin) { running running ? 0 : 1; } } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { if (running) { led_state !led_state; HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, led_state ? GPIO_PIN_SET : GPIO_PIN_RESET); } } } int main(void) { // ... 初始化部分由CubeMX生成 ... while (1) { if (running) { printf(System is running, LED state: %d\r\n, led_state); } HAL_Delay(200); } }代碼不復雜但有一個值得品一品的設計按鍵消抖在真實板子上是個繞不開的話題可在仿真環(huán)境里由于沒有真實的機械抖動信號EXTI引腳在模擬器中被鼠標點擊時只會產(chǎn)生一次電平變化所以不需要額外做延時消抖。這是仿真的簡化優(yōu)勢也是仿真的潛在陷阱——等到了真機上同樣的代碼可能因為沒消抖而產(chǎn)生錯誤的邊沿觸發(fā)這點必須要心里有數(shù)。6.3 仿真中的調試體驗復盤把這套組合實驗跑通我在仿真器里重點觀察了幾個數(shù)據(jù)位EXTI標志位是否在點擊引腳時及時置位、定時器中斷回調里的led_state翻轉是否穩(wěn)定、串口窗口打印的頻率是否符合200毫秒間隔。有意思的是問題真的被我抓到過一次。在中斷回調里我一開始把打印語句也放進去了結果串口窗口的輸出變得混亂且重復。排查后發(fā)現(xiàn)打印本身耗時較長定時器中斷又頻繁觸發(fā)導致回調還沒跑完新一輪中斷又來了。解決方法是把打印從回調挪到主循環(huán)用標志位去協(xié)調。這種中斷里不做耗時操作的原則在仿真里犯過一次印象會非常深刻比看十遍教科書都管用。7. 仿真之外往真實硬件過渡要注意的幾個落差寫到這里我覺得有必要專門用一個篇幅討論一下仿真和真機的差異。這不是潑冷水而是希望你在純軟件路線里獲得的經(jīng)驗不至于到真機上時被打個措手不及。7.1 電平與時序的真實性差異仿真中對IO引腳狀態(tài)的更新是立即生效的而真實芯片從CPU寫寄存器到引腳真正拉高需要經(jīng)過電平轉換、負載電容充電等物理過程存在一個微小但客觀存在的延遲。在低速外設場景點燈、串口9600波特率這種延遲可以完全忽略但在追求精確時序的場合比如模擬一些對外通信協(xié)議必須考慮到它。另一個常見落差在時鐘精度上。仿真環(huán)境使用的是理想化的時鐘頻率模型不會存在晶振溫漂、內(nèi)部RC振蕩器精度偏差這些因素。真實板子上的串口長時間通信可能會出現(xiàn)偶發(fā)亂碼相當一部分原因就是板載時鐘精度不夠。如果仿真階段從沒遇過這種問題上板時遇到反而容易一頭霧水。我將給你分享幾條硬件過渡的經(jīng)驗要做的是先跑一個最簡單的GPIO輸出程序驗證板子本身能不能工作而不是一上來就挑戰(zhàn)復雜的綜合例程。另外不要直接照搬仿真的引腳配置到真機先對照原理圖確認哪些引腳連接了按鍵、哪些連接了LED、哪些引腳被復用這步出錯的概率其實很高。7.2 調試手段的降級與補充仿真里你能隨便暫停、隨便看寄存器但真機上調試受制于調試器類型和連接穩(wěn)定性隨時暫停在大部分使用場景下是不可行的。這會導致一個典型的初學困境仿真跑得好好的程序到真機上掛死或運行邏輯詭異卻因為無法暫停而毫無頭緒。我的建議是在純軟件階段就有意識地培養(yǎng)借助代碼排查問題的能力比如打印關鍵變量、設置條件斷點、使用標志位觀測執(zhí)行流程。這些習慣在真機上同樣有效甚至更重要。養(yǎng)成通過程序自己觀測自己的習慣比依賴暫停仿真器來得更貼近實際開發(fā)。簡而言之純軟件路線是很好的起點但你得有意識地為下一次真實硬件之旅做鋪墊。不用急著現(xiàn)在買板子不過也不必把仿真當成取代硬件的萬金油。8. 回顧與幾個容易被低估的細節(jié)到了這一節(jié)我想把散落在各個步驟里容易被忽視但實際操作中相當關鍵的小點集中拎出來再講一遍。這些都是正文流程里出現(xiàn)過、但一句話帶過去的細節(jié)值得你反復體味。外設窗口要主動打開不會自動出現(xiàn)。模擬器里默認只顯示代碼和寄存器窗口GPIO、定時器、串口這些外設觀察窗口都要通過Peripherals菜單手動打開。不打開這些窗口仿真體驗直接從可視化變成盲調你會錯過最有價值的部分。單片機的引腳狀態(tài)位和邏輯詞經(jīng)常是反的。看GPIO窗口時GPIO Pin置高可能對應代碼里Reset狀態(tài)具體要根據(jù)電路邏輯去理解別跟概念較勁。理解置0復位、置1置位的稱呼分清物理狀態(tài)與邏輯狀態(tài)是兩套東西能少繞不少彎。虛擬串口窗口不要同時開多個。模擬器里同時打開多個串口窗口一個是調試起來容易串心流另一個是資源占用會拖慢模擬速度。按需使用用完關掉體驗更流暢。文件保存路徑別帶全英文字符之外的特殊符號。這個雖說是個人習慣問題但CubeMX生成工程時如果路徑含中文或空格后續(xù)編譯階段偶爾會出莫名其妙的報錯不如一開始就規(guī)避掉。這一點在我見過不少同學的實操里都踩過坑。時鐘樹頁面自己點一點理解一下。整個外設配置里時鐘樹的設置最容易應付了事卻也是最能幫你建立全局觀的地方。試著改一下總線分頻系數(shù)看看APB1外設時鐘和APB2外設時鐘的變化這比任何講解都直觀。如果你之前只看文字、沒有上手操作我強烈建議你現(xiàn)在就動手把環(huán)境搭起來。我?guī)缀蹩梢员WC在模擬器里親手跑通第一個GPIO點燈程序后你對嵌入式開發(fā)這個概念的理解會發(fā)生一次難得的具象化躍遷——你不再覺得它是一堆永遠摸不著門道的寄存器而是一套可以用邏輯和實驗去驗證的工程體系。