
玩STM32的人遲早要跟“燒錄”這兩個(gè)字打交道。不管是點(diǎn)亮第一顆LED還是調(diào)試復(fù)雜的電機(jī)控制算法你寫(xiě)好的程序最終都要經(jīng)過(guò)編譯、下載這一步才能跑在芯片上。而在所有燒錄工具里ST-LINK應(yīng)該是絕大多數(shù)新手接觸到的第一個(gè)調(diào)試器。它便宜、穩(wěn)定和Keil5配合起來(lái)也比較順手基本屬于“出廠標(biāo)配”級(jí)別的存在。但正因?yàn)槭菢?biāo)配很多人反而忽略了它背后的完整鏈路。我之前帶過(guò)不少剛?cè)腴T(mén)的朋友一上來(lái)就遇到“No ST-LINK detected”“Flash Download failed”這類(lèi)報(bào)錯(cuò)然后就開(kāi)始懷疑板子壞了、芯片壞了甚至直接把整個(gè)工程刪了重建——其實(shí)大概率是配置問(wèn)題或者接線問(wèn)題幾分鐘就能搞定。這篇文章我就把ST-LINK燒錄的整個(gè)流程徹底拆開(kāi)講一遍從原理到硬件接線從Keil5配置到問(wèn)題排查全部按實(shí)際操作的順序來(lái)。無(wú)論你是剛拿到開(kāi)發(fā)板的新手還是已經(jīng)被燒錄失敗折磨了一會(huì)兒的“準(zhǔn)新手”照著下面一步步來(lái)基本能走通。1. 先搞明白燒錄是怎么回事再動(dòng)手配工具1.1 燒錄的本質(zhì)把程序?qū)戇M(jìn)芯片的Flash很多人把“燒錄”理解成“把程序復(fù)制到芯片里”這個(gè)說(shuō)法方向沒(méi)錯(cuò)但不完整。STM32的程序最終存在芯片內(nèi)部的Flash存儲(chǔ)器里而燒錄的本質(zhì)就是通過(guò)調(diào)試器ST-LINK把編譯好的機(jī)器碼文件一般是 .hex 或者 .axf通過(guò)特定的通信協(xié)議寫(xiě)入Flash的指定地址。注意“特定通信協(xié)議”這幾個(gè)字。也就是說(shuō)ST-LINK和芯片之間是有約定通信方式的不是簡(jiǎn)單地把兩根線接上就能傳數(shù)據(jù)。STM32支持多種調(diào)試接口日常開(kāi)發(fā)中用得最多的就是SWDSerial Wire Debug和JTAG。SWD只需要兩根線SWDIO、SWCLK加上電源和地就能完成下載和調(diào)試JTAG用的線更多功能更全但實(shí)際開(kāi)發(fā)中絕大多數(shù)場(chǎng)景用SWD就夠了。ST-LINK/V2和很多板載ST-LINK默認(rèn)都支持SWD模式這也是為什么你經(jīng)??吹剿母虐罹€就能完成燒錄的原因。理解了這一點(diǎn)你就能明白為什么好多問(wèn)題會(huì)出在“接線沒(méi)接對(duì)”“接觸不良”“供電不足”上了——燒錄本質(zhì)上是一次高速的通信線沒(méi)通、電平不對(duì)程序自然寫(xiě)不進(jìn)去。所以遇到任何燒錄失敗第一步永遠(yuǎn)不是懷疑Keil配置而是先確認(rèn)硬件通路是否正常。1.2 為什么燒錄會(huì)失敗從編譯到下載的三個(gè)環(huán)節(jié)要排查問(wèn)題首先得知道程序的“旅程”分幾步。簡(jiǎn)單來(lái)說(shuō)整個(gè)過(guò)程分為三段第一段是編譯。Keil里的C代碼編譯后會(huì)生成中間文件最終鏈接成可執(zhí)行文件。如果編譯就報(bào)錯(cuò)那根本走不到燒錄那一步。第二段是連接。ST-LINK通過(guò)USB連到電腦通過(guò)SWD接口連到STM32芯片。電腦要能識(shí)別ST-LINKST-LINK要能探測(cè)到芯片。這一步最容易出問(wèn)題也是新手的重災(zāi)區(qū)驅(qū)動(dòng)沒(méi)裝好、USB口供電不足、SWD線序接錯(cuò)、芯片進(jìn)入了低功耗模式、甚至芯片被“鎖死”了都會(huì)導(dǎo)致連接失敗。第三段是寫(xiě)入。ST-LINK把程序數(shù)據(jù)通過(guò)SWD協(xié)議寫(xiě)入Flash同時(shí)還會(huì)做擦除、校驗(yàn)等操作。如果Flash算法選錯(cuò)、芯片型號(hào)選錯(cuò)、芯片保護(hù)位被設(shè)置都會(huì)在這一步報(bào)錯(cuò)。所以你會(huì)發(fā)現(xiàn)排查燒錄問(wèn)題的思路其實(shí)是線性的先保證硬件通路再確認(rèn)驅(qū)動(dòng)識(shí)別最后檢查軟件配置。很多人一上來(lái)就亂改Keil設(shè)置結(jié)果越改越亂就是因?yàn)闆](méi)按照這個(gè)遞進(jìn)關(guān)系來(lái)排查。下面我就按這個(gè)順序把每一步都講透。2. 硬件和驅(qū)動(dòng)ST-LINK選型、接線、裝驅(qū)動(dòng)2.1 先選對(duì)你的ST-LINK獨(dú)立版和板載版ST-LINK目前市面上能見(jiàn)到的形態(tài)大致分兩類(lèi)。一類(lèi)是獨(dú)立的小盒子最常見(jiàn)的是ST-LINK/V2淘寶上十幾塊到幾十塊不等另一類(lèi)是集成在開(kāi)發(fā)板上的電路比如很多Nucleo板、正點(diǎn)原子/野火的板子板子自帶ST-LINK通過(guò)USB線連接電腦就能直接燒錄。如果你的板子自帶ST-LINK那基本不用操心電源和接線問(wèn)題直接用USB線連電腦即可。如果用的是獨(dú)立的ST-LINK/V2那就要注意接線了。獨(dú)立ST-LINK/V2接口一般有SWD和JTAG兩排引腳新手只需要盯住SWD那四個(gè)腳3.3V、SWDIO、SWCLK、GND。有的ST-LINK還會(huì)引出5V引腳但燒錄STM32用3.3V就夠千萬(wàn)別拿5V去懟芯片的3.3V引腳除非你的板子明確支持5V供電。這里有一個(gè)我見(jiàn)過(guò)很多次的翻車(chē)現(xiàn)場(chǎng)——把5V接到了3.3V引腳上芯片要么直接冒煙要么發(fā)熱嚴(yán)重直接報(bào)廢。另外提一句市面上有些號(hào)稱(chēng)“ST-LINK”的其實(shí)是“V2山寨版”或者“V2克隆版”芯片是第三方仿制的。絕大多數(shù)情況下它們也能正常使用但偶爾會(huì)出現(xiàn)固件問(wèn)題導(dǎo)致Keil識(shí)別異常。如果你發(fā)現(xiàn)某個(gè)ST-LINK怎么配置都連不上芯片換一個(gè)正品或者換一個(gè)型號(hào)試試往往是解決問(wèn)題的捷徑。2.2 接線錯(cuò)了能燒毀芯片這事真不是開(kāi)玩笑接線是新手最容易翻車(chē)的地方而且一旦接錯(cuò)輕則燒錄失敗重則損壞芯片。以STM32F103C8T6這種“網(wǎng)紅芯片”為例它常用的SWD引腳是PA13SWDIO和PA14SWCLK。在絕大多數(shù)最小系統(tǒng)板和開(kāi)發(fā)板上這兩個(gè)引腳都會(huì)被引出來(lái)旁邊還有3.3V和GND直接用杜邦線對(duì)應(yīng)接到ST-LINK上就行。這里有幾個(gè)細(xì)節(jié)值得注意。第一個(gè)是線序。杜邦線的顏色并不統(tǒng)一不要默認(rèn)“紅線就是電源、黑線就是地”。我看過(guò)太多人照著別人的圖片接結(jié)果對(duì)方用的線序和自己的不一樣白白費(fèi)了半天時(shí)間。最靠譜的做法是拿萬(wàn)用表的通斷檔測(cè)一下ST-LINK引腳上絲印和實(shí)際引腳的對(duì)應(yīng)關(guān)系確認(rèn)無(wú)誤后再接芯片。第二個(gè)是接觸問(wèn)題。杜邦線母頭用久了容易松動(dòng)尤其是反復(fù)插拔之后會(huì)出現(xiàn)“看起來(lái)接上了實(shí)際上沒(méi)接通”的假象。如果你遇到燒錄時(shí)好時(shí)壞的情況可以試試按壓線頭或者換一根新杜邦線很多時(shí)候問(wèn)題就解決了。實(shí)在不行直接焊幾根線上去一勞永逸。第三個(gè)是供電問(wèn)題。有的ST-LINK/3.3V引腳輸出電流有限如果你用它給整個(gè)開(kāi)發(fā)板供電而板子上又有傳感器、顯示屏、舵機(jī)等外設(shè)可能會(huì)導(dǎo)致電壓跌落燒錄時(shí)芯片不穩(wěn)定。穩(wěn)妥的做法是開(kāi)發(fā)板用USB或者外部電源供電ST-LINK只負(fù)責(zé)燒錄和調(diào)試兩邊共地即可。共地這個(gè)點(diǎn)容易被忽略但如果你的板子供電和ST-LINK的供電不是同一個(gè)來(lái)源就一定要把GND連起來(lái)否則通信電平?jīng)]有參考基準(zhǔn)數(shù)據(jù)會(huì)亂掉。2.3 驅(qū)動(dòng)安裝與驗(yàn)證如何判斷電腦已經(jīng)識(shí)別ST-LINK硬件接好之后你還需要讓電腦認(rèn)識(shí)ST-LINK。大部分ST-LINK都是免驅(qū)或者自動(dòng)安裝驅(qū)動(dòng)的但如果你的系統(tǒng)比較老或者用了精簡(jiǎn)版系統(tǒng)可能就需要手動(dòng)裝一下。去ST官方網(wǎng)站搜索“ST-LINK driver”就能找到官方驅(qū)動(dòng)安裝包下載安裝后把ST-LINK插到電腦上。這時(shí)打開(kāi)設(shè)備管理器在“端口(COM和LPT)”或者“通用串行總線設(shè)備”下面應(yīng)該能看到一個(gè)名為“ST-LINK”或者“STM32 ST-LINK”的設(shè)備。如果看到的是一個(gè)帶黃色感嘆號(hào)或者問(wèn)號(hào)的未知設(shè)備那就說(shuō)明驅(qū)動(dòng)沒(méi)裝好需要手動(dòng)更新驅(qū)動(dòng)或者重新安裝。另外很多人會(huì)安裝STM32 ST-LINK Utility這個(gè)軟件。它除了可以燒錄程序外還有一個(gè)很實(shí)用的功能幫你確認(rèn)ST-LINK是否和芯片正常通信。打開(kāi)軟件點(diǎn)擊“Connect to the target”如果能夠正常識(shí)別到芯片型號(hào)和Flash大小就說(shuō)明硬件鏈路和驅(qū)動(dòng)都沒(méi)問(wèn)題。如果這里都連不上那后面Keil里再怎么折騰也是白搭。我這里多說(shuō)一句STM32 ST-LINK Utility在“芯片鎖死”的場(chǎng)景下幾乎是救命稻草。STM32有讀寫(xiě)保護(hù)機(jī)制如果你不小心在選項(xiàng)中開(kāi)啟了讀保護(hù)那么Keil里燒錄會(huì)報(bào)錯(cuò)但ST-LINK Utility里可以用“Connect under reset”的方式連接然后執(zhí)行全片擦除把芯片恢復(fù)出廠狀態(tài)。后面我在常見(jiàn)問(wèn)題部分會(huì)再詳細(xì)講。3. Keil5里的關(guān)鍵配置一步都不能錯(cuò)3.1 工程配置第一步Debug選項(xiàng)卡里的ST-LINK設(shè)置驅(qū)動(dòng)裝好、硬件接好之后剩下的戰(zhàn)場(chǎng)就在Keil5里了。很多人都知道要配置工程選項(xiàng)魔術(shù)棒但不知道每一項(xiàng)具體是干嘛的只會(huì)抄別人的截圖一旦遇到和自己工程不一樣的界面就懵。打開(kāi)Keil5的“Options for Target”界面切換“Debug”選項(xiàng)卡右下角有個(gè)下拉框這里要選擇調(diào)試器。如果你用ST-LINK就要選“ST-Link Debugger”如果選成了J-LINK或者CMSIS-DAP那ST-LINK當(dāng)然不會(huì)被識(shí)別。這里聽(tīng)起來(lái)像廢話但確實(shí)有人因?yàn)檠b了多個(gè)調(diào)試器驅(qū)動(dòng)之后下拉框被改了還不知道。選好之后點(diǎn)擊旁邊的“Settings”按鈕會(huì)彈出一個(gè)“Cortex-M Target Driver Setup”窗口。正常情況下“Debug”區(qū)域會(huì)顯示“ST-LINK/V2”并且SW Device區(qū)域會(huì)列出一個(gè)ARM CoreSight SW-DP設(shè)備。如果這個(gè)窗口里什么都看不到或者顯示“No target connected”那就說(shuō)明ST-LINK沒(méi)有連到芯片需要回頭檢查接線和驅(qū)動(dòng)。這個(gè)窗口里還有幾個(gè)參數(shù)值得關(guān)注。第一個(gè)是Max Clock默認(rèn)可能是4MHz或者更高但如果你的接線比較長(zhǎng)或者杜邦線質(zhì)量一般可以把它降到1MHz試試能顯著提高連接穩(wěn)定性。第二個(gè)是接口模式要確保選的是SW模式而不是JTAG因?yàn)榇蠖鄶?shù)板子都是按SWD接口引出的。第三個(gè)是Port下拉框一般自動(dòng)識(shí)別即可但如果燒錄不正??梢允謩?dòng)切換試試。3.2 Flash Download設(shè)置算法選不對(duì)程序?qū)懖贿M(jìn)去Debug選項(xiàng)卡配置完成只是第一步真正決定燒錄成敗的是“Flash Download”這個(gè)不起眼的小區(qū)域。你選擇的芯片型號(hào)不同要用的下載算法Programming Algorithm也不同。STM32F103系列一般選“STM32F10x Med-density Flash”STM32F407系列選“STM32F4xx Flash”如果選錯(cuò)了Keil在燒錄時(shí)會(huì)提示找不到匹配的Flash算法直接報(bào)錯(cuò)。我見(jiàn)過(guò)不少新手工程是從別人那里拷來(lái)的Debug那邊改成了自己的ST-LINK但Flash Download里的算法還是別人芯片型號(hào)的結(jié)果燒錄怎么都不成功。所以這里一定要確認(rèn)你的工程Target芯片型號(hào)Device選項(xiàng)卡里的芯片型號(hào)和Flash算法是匹配的。另外Flash Download區(qū)域里還有幾個(gè)勾選項(xiàng)Erase Full Chip全片擦除、Erase Sectors扇區(qū)擦除、Program編程、Verify校驗(yàn)、Reset and Run下載后自動(dòng)復(fù)位運(yùn)行。新手我建議第一次燒錄或者程序變動(dòng)很大的時(shí)候勾選“Erase Full Chip”確保沒(méi)有殘存的數(shù)據(jù)干擾日常調(diào)試時(shí)用“Erase Sectors”就行燒錄速度更快“Reset and Run”建議勾上燒錄完自動(dòng)運(yùn)行省去手動(dòng)按復(fù)位鍵的麻煩。這里的“Verify”選項(xiàng)也建議保持勾選燒錄完成后會(huì)回讀校驗(yàn)程序是否有問(wèn)題一清二楚。多花幾秒鐘換一個(gè)放心。3.3 Utilities選項(xiàng)卡與復(fù)位設(shè)置容易被忽略的兩處細(xì)節(jié)“Debug”選項(xiàng)卡核對(duì)無(wú)誤后還要看一眼“Utilities”選項(xiàng)卡。這里上面有一個(gè)下拉框默認(rèn)應(yīng)該是“ST-Link Debugger”。點(diǎn)擊右邊的“Settings”按鈕會(huì)發(fā)現(xiàn)里面的界面和之前的Flash Download設(shè)置類(lèi)似。簡(jiǎn)單來(lái)說(shuō)Utilities選項(xiàng)卡的作用就是告訴Keil“燒錄的時(shí)候該用哪個(gè)工具鏈”。如果你這里選的是別的調(diào)試器或者Settings里的算法不對(duì)也會(huì)導(dǎo)致燒錄異常。再補(bǔ)充一個(gè)很多人問(wèn)到的“Reset and Run”不生效的問(wèn)題。有時(shí)候你明明勾選了Reset and Run但燒錄完成后程序并沒(méi)有跑起來(lái)而是停在調(diào)試狀態(tài)或者黑屏。這種情況在部分STM32型號(hào)上會(huì)出現(xiàn)原因是復(fù)位方式選擇不對(duì)。在Utilities的Settings里有一個(gè)“Reset”相關(guān)的設(shè)置有的芯片選“HW RESET”比較可靠有的選“SYSRESETREQ”更穩(wěn)定。如果你發(fā)現(xiàn)程序沒(méi)自動(dòng)運(yùn)行可以試著切換這里然后重新燒錄。還有兩個(gè)和Keil5相關(guān)的“經(jīng)典玄學(xué)”一個(gè)是Target選項(xiàng)卡里的XTAL晶振頻率置灰。很多人會(huì)發(fā)現(xiàn)XTAL這一欄是灰色的改不了。這是因?yàn)樗怯蒁evice選項(xiàng)卡里選擇的芯片型號(hào)自動(dòng)決定的所以不需要手動(dòng)改也不是配置錯(cuò)誤。另一個(gè)是Keil5裝了C51版和MDK版共存時(shí)可能出現(xiàn)工程無(wú)法編譯、限制2K代碼的情況。如果你同時(shí)裝了C51和MDK需要確認(rèn)你打開(kāi)的是MDK版而不是C51版否則確實(shí)會(huì)有2K限制的提示但那不是STM32的問(wèn)題是工具鏈選錯(cuò)了。3.4 工程整體檢查這幾個(gè)基礎(chǔ)項(xiàng)別等翻車(chē)了再回頭看在配置完Debug和Utilities之后我強(qiáng)烈建議你順手檢查一下工程的其他幾個(gè)基礎(chǔ)選項(xiàng)因?yàn)闊浭∮袝r(shí)候是“上游”問(wèn)題導(dǎo)致的。第一個(gè)是Device選項(xiàng)卡里的芯片型號(hào)。如果這里選的芯片和你手里真正用的不是同一個(gè)系列比如你用的是STM32F103C8T6但工程里選的是STM32F103RCT6Flash大小、SRAM大小都不同燒錄時(shí)可能出現(xiàn)地址越界或者算法不匹配的警告嚴(yán)重點(diǎn)直接失敗。第二個(gè)是Output選項(xiàng)卡里的“Create HEX File”。如果你需要生成.hex文件比如用ST-LINK Utility、J-Flash或者其他工具單獨(dú)燒錄一定要把這里勾上。如果你只是在Keil里直接下載不生成hex其實(shí)也能燒錄但建議還是勾上方便后續(xù)備用。第三個(gè)是工程的編譯輸出。配置完所有設(shè)置后先點(diǎn)一下“Build”確保編譯通過(guò)生成0 Error 0 Warning或者至少0 Error。如果編譯都不過(guò)后面的一切都是空談。4. 完整燒錄實(shí)操?gòu)木幾g到驗(yàn)證一把過(guò)4.1 第一次完整燒錄按這個(gè)順序來(lái)基本不會(huì)翻車(chē)配置做完之后就到了最暢快的一步把程序燒進(jìn)芯片。這里我按實(shí)際操作順序復(fù)盤(pán)一遍完整的流程。先把ST-LINK和開(kāi)發(fā)板接好把ST-LINK插上電腦USB口。然后打開(kāi)你的Keil5工程先點(diǎn)一下“Rebuild”按鈕確保編譯通過(guò)。接著點(diǎn)一下“LOAD”按鈕就是那個(gè)向下的紅色箭頭Keil就會(huì)開(kāi)始連接ST-LINK自動(dòng)擦除Flash、寫(xiě)入程序、校驗(yàn)數(shù)據(jù)。如果一切順利你會(huì)在輸出窗口看到“Flash Load finished successfully”之類(lèi)的提示同時(shí)開(kāi)發(fā)板上對(duì)應(yīng)的程序開(kāi)始運(yùn)行。但很多新手在這一步會(huì)遇到一個(gè)很奇怪的現(xiàn)象Keil提示燒錄成功了程序卻沒(méi)反應(yīng)。這時(shí)候不要慌先檢查兩個(gè)點(diǎn)第一程序是否真的燒錄進(jìn)去了——可以用調(diào)試器進(jìn)入Debug模式在代碼里打斷點(diǎn)看PC指針是否停在main函數(shù)第二程序是否真的“跑”了——如果芯片供電正常、復(fù)位引腳正常但程序沒(méi)反應(yīng)可能是晶振或者復(fù)位電路的問(wèn)題這個(gè)跟燒錄關(guān)系不大屬于硬件問(wèn)題。這里我要特別提醒一個(gè)技巧燒錄完成后盡量養(yǎng)成“斷開(kāi)調(diào)試器再運(yùn)行”的習(xí)慣。雖然ST-LINK供電情況下程序也能跑但調(diào)試器的連接會(huì)對(duì)芯片的某些引腳狀態(tài)產(chǎn)生影響尤其是用到SWD引腳做普通IO的時(shí)候調(diào)試器連接會(huì)干擾程序運(yùn)行。所以最好把USB線拔掉讓板子獨(dú)立供電再觀察現(xiàn)象。4.2 燒錄文件的選擇hex、axf與bin的區(qū)別很多項(xiàng)目要求你提交一個(gè)燒錄文件而不是讓最終用戶(hù)安裝Keil和ST-LINK去燒錄。這時(shí)候就需要理解燒錄文件的區(qū)別了。在Keil5編譯的Output文件夾里你會(huì)看到一堆文件.axf、.hex、.bin等。其中.axf是Keil調(diào)試和下載用的主力格式它包含了調(diào)試符號(hào)信息Keil直接用它燒錄和調(diào)試.hex是Intel HEX格式的文本文件把地址和數(shù)據(jù)都編碼成了ASCII字符是單片機(jī)領(lǐng)域最通用的燒錄格式之一ST-LINK Utility、J-Flash、各種串口下載工具都支持.bin是純二進(jìn)制文件沒(méi)有任何地址信息燒錄時(shí)必須指定起始地址一般用于OTA升級(jí)或者做BootLoader時(shí)使用。日常自己玩用Keil直接下載就行如果要把程序發(fā)給別人量產(chǎn)或者遠(yuǎn)程升級(jí)一般給.hex文件。對(duì)于STM32F103這種從0x08000000地址啟動(dòng)的芯片.hex文件里已經(jīng)包含了地址信息直接下就行。如果你用STM32 ST-LINK Utility燒錄點(diǎn)“Open file”選擇.hex再點(diǎn)“Program verify”就能完成燒錄。4.3 用定時(shí)器做一個(gè)最簡(jiǎn)單的驗(yàn)證程序理論說(shuō)再多不如實(shí)際跑一段代碼。這里我以STM32F103系列為例寫(xiě)一個(gè)最簡(jiǎn)單的定時(shí)器翻轉(zhuǎn)程序用來(lái)驗(yàn)證你的燒錄鏈路是否完全正常。這個(gè)程序用TIM2產(chǎn)生中斷在中斷里翻轉(zhuǎn)PC13引腳的電平如果你用正點(diǎn)原子或者野火的板子板載LED一般連在PC13或者PB0/PB1請(qǐng)根據(jù)實(shí)際原理圖調(diào)整。#include stm32f10x.h void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) ! RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13))); } } int main(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_2MHz; GPIO_Init(GPIOC, GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period 999; TIM_TimeBaseStructure.TIM_Prescaler 7199; TIM_TimeBaseStructure.TIM_ClockDivision 0; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_Cmd(TIM2, ENABLE); NVIC_InitStructure.NVIC_IRQChannel TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority 0; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); while (1); }這段代碼的邏輯很樸素72MHz系統(tǒng)時(shí)鐘TIM2時(shí)鐘來(lái)自APB1在系統(tǒng)時(shí)鐘72MHz時(shí)APB1最大是36MHz但TIM2的時(shí)鐘是APB1的兩倍即72MHz分頻數(shù)71991等于7200所以計(jì)數(shù)頻率是10kHz自動(dòng)重裝值9991等于1000這樣就得到了10Hz的中斷頻率即LED每秒翻轉(zhuǎn)10次。如果你把這兩個(gè)參數(shù)配好燒錄成功后LED應(yīng)該以肉眼可見(jiàn)的頻率閃爍大約每秒閃5個(gè)完整周期。這里也順便回應(yīng)一下熱搜詞“STM32測(cè)頻法”和“STM32定時(shí)器”定時(shí)器中斷只是最基礎(chǔ)的用法但燒錄鏈路是否正常用這個(gè)例子來(lái)驗(yàn)證非常直觀。如果你的LED在燒錄后正常閃爍說(shuō)明從編譯、下載、復(fù)位到程序運(yùn)行整條鏈路完全打通了。5. 常見(jiàn)問(wèn)題速查這些坑我基本都踩過(guò)5.1 常見(jiàn)問(wèn)題與解決思路一覽燒錄問(wèn)題翻來(lái)覆去就那么幾類(lèi)我整理了一個(gè)速查表基本上覆蓋了99%的新手場(chǎng)景現(xiàn)象可能原因排查方向Keil提示No ST-LINK detectedUSB線問(wèn)題、驅(qū)動(dòng)沒(méi)裝好、ST-LINK本身壞了換USB口、重裝驅(qū)動(dòng)、用ST-LINK Utility確認(rèn)能否識(shí)別Keil能識(shí)別ST-LINK但找不到芯片SWD接線錯(cuò)誤、芯片供電異常、芯片處于低功耗/鎖死狀態(tài)檢查接線和供電、嘗試Connect under Reset、全片擦除燒錄報(bào)Flash Download failedFlash算法選錯(cuò)、芯片型號(hào)不匹配、芯片F(xiàn)lash保護(hù)核對(duì)Flash算法與芯片型號(hào)、在Utility里執(zhí)行全片擦除燒錄成功但程序不運(yùn)行Reset and Run未勾選、復(fù)位電路異常、晶振沒(méi)起振手動(dòng)按復(fù)位鍵、勾選Reset and Run、檢查RST引腳和外部晶振燒錄速度很慢SWD時(shí)鐘頻率過(guò)高、杜邦線太長(zhǎng)/質(zhì)量差在Debug設(shè)置里把Max Clock降到1MHz換了電腦后燒錄失敗新電腦缺驅(qū)動(dòng)、Keil工程里的調(diào)試器配置被重置重新安裝ST-LINK驅(qū)動(dòng)、檢查Debug選項(xiàng)卡是否還是ST-Link Debugger提示RDDI-DAP Error接線不良、目標(biāo)芯片供電不足、調(diào)試口被程序占用檢查接線、單獨(dú)給板子供電、將BOOT0拉高后重新上電連接提示Cannot access target芯片讀保護(hù)開(kāi)啟、SWD引腳被復(fù)用用ST-LINK Utility執(zhí)行Connect under Reset并全片擦除這張表里的場(chǎng)景絕大多數(shù)我都實(shí)際遇到過(guò)。尤其是“RDDI-DAP Error”和“Cannot access target”這兩個(gè)報(bào)錯(cuò)在剛接觸STM32時(shí)特別嚇人看著像是芯片變磚了其實(shí)大部分情況下只是接線不良或者芯片讀保護(hù)開(kāi)了。5.2 芯片鎖死也不怕ST-LINK Utility救磚實(shí)操這里單獨(dú)把“芯片鎖死”拿出來(lái)講一下因?yàn)樘嗳嗽谶@里被嚇到了。STM32有Flash讀保護(hù)機(jī)制如果你用過(guò)STM32CubeProgrammer或者ST-LINK Utility的選項(xiàng)字節(jié)功能不小心把讀保護(hù)級(jí)別從Level 0切到了Level 1那么芯片的Flash就無(wú)法通過(guò)調(diào)試器正常讀寫(xiě)Keil燒錄時(shí)會(huì)報(bào)“Cannot access target”或者類(lèi)似錯(cuò)誤。很多人的第一反應(yīng)是“完了芯片報(bào)廢了”其實(shí)不是。STM32在Level 1讀保護(hù)下可以通過(guò)一種特殊方式解除把BOOT0引腳拉高然后復(fù)位芯片讓芯片從System Memory啟動(dòng)Bootloader模式然后再用ST-LINK連接執(zhí)行全片擦除。全片擦除之后讀保護(hù)級(jí)別會(huì)自動(dòng)降回Level 0芯片就恢復(fù)正常了。如果你用帶板載ST-LINK的開(kāi)發(fā)板一般板子上都有一個(gè)BOOT0跳線帽或者按鍵操作起來(lái)非常方便。這個(gè)操作用STM32 ST-LINK Utility來(lái)完成最方便打開(kāi)軟件按住芯片的復(fù)位鍵或者拉BOOT0到高電平后重新上電點(diǎn)擊“Connect under Reset”軟件連接到芯片后選擇“Target”菜單下的“Erase Chip”等進(jìn)度條跑完芯片就解鎖了。之后回到Keil你會(huì)發(fā)現(xiàn)燒錄又正常了。5.3 幾個(gè)容易忽略的“隱性”問(wèn)題除了上面這些好識(shí)別的報(bào)錯(cuò)還有一些問(wèn)題不會(huì)報(bào)錯(cuò)但會(huì)給你添亂。一個(gè)是供電問(wèn)題。有些USB口供電能力弱尤其是臺(tái)式機(jī)前置USB口或者老筆記本的USB口插上ST-LINK后電壓不足導(dǎo)致燒錄時(shí)好時(shí)壞。這時(shí)候換一個(gè)后置USB口或者用帶供電的USB HUB往往能解決。還有一個(gè)更隱蔽的問(wèn)題如果開(kāi)發(fā)板和ST-LINK由兩個(gè)不同的USB口供電但兩邊地沒(méi)連在一起也會(huì)導(dǎo)致通信不穩(wěn)定。所以要么用同一個(gè)USB口供電要么確保共地。另一個(gè)問(wèn)題是Keil5的版本和芯片支持包Device Pack版本不匹配。有時(shí)候你從網(wǎng)上下載的工程用了老版本的芯片庫(kù)而你當(dāng)前的Keil5版本太高或者芯片支持包沒(méi)裝全會(huì)導(dǎo)致工程編譯時(shí)報(bào)一堆找不到頭文件的錯(cuò)誤。這種情況不是燒錄本身的問(wèn)題但確實(shí)會(huì)卡住你燒錄前的最后一步。建議安裝Keil5時(shí)就一次性裝好對(duì)應(yīng)芯片廠商的DFP包Device Family Pack比如STM32F1系列的“Keil.STM32F1xx_DFP”。再提一個(gè)和“J-Link”有關(guān)的小坑。有些開(kāi)發(fā)板默認(rèn)是給J-Link使用的或者板載調(diào)試器是CMSIS-DAP你非要用ST-LINK去連發(fā)現(xiàn)怎么也連不上。這時(shí)候先看板子上的調(diào)試器是什么型號(hào)再選擇對(duì)應(yīng)的驅(qū)動(dòng)和Keil配置不要認(rèn)準(zhǔn)ST-LINK就不撒手。J-Link燒錄STM32的流程和ST-LINK類(lèi)似只是在Keil的Debug選項(xiàng)卡里選“J-LINK/J-TRACE Cortex”其他配置思路基本一致。5.4 燒錄成功后的調(diào)試小技巧最后再分享幾個(gè)燒錄成功之后實(shí)際調(diào)試會(huì)用到的小技巧。第一個(gè)是善用Keil的Debug功能。很多人燒錄成功就關(guān)掉Keil直接看在板子上的現(xiàn)象。但如果程序行為不符合預(yù)期更高效的方式是進(jìn)入Debug模式在全速運(yùn)行前打斷點(diǎn)或者利用Watch窗口查看變量的實(shí)時(shí)值。STM32的調(diào)試功能很強(qiáng)大內(nèi)置的SWVSerial Wire Viewer可以直接通過(guò)SWDIO引腳輸出printf信息不需要額外的串口線。不過(guò)要啟用SWV功能你需要把Debug選項(xiàng)卡里的設(shè)置改成“Trace”模式并且把系統(tǒng)時(shí)鐘頻率填對(duì)否則打印出來(lái)的波特率是亂的。第二個(gè)是學(xué)會(huì)使用邏輯分析儀或者示波器驗(yàn)證時(shí)序。程序燒錄成功之后如果你想確認(rèn)PWM波形、串口波形是否正常直接用邏輯分析儀抓一下引腳電平。很多便宜的USB邏輯分析儀就夠用不必一開(kāi)始就上幾千塊的示波器。這個(gè)習(xí)慣能幫你把“程序燒進(jìn)去了”和“程序功能正確”這兩件事區(qū)分開(kāi)排查效率會(huì)高很多。第三個(gè)是注意SWD引腳被復(fù)用的問(wèn)題。如果你在代碼里把PA13或PA14配置成了普通GPIO或者開(kāi)啟了JTAG/SWD的禁用設(shè)置那么下次燒錄時(shí)ST-LINK就找不到芯片了。解決辦法是用前面提到的“Connect under Reset”方式連接或者把BOOT0拉高進(jìn)Bootloader后連接然后把代碼擦掉。如果你經(jīng)常調(diào)試建議不要輕易把SWD引腳復(fù)用作其他功能特別是在調(diào)試階段。我在實(shí)際帶新人的過(guò)程中也發(fā)現(xiàn)還有一個(gè)特別容易被忽視的點(diǎn)很多人喜歡一邊開(kāi)著STM32 ST-LINK Utility一邊開(kāi)著Keil兩個(gè)軟件同時(shí)在搶占ST-LINK端口。如果你發(fā)現(xiàn)Keil偶爾連不上ST-LINK可以先看看后臺(tái)是不是還掛著ST-LINK Utility沒(méi)有關(guān)閉。類(lèi)似的情況也會(huì)出現(xiàn)在用STM32CubeProgrammer燒錄時(shí)CubeProgrammer和Keil搶同一個(gè)調(diào)試器互相報(bào)錯(cuò)。燒錄這件事說(shuō)白了就是“硬件通路 驅(qū)動(dòng)識(shí)別 軟件配置”的三角關(guān)系任何一個(gè)環(huán)節(jié)斷了都會(huì)出問(wèn)題。但只要你按照本文的順序先把接線和驅(qū)動(dòng)搞定再核對(duì)Keil里的Debug、Flash Download、Utilities這幾塊設(shè)置絕大多數(shù)燒錄失敗都能在十分鐘內(nèi)解決。最后想說(shuō)的是不要害怕報(bào)錯(cuò)STM32的報(bào)錯(cuò)信息絕大多數(shù)都是“明確的提示”它已經(jīng)告訴你問(wèn)題出在哪了。你需要的只是一套系統(tǒng)的排查思路而這也是這篇內(nèi)容最想讓你拿走的東西。