習(xí)板實(shí)戰(zhàn):從CubeMX到USB/CAN通信)
簡(jiǎn)介面向嵌入式學(xué)習(xí)者的這款STM32F072C8T6學(xué)習(xí)板資料包基于ARM Cortex-M0內(nèi)核主打低功耗與高性能適用于物聯(lián)網(wǎng)、智能家居、消費(fèi)電子等場(chǎng)景。壓縮包內(nèi)含2000個(gè)文件總體積約168.69MB文件類(lèi)型以C語(yǔ)言源碼、頭文件、工程配置文件、HTML文檔為主同時(shí)包含Keil、IAR等集成開(kāi)發(fā)環(huán)境的工程與芯片手冊(cè)資料便于直接打開(kāi)參考。資料提供21個(gè)示例程序覆蓋GPIO、定時(shí)器、UART、SPI、I2C、ADC、DAC、CAN、USB以及RTOS和TCP/IP協(xié)議棧等內(nèi)容可幫助開(kāi)發(fā)者由淺入深掌握初始化、中斷處理、外設(shè)驅(qū)動(dòng)和內(nèi)存管理等核心技能。每個(gè)例程均配有可直接編譯的工程文件與注釋部分涉及無(wú)線通信和網(wǎng)絡(luò)協(xié)議適合作為項(xiàng)目起步模板。配套用戶手冊(cè)與電路圖進(jìn)一步完善了硬件設(shè)計(jì)與調(diào)試信息方便對(duì)照實(shí)踐降低排查問(wèn)題難度。目前已有1197人學(xué)習(xí)下載適合希望系統(tǒng)入門(mén)STM32F072并積累嵌入式項(xiàng)目經(jīng)驗(yàn)的開(kāi)發(fā)者。 今天想聊一聊極客良品這塊STM32F072C8T6學(xué)習(xí)板。很多人一提到嵌入式入門(mén)第一反應(yīng)是STM32F103玩的人多、教程多但真上手后會(huì)發(fā)現(xiàn)F103那顆芯片在M3內(nèi)核里其實(shí)有不少?gòu)?fù)雜度是新手暫時(shí)用不上的。F072雖然是一顆M0內(nèi)核的低成本芯片卻把USB、CAN這類(lèi)“高級(jí)外設(shè)”塞了進(jìn)來(lái)非常適合做學(xué)習(xí)板。這篇文章是我把這塊板子相關(guān)資料重新過(guò)了一遍之后整理的實(shí)操筆記內(nèi)容包括芯片選型、硬件盤(pán)點(diǎn)、環(huán)境搭建、進(jìn)階實(shí)驗(yàn)和問(wèn)題排查適合剛?cè)胧诌@塊學(xué)習(xí)板或者正在糾結(jié)選哪塊板子入門(mén)的同學(xué)。1. 定位拆解STM32F072C8T6為什么適合當(dāng)學(xué)習(xí)板1.1 C8T6這批芯片到底強(qiáng)在哪STM32F072C8T6LQFP48封裝Cortex-M0內(nèi)核主頻48MHz64KB Flash和16KB SRAM。光看這些參數(shù)會(huì)覺(jué)得平平無(wú)奇但它擁有一個(gè)在同價(jià)位M0芯片里并不常見(jiàn)的組合USB 2.0全速設(shè)備控制器、CAN 2.0B控制器、兩個(gè)12位DAC、兩個(gè)比較器、七個(gè)定時(shí)器、多個(gè)USART/I2C/SPI。也就是說(shuō)這顆芯片既能玩串口、I2C這類(lèi)基礎(chǔ)外設(shè)也能?chē)L試USB、CAN這些在F103上往往需要外部PHY或更復(fù)雜電路的功能在芯片內(nèi)部全部搞定。對(duì)學(xué)習(xí)者來(lái)說(shuō)這個(gè)組合的最大價(jià)值在于“用最小成本接觸真實(shí)世界的通信接口”。比如USBPC端應(yīng)用、HID設(shè)備、CDC虛擬串口這在開(kāi)發(fā)中幾乎是躲不開(kāi)的。在F103上做USB經(jīng)常要求外接晶振和較多調(diào)試經(jīng)驗(yàn)F072內(nèi)部有專(zhuān)門(mén)的USB時(shí)鐘恢復(fù)單元配合48MHz PLL能更從容地跑起來(lái)。學(xué)習(xí)板選擇了這顆芯片也就意味著你不需要在硬件上付出額外代價(jià)就能把通信協(xié)議棧跑通。還有一點(diǎn)容易被忽略M0內(nèi)核比M3/M4簡(jiǎn)單中斷向量表、寄存器模型這些底層機(jī)制更容易看懂。我見(jiàn)過(guò)很多同學(xué)直接從F103入手結(jié)果被復(fù)雜的中斷嵌套和總線協(xié)議勸退。F072更像是先給你的認(rèn)知打底之后再去看M3/M4項(xiàng)目反而輕松很多。1.2 極客良品這塊學(xué)習(xí)板資料和定位怎么樣極客良品這個(gè)品牌在淘寶學(xué)習(xí)板圈子里主打“資料全、例程多”。STM32F072C8T6學(xué)習(xí)板屬于比較典型的教學(xué)向產(chǎn)品板子設(shè)計(jì)不花哨但把所有IO引出、常見(jiàn)外設(shè)都做了擴(kuò)展接口并且大部分版本自帶USB轉(zhuǎn)串口芯片。這樣設(shè)計(jì)的好處是上課、做課設(shè)、做畢設(shè)一塊板子都能應(yīng)付。資料方面我拿到手這版包含PDF原理圖、Keil/HAL庫(kù)例程、基礎(chǔ)實(shí)驗(yàn)文檔還有出廠測(cè)試固件。這類(lèi)資料在廠商官網(wǎng)或者官方論壇很難找到完整版基本是隨板子附帶的所以買(mǎi)到板子后最好第一時(shí)間把網(wǎng)盤(pán)下載鏈接存好版本號(hào)也要看清別等后面要用時(shí)才發(fā)現(xiàn)手頭的資料和實(shí)物對(duì)不上。整體來(lái)說(shuō)這套例程覆蓋面比官方CubeMX生成的模板更貼近實(shí)戰(zhàn)因?yàn)樗鼤?huì)考慮到學(xué)習(xí)板上的硬件跳線、按鍵消抖這些實(shí)際問(wèn)題。2. 開(kāi)箱檢查先別急著通電這兩步很有用2.1 先盤(pán)點(diǎn)板載硬件資源拿到板子的第一件事不是插USB燈亮就完事而是對(duì)照原理圖把板子上的關(guān)鍵器件認(rèn)一遍。常見(jiàn)配置大致是主控為STM32F072C8T68MHz無(wú)源晶振USB 5V輸入并經(jīng)LDO穩(wěn)壓到3.3VUSB轉(zhuǎn)串口芯片多為CH340或CP2102連接MCU的USART1用于下載程序和調(diào)試調(diào)試接口通過(guò)板載調(diào)試器或SWD排針引出板上還帶若干LED、按鍵、排針以及可能的CAN收發(fā)器。我這里用表格整理一下方便對(duì)照資源常見(jiàn)配置使用提示主控STM32F072C8T6確認(rèn)芯片絲印時(shí)鐘源8MHz HSEUSB應(yīng)用優(yōu)先用PLL輸出48MHzUSB轉(zhuǎn)串口CH340/CP2102先裝驅(qū)動(dòng)確認(rèn)COM口號(hào)調(diào)試口SWD排針/板載調(diào)試器連接仿真器時(shí)注意共地外設(shè)LED、按鍵、排針等各引腳定義以原理圖為準(zhǔn)這一部分看似瑣碎但我實(shí)際收到過(guò)不少反饋說(shuō)“程序下載不了”最后排查下來(lái)不是軟件問(wèn)題而是不知道板載調(diào)試器需要另外供電或者BOOT跳線沒(méi)接對(duì)。原理圖能看到的東西往往比網(wǎng)上的經(jīng)驗(yàn)貼更可靠。2.2 上電檢查別跳過(guò)接著就是上電前的基礎(chǔ)檢查。我習(xí)慣先用萬(wàn)用表量一下3.3V和GND之間的阻抗避免有焊接短路然后插USB看電源指示燈是否正常亮起再用萬(wàn)用表確認(rèn)LDO輸出電壓在3.3V附近誤差別超過(guò)5%。如果是USB轉(zhuǎn)串口芯片設(shè)備管理器里應(yīng)該能看到一個(gè)新的COM口看不到就先安裝對(duì)應(yīng)驅(qū)動(dòng)Win10/11通常自帶但有些精簡(jiǎn)版系統(tǒng)會(huì)缺。這一步對(duì)新手來(lái)說(shuō)容易忽略但能省掉后面大量排查時(shí)間。我見(jiàn)過(guò)有同學(xué)把板子接到電腦上燈亮了就以為一切正常結(jié)果程序一直下載不進(jìn)去最后發(fā)現(xiàn)是USB線只有充電功能數(shù)據(jù)線沒(méi)接觸好。這個(gè)坑雖然蠢但很常見(jiàn)建議換一根明確標(biāo)注“數(shù)據(jù)線”的線現(xiàn)場(chǎng)試一下。3. 環(huán)境搭建實(shí)操?gòu)腃ubeMX生成工程到串口輸出3.1 工具鏈選型用CubeMX還是直接寫(xiě)寄存器STM32F072屬于F0系列官方有完整的HAL庫(kù)和LL庫(kù)支持。我建議的搭配是STM32CubeMX 6.x Keil MDK或者STM32CubeMX VS Code arm-none-eabi-gcc。CubeMX負(fù)責(zé)圖形化配置時(shí)鐘、引腳、外設(shè)MDK/GCC負(fù)責(zé)編譯和調(diào)試。用CubeMX的核心價(jià)值就是避免手工寫(xiě)初始化代碼時(shí)踩引腳復(fù)用和時(shí)鐘樹(shù)的坑尤其對(duì)新手特別友好。需要提前做的事在CubeMX里安裝STM32CubeF0固件包在Keil里裝好STM32F0系列的Device Family Pack。不然新建工程時(shí)會(huì)直接卡住或者編譯時(shí)報(bào)“cannot open device header file”一類(lèi)錯(cuò)誤。MDK版本建議5.x以上USB驅(qū)動(dòng)和調(diào)試器固件也順便更新一下能避免很多隱性兼容問(wèn)題。3.2 點(diǎn)燈和串口打印的完整步驟我用最小工程走了一遍這里直接貼可復(fù)現(xiàn)的步驟打開(kāi)CubeMX新建工程選擇STM32F072C8Tx型號(hào)。在SYS里把Debug設(shè)為Serial Wire并把RCC的HSE設(shè)為Crystal/Ceramic Resonator。時(shí)鐘樹(shù)配置HSE 8MHz輸入PLL倍頻到48MHz確保系統(tǒng)時(shí)鐘和USB時(shí)鐘都在48MHz。配置一個(gè)LED引腳為GPIO輸出再配置USART1PA9為T(mén)X、PA10為RX波特率115200。生成代碼后在main函數(shù)里翻轉(zhuǎn)LED電平在主循環(huán)里用HAL_UART_Transmit發(fā)送一段字符串。如果要用printf需要重定向底層單字符輸出函數(shù)到USART1HAL環(huán)境下可以重寫(xiě)fputc并在MDK里勾選MicroLib不然浮點(diǎn)數(shù)打印會(huì)出問(wèn)題。int fputc(int ch, FILE *f) { HAL_UART_Transmit(huart1, (uint8_t *)ch, 1, 100); return ch; }編譯下載后打開(kāi)串口助手選擇對(duì)應(yīng)COM口波特率115200應(yīng)該能看到板上不斷打印數(shù)據(jù)。如果串口沒(méi)輸出先檢查波特率、接線和工程里用的串口是否和板上芯片一致。這里也提醒一句很多學(xué)習(xí)板的板載串口會(huì)占用USART1如果你換用USART2調(diào)試需要另外飛線第一次做實(shí)驗(yàn)別圖省事直接找錯(cuò)串口腳。3.3 學(xué)習(xí)板的下載方式和BOOT跳線下載程序的方式主要有三種板載調(diào)試器直接SWD下載、外接ST-Link/J-Link下載、串口ISP下載。前兩種要求SWDIO/SWCLK沒(méi)有被程序禁掉第三種要求BOOT0拉高、BOOT1拉低然后通過(guò)USART1把bin文件燒進(jìn)系統(tǒng)Bootloader。對(duì)于學(xué)習(xí)板BOOT跳線通常焊在排針或者撥碼開(kāi)關(guān)旁邊出問(wèn)題的時(shí)候很好用。我個(gè)人建議新手優(yōu)先用SWD方式因?yàn)樵谡{(diào)試時(shí)可以打斷點(diǎn)、看寄存器。串口ISP只適合在沒(méi)有調(diào)試器或者芯片被讀保護(hù)之后用來(lái)擦除。萬(wàn)一遇到“芯片被鎖”這類(lèi)情況把BOOT0拉到高電平重新上電用Flash Loader或STM32CubeProgrammer連接并執(zhí)行“Full Chip Erase”就能救回來(lái)。4. 進(jìn)階實(shí)驗(yàn)USB虛擬串口和CAN通信的踩坑記錄4.1 在F072上做USB CDC虛擬串口F072內(nèi)置USB 2.0全速設(shè)備這個(gè)功能如果不玩一下我覺(jué)得有點(diǎn)可惜。用CubeMX配置時(shí)把USB外設(shè)打開(kāi)再選擇Middleware為USB Device類(lèi)別選Communication Device ClassCDC路由好后生成代碼。工程里會(huì)多出usbd_cdc_if.c發(fā)送數(shù)據(jù)一般調(diào)用CDC_Transmit_FS接收數(shù)據(jù)在回調(diào)函數(shù)里處理。這里最大的坑是時(shí)鐘。F072的USB需要48MHz時(shí)鐘且精度要滿足USB規(guī)范否則電腦會(huì)識(shí)別不了或者每次插拔都要重新枚舉。如果你用的是外部8MHz晶振時(shí)鐘樹(shù)里要確認(rèn)PLL輸出是48MHz如果你用了內(nèi)部HSI要留意F072專(zhuān)門(mén)提供的時(shí)鐘恢復(fù)單元CRS通過(guò)USB SOF信號(hào)校準(zhǔn)時(shí)鐘源代碼里可以把CRS初始化加上。實(shí)測(cè)下來(lái)晶振本身質(zhì)量差也會(huì)導(dǎo)致USB枚舉不穩(wěn)定表現(xiàn)是插上后電腦一會(huì)兒識(shí)別一會(huì)兒掉線很多初學(xué)會(huì)誤以為是代碼問(wèn)題實(shí)際是硬件時(shí)鐘源質(zhì)量太差。USB CDC成功枚舉后系統(tǒng)會(huì)多出一個(gè)虛擬COM口發(fā)送數(shù)據(jù)和對(duì)普通串口一樣方便這樣你寫(xiě)PC端上位機(jī)時(shí)不用額外接線還能順帶理解USB描述符和端點(diǎn)配置的概念。如果你以后要做HID鍵盤(pán)、U盤(pán)、自定義設(shè)備這套流程都能復(fù)用。4.2 CAN通信波特率和終端電阻是高頻翻車(chē)點(diǎn)F072帶CAN 2.0B控制器這在同價(jià)位M0芯片里非常難得。學(xué)習(xí)板通常會(huì)把CAN收發(fā)器芯片做成選配或者直接焊在板上。如果是TJA1050這類(lèi)收發(fā)器想通信只需外接CANH、CANL進(jìn)行雙絞線組網(wǎng)如果板子上沒(méi)有收發(fā)器需要自己外接模塊此時(shí)注意收發(fā)器電源和地不能接反。配置CAN時(shí)需要設(shè)定波特率。以常見(jiàn)125Kbps為例APB時(shí)鐘48MHz要求預(yù)分頻器、時(shí)間段1和時(shí)間段2搭配到位CubeMX里有“Bit Timings”自動(dòng)計(jì)算功能但實(shí)際組網(wǎng)時(shí)還要保證所有節(jié)點(diǎn)的波特率一致125/250/500Kbps不要混用。另外CAN總線兩端各加一個(gè)120歐終端電阻不是每個(gè)節(jié)點(diǎn)都加總阻抗匹配不對(duì)時(shí)表現(xiàn)為間歇性收發(fā)失敗偶爾進(jìn)錯(cuò)誤狀態(tài)。我實(shí)際測(cè)試兩個(gè)學(xué)習(xí)板之間通信時(shí)最大的體會(huì)是看似最簡(jiǎn)單的初始化順序也不能亂。建議先初始化CAN控制器和過(guò)濾器再啟動(dòng)CAN并進(jìn)入Normal模式最后在發(fā)送函數(shù)里判斷郵箱是否空閑。如果一上來(lái)就連續(xù)發(fā)多條報(bào)文很容易觸發(fā)郵箱報(bào)錯(cuò)或者進(jìn)Bus Off狀態(tài)。5. 常見(jiàn)問(wèn)題排查下載失敗、枚舉失敗、資料版本混亂5.1 下載失敗的幾個(gè)原因和處置我把之前幫人排查過(guò)的下載失敗案例整理成了表格方便對(duì)照現(xiàn)象可能原因解決辦法Keil提示找不到設(shè)備調(diào)試器驅(qū)動(dòng)沒(méi)裝、USB線不通、目標(biāo)板沒(méi)供電重裝驅(qū)動(dòng)換數(shù)據(jù)線確認(rèn)電源燈亮燒錄時(shí)報(bào)RDDI-DAP ErrorSWDIO/SWCLK被程序復(fù)用按住RESET再下載或串口ISP擦除下載后第一次能跑第二次連不上代碼里把SWD引腳改成了普通GPIO檢查初始化代碼保留SWD功能芯片加了讀保護(hù)RDP等級(jí)被改用CubeProgrammer解鎖并全片擦除下載失敗這種情況十有八九不是軟件壞了而是連接問(wèn)題。我的建議是先在Keil的Settings里點(diǎn)擊“Engine”看能不能識(shí)別到芯片ID。識(shí)別不到就從硬件找原因識(shí)別到了但下載失敗再考慮代碼和Option字節(jié)的問(wèn)題。還有一個(gè)特別容易忽略的如果PC上同時(shí)開(kāi)著多個(gè)軟件占用調(diào)試器比如串口助手和IDE同時(shí)在用某些一體式調(diào)試器會(huì)被擠掉。關(guān)掉多余軟件重新插拔調(diào)試器大部分問(wèn)題馬上消失。5.2 串口亂碼和USB枚舉失敗如何排查串口亂碼先看波特率是否一致再看系統(tǒng)時(shí)鐘是否準(zhǔn)確。如果用的是HSI內(nèi)部時(shí)鐘串口波特率誤差會(huì)比HSE大長(zhǎng)時(shí)間通信容易掉字。解決辦法是改用外部晶振或針對(duì)波特率誤差做精細(xì)整定。USB枚舉失敗重點(diǎn)查四點(diǎn)USB時(shí)鐘源是否配置為48MHz、VBUS是否被正確檢測(cè)、DP/DM引腳有沒(méi)有接錯(cuò)、電腦端設(shè)備管理器是否出現(xiàn)未知設(shè)備。如果出現(xiàn)未知設(shè)備多半是底層描述符沒(méi)對(duì)或者驅(qū)動(dòng)沒(méi)裝。調(diào)試這類(lèi)問(wèn)題時(shí)我習(xí)慣打開(kāi)STM32CubeProgrammer里的內(nèi)存查看窗口直接讀取DBGMCU寄存器看是否配置了調(diào)試端口再配合示波器或者邏輯分析儀看DP/DM上的波形。沒(méi)有示波器的時(shí)候可以用USBlyzer這類(lèi)軟件抓枚舉過(guò)程錯(cuò)誤碼能直接幫你定位到是設(shè)備端還是主機(jī)端的問(wèn)題。5.3 網(wǎng)上流傳資料版本多怎么分辨極客良品的學(xué)習(xí)板資料在網(wǎng)盤(pán)和各論壇流傳很廣但多版本共存的情況也很明顯。有的壓縮包是舊版HAL庫(kù)工程有的是標(biāo)準(zhǔn)庫(kù)工程有的芯片型號(hào)寫(xiě)的是F103xx這對(duì)剛?cè)腴T(mén)的同學(xué)來(lái)說(shuō)是地獄難度。我的做法是先看ReadMe文件和工程文件名的日期再看.ioc文件、.uvprojx文件里的目標(biāo)芯片型號(hào)最后核對(duì)原理圖PDF的頁(yè)數(shù)和板子版本號(hào)。如果資料里的例程編譯報(bào)錯(cuò)最常見(jiàn)的原因是Keil的Pack版本和例程要求版本不一致或是HAL庫(kù)頭文件路徑?jīng)]有被正確包含。優(yōu)先選擇和自己CubeMX版本相近的例程不要盲目下載最新版。一些老例程里用的驅(qū)動(dòng)接口在新版HAL庫(kù)里已經(jīng)改了函數(shù)名需要對(duì)照頭文件逐個(gè)調(diào)整。6. 我的個(gè)人建議怎么把這套學(xué)習(xí)板資料吃透6.1 先把基礎(chǔ)外設(shè)全部自己建一遍工程我見(jiàn)過(guò)太多人拿到學(xué)習(xí)板后都是把教程里的例程直接下載編譯然后跑一下燈亮了就算完成任務(wù)。這樣其實(shí)效率極低。我更建議的做法是照著資料里的例程功能自己用CubeMX從零建工程不參考原工程卡住了再看源碼。比如GPIO點(diǎn)燈、外部中斷、定時(shí)器PWM、串口收發(fā)這四個(gè)實(shí)驗(yàn)每個(gè)都自己建一遍基本工具鏈和排查能力就練出來(lái)了。跑通不是目的能解釋“為什么這么配置”才是關(guān)鍵。從外設(shè)清單來(lái)看F072的學(xué)習(xí)路徑可以這樣排GPIO、定時(shí)器PWM、外部中斷、串口收發(fā)、ADC/DAC、I2C/SPI、USB CDC、CAN。前面的基礎(chǔ)實(shí)驗(yàn)最多兩周時(shí)間后面兩個(gè)高階外設(shè)可以各花一周。按這個(gè)節(jié)奏走等你把USB和CAN都跑通再回頭看主流崗位里的嵌入式要求會(huì)發(fā)現(xiàn)大部分知識(shí)點(diǎn)都已經(jīng)接觸過(guò)。6.2 資料之外務(wù)必會(huì)查官方手冊(cè)和搜索關(guān)鍵詞學(xué)習(xí)板資料是很好的起點(diǎn)但永遠(yuǎn)不是終點(diǎn)。真正遇到“為什么這個(gè)寄存器是這么配置”的疑問(wèn)還是要回到ST官方手冊(cè)建議常備《STM32F0xx Reference Manual》和Cortex-M0相關(guān)文檔。另外網(wǎng)上關(guān)于這塊板子的學(xué)生分享其實(shí)不少偶爾搜“stcb學(xué)習(xí)板hnu”這類(lèi)關(guān)鍵詞能看到高校嵌入式課程的相關(guān)實(shí)驗(yàn)筆記內(nèi)容往往比官方例程更貼近考試和課設(shè)要求可以當(dāng)作補(bǔ)充資料看。最后分享一個(gè)我用了很久的技巧做一個(gè)“功能-寄存器-現(xiàn)象”對(duì)照表。每跑通一個(gè)實(shí)驗(yàn)就把對(duì)應(yīng)的外設(shè)寄存器關(guān)鍵位寫(xiě)下來(lái)再記錄實(shí)驗(yàn)現(xiàn)象。到了后面項(xiàng)目做復(fù)雜了翻自己整理的對(duì)照表比翻幾百頁(yè)手冊(cè)高效得多這也是我從這塊入門(mén)板一路做項(xiàng)目到現(xiàn)在一直保持的習(xí)慣。本文還有配套的精品資源點(diǎn)擊獲取