戰(zhàn):從時(shí)鐘配置到外設(shè)驅(qū)動(dòng)避坑指南)
簡(jiǎn)介這份資源是面向嵌入式開(kāi)發(fā)者的比亞迪BF7613BMXX單片機(jī)參考程序例程包適合已具備一定C語(yǔ)言與單片機(jī)基礎(chǔ)、希望快速上手該芯片外設(shè)驅(qū)動(dòng)的人員使用。例程圍繞ADC、EEPROM、GPIO、IIC、PWM、SLEEP低功耗、UART、定時(shí)器、外部中斷與觸摸功能等核心模塊展開(kāi)逐一給出可編譯運(yùn)行的底層實(shí)現(xiàn)幫助讀者理解各接口的配置流程與數(shù)據(jù)處理方式。壓縮包共877個(gè)文件約11.73MB以240個(gè)h頭文件、228個(gè)c源文件為主體輔以lst列表、obj目標(biāo)文件、hex與bin燒錄鏡像、uvproj與uvopt工程文件、a51啟動(dòng)代碼及少量pdf、ppt說(shuō)明文檔工程結(jié)構(gòu)完整便于直接導(dǎo)入Keil環(huán)境調(diào)試。目前已有931人學(xué)習(xí)下載可作為STM32及ARM架構(gòu)嵌入式硬件開(kāi)發(fā)的實(shí)踐參考幫助讀者掌握外設(shè)驅(qū)動(dòng)編寫、低功耗設(shè)計(jì)與中斷處理思路為實(shí)際項(xiàng)目提供可復(fù)用的代碼基礎(chǔ)。1. 從一份冷門參考例程說(shuō)起B(yǎng)F7613BMXX 能解決什么問(wèn)題如果你手頭正捏著一顆 BF7613BMXX 芯片翻遍官網(wǎng)只找到一份數(shù)據(jù)手冊(cè)寄存器列表長(zhǎng)得讓人頭皮發(fā)麻那這份參考程序例程就是來(lái)救場(chǎng)的。它本質(zhì)上是一套面向該芯片的裸機(jī)驅(qū)動(dòng)集合把 GPIO、定時(shí)器、UART、ADC、PWM 這些外設(shè)的初始化流程和中斷處理都寫成了可直接編譯的 C 代碼。和 STM32 那種生態(tài)鋪天蓋地的芯片不同BF7613BMXX 的資料相對(duì)零散很多時(shí)候你得靠例程反推寄存器的正確配置順序。這套代碼最適合兩類人一是剛接手該芯片、需要快速點(diǎn)燈和跑通串口的嵌入式新手二是從 STM32 轉(zhuǎn)過(guò)來(lái)、想對(duì)比兩者外設(shè)驅(qū)動(dòng)差異的老手。它不涉及 RTOS也不綁定特定 IDE核心價(jià)值在于把“黑匣子”一樣的寄存器操作拆成了能讀、能改、能驗(yàn)證的工程文件。2. 工程結(jié)構(gòu)拆解從啟動(dòng)文件到外設(shè)驅(qū)動(dòng)的調(diào)用鏈拿到一份參考例程最忌諱直接打開(kāi) main.c 就開(kāi)始改。我一般會(huì)先花十分鐘把目錄樹(shù)和調(diào)用關(guān)系理一遍否則后面出問(wèn)題連從哪查都不知道。BF7613BMXX 這套例程的結(jié)構(gòu)比較典型屬于“啟動(dòng)文件 系統(tǒng)初始化 外設(shè)驅(qū)動(dòng) 應(yīng)用層”的四層布局和 STM32 的標(biāo)準(zhǔn)庫(kù)工程有相似之處但細(xì)節(jié)上更精簡(jiǎn)沒(méi)有 HAL 那層厚厚的抽象。2.1 目錄布局與關(guān)鍵文件職責(zé)先看整體目錄常見(jiàn)做法是分成 CMSIS 內(nèi)核支持、外設(shè)驅(qū)動(dòng)、用戶應(yīng)用三塊。下面這張表是我根據(jù)例程實(shí)際文件整理的職責(zé)說(shuō)明你拿到手可以對(duì)照著看。目錄/文件職責(zé)是否建議修改startup_bf7613.s中斷向量表、復(fù)位處理、堆棧初始化僅改堆棧大小時(shí)動(dòng)system_bf7613.c系統(tǒng)時(shí)鐘配置、Flash 等待周期時(shí)鐘頻率不對(duì)時(shí)才改bf7613_gpio.c/hGPIO 初始化、位操作宏按需增刪函數(shù)bf7613_uart.c/h串口波特率、中斷收發(fā)改波特率和引腳映射bf7613_tim.c/h定時(shí)器周期、PWM 輸出按業(yè)務(wù)調(diào)參數(shù)main.c外設(shè)調(diào)用順序、主循環(huán)主要修改區(qū)啟動(dòng)文件里最關(guān)鍵的是中斷向量表它決定了每個(gè)中斷服務(wù)函數(shù)的名字和入口地址。如果你從別的工程拷貝代碼向量表對(duì)不上中斷就會(huì)跑飛這種翻車現(xiàn)場(chǎng)我見(jiàn)過(guò)不止一次。system_bf7613.c 里的時(shí)鐘配置直接影響到 UART 波特率和定時(shí)器周期改之前一定先確認(rèn)外部晶振頻率例程默認(rèn)用的是內(nèi)部 RC 還是外部晶振在代碼注釋里通常會(huì)寫。2.2 時(shí)鐘樹(shù)與初始化順序的硬約束B(niǎo)F7613BMXX 的時(shí)鐘樹(shù)比 STM32 簡(jiǎn)單但初始化順序有硬性要求。常見(jiàn)做法是先配置系統(tǒng)時(shí)鐘源再設(shè)置各外設(shè)總線分頻最后才初始化具體外設(shè)。順序反了外設(shè)寄存器可能寫不進(jìn)去或者寫進(jìn)去但工作頻率不對(duì)。// system_bf7613.c 中的時(shí)鐘初始化片段 void SystemInit(void) { // 1. 使能內(nèi)部高速時(shí)鐘等待穩(wěn)定 RCC-CR | RCC_CR_HSION; while(!(RCC-CR RCC_CR_HSIRDY)); // 2. 配置 PLL假設(shè)外部晶振 8MHz目標(biāo) 48MHz RCC-CFGR ~RCC_CFGR_PLLSRC; // 選擇 HSI 作為 PLL 源 RCC-CFGR | RCC_CFGR_PLLMULL6; // 8MHz * 6 48MHz RCC-CR | RCC_CR_PLLON; while(!(RCC-CR RCC_CR_PLLRDY)); // 3. 切換系統(tǒng)時(shí)鐘到 PLL RCC-CFGR | RCC_CFGR_SW_PLL; while((RCC-CFGR RCC_CFGR_SWS) ! RCC_CFGR_SWS_PLL); // 4. 設(shè)置 AHB/APB 分頻 RCC-CFGR | RCC_CFGR_HPRE_DIV1; RCC-CFGR | RCC_CFGR_PPRE1_DIV2; }這段代碼的邏輯說(shuō)明第一步先讓內(nèi)部高速時(shí)鐘起振這是所有后續(xù)操作的基礎(chǔ)第二步配置 PLL 倍頻注意 PLLMULL6 這個(gè)宏在不同頭文件里可能叫法不同以你實(shí)際工程為準(zhǔn)第三步把系統(tǒng)時(shí)鐘切到 PLL 輸出切換完必須等 SWS 狀態(tài)位確認(rèn)第四步設(shè)置總線分頻APB1 通常不超過(guò) 24MHz分頻系數(shù)要根據(jù)你實(shí)際外設(shè)需求調(diào)。參數(shù)怎么改如果你板子上是 12MHz 晶振PLLMULL6 就變成 72MHz 了得重新算分頻別直接抄。提示時(shí)鐘配置改完第一件事是拿示波器或者用 MCO 引腳輸出時(shí)鐘測(cè)一下別光看代碼覺(jué)得對(duì)就往下跑。2.3 GPIO 與 UART 的聯(lián)動(dòng)配置GPIO 初始化本身不難但和 UART 復(fù)用引腳綁在一起時(shí)順序錯(cuò)了就收不到數(shù)據(jù)。我一般會(huì)先配 GPIO 為復(fù)用功能再配 UART 寄存器最后使能 UART。// bf7613_uart.c 中的初始化函數(shù) void UART1_Init(uint32_t baud) { // 1. 使能 GPIO 和 UART 時(shí)鐘 RCC-APB2ENR | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN; // 2. 配置 PA9 為復(fù)用推挽輸出PA10 為浮空輸入 GPIOA-CRH ~(0xFF 4); GPIOA-CRH | (0x0B 4) | (0x04 8); // 3. 配置波特率假設(shè)系統(tǒng)時(shí)鐘 48MHz USART1-BRR 48000000 / baud; // 4. 使能收發(fā)和 UART USART1-CR1 | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; }邏輯說(shuō)明第一步時(shí)鐘使能漏掉任何一個(gè)后面寄存器都寫不進(jìn)去第二步 CRH 寄存器控制 PA8~PA15PA9 對(duì)應(yīng) bit4~70x0B 表示復(fù)用推挽 50MHzPA10 對(duì)應(yīng) bit8~110x04 表示浮空輸入第三步 BRR 是整數(shù)分頻如果波特率算出來(lái)有小數(shù)誤差超過(guò) 3% 通信就會(huì)不穩(wěn)定這時(shí)候得換晶振或者調(diào) PLL第四步 UE 位最后置一提前置一可能發(fā)送出亂碼。參數(shù)怎么改波特率 115200 時(shí) BRR 值約 417你可以用示波器測(cè)一位的時(shí)間來(lái)驗(yàn)證。3. 編譯環(huán)境搭建與第一個(gè)可運(yùn)行工程例程能不能跑起來(lái)一半看代碼一半看環(huán)境。BF7613BMXX 不像 STM32 那樣在 Keil 和 IAR 里都有現(xiàn)成器件包很多時(shí)候需要手動(dòng)選一個(gè)內(nèi)核相近的器件或者自己建工程模板。這一章我把從零建工程到串口輸出 Hello 的完整流程走一遍中間涉及的工具鏈選擇和下載配置都給出具體操作。3.1 工具鏈選擇與工程模板創(chuàng)建常見(jiàn)做法是用 Keil MDK 或者 IAR EWARM兩者對(duì) Cortex-M 內(nèi)核支持都成熟。如果你用 Keil新建工程時(shí)器件選 ARMCM3 或者 ARMCM4具體看 BF7613BMXX 的內(nèi)核版本例程注釋里一般會(huì)寫。選完器件后把啟動(dòng)文件、系統(tǒng)文件、外設(shè)驅(qū)動(dòng)文件按目錄加進(jìn)工程組頭文件路徑也要加全。# 以 Keil 命令行編譯為例假設(shè)工程文件為 bf7613_demo.uvprojx UV4.exe -b bf7613_demo.uvprojx -o build_log.txt # 查看編譯結(jié)果 cat build_log.txt | grep -E Error|Warning這段命令的邏輯-b 表示批量編譯-o 把輸出重定向到日志文件方便你排查錯(cuò)誤。參數(shù)怎么改如果你工程路徑有空格記得用引號(hào)包起來(lái)否則命令行會(huì)截?cái)?。編譯報(bào)錯(cuò)最常見(jiàn)的是頭文件找不到檢查 Include Paths 里有沒(méi)有把 bf7613_gpio.h 所在目錄加進(jìn)去。3.2 下載配置與串口驗(yàn)證編譯通過(guò)只是第一步下載進(jìn)去跑起來(lái)才算數(shù)。BF7613BMXX 支持 SWD 兩線下載常見(jiàn)做法是在 Keil 的 Debug 設(shè)置里選 CMSIS-DAP 或者 J-Link然后配置 Flash 算法。Flash 算法文件通常例程包里會(huì)帶一個(gè) .FLM 文件如果沒(méi)有你得根據(jù)芯片手冊(cè)的 Flash 編程時(shí)序自己寫一個(gè)這是比較頭疼的情況。// main.c 中的串口驗(yàn)證代碼 #include bf7613_uart.h int main(void) { SystemInit(); // 時(shí)鐘初始化 UART1_Init(115200); // 串口初始化波特率 115200 while(1) { UART1_SendString(BF7613 UART OK\r\n); for(int i 0; i 1000000; i); // 簡(jiǎn)單延時(shí) } }邏輯說(shuō)明SystemInit 必須在 UART1_Init 之前調(diào)用否則波特率計(jì)算用的時(shí)鐘頻率是錯(cuò)的UART1_SendString 是例程里封裝好的發(fā)送函數(shù)內(nèi)部通常是輪詢發(fā)送如果你要改中斷發(fā)送得自己加中斷服務(wù)函數(shù)。參數(shù)怎么改延時(shí)循環(huán)的 1000000 是經(jīng)驗(yàn)值系統(tǒng)時(shí)鐘 48MHz 時(shí)大約幾百毫秒你要改發(fā)送頻率就調(diào)這個(gè)數(shù)。驗(yàn)證方法打開(kāi)串口助手波特率設(shè) 115200數(shù)據(jù)位 8停止位 1無(wú)校驗(yàn)?zāi)芸吹讲粩啻蛴〉淖址驼f(shuō)明時(shí)鐘和串口都對(duì)了。注意如果串口收到亂碼先查波特率再查時(shí)鐘配置最后查 GPIO 復(fù)用有沒(méi)有配錯(cuò)。這三個(gè)地方按順序排查能省不少時(shí)間。4. 外設(shè)驅(qū)動(dòng)實(shí)戰(zhàn)定時(shí)器、ADC 與 PWM 的配置要點(diǎn)點(diǎn)燈和串口只是開(kāi)胃菜真正做產(chǎn)品時(shí)定時(shí)器、ADC、PWM 才是高頻外設(shè)。BF7613BMXX 的這幾個(gè)外設(shè)寄存器和 STM32 有相似之處但細(xì)節(jié)差異不小比如定時(shí)器的預(yù)分頻寄存器位寬、ADC 的采樣時(shí)間配置方式直接抄 STM32 的代碼大概率翻車。這一章我把這三個(gè)外設(shè)的配置流程和參數(shù)計(jì)算拆開(kāi)講。4.1 定時(shí)器中斷配置與周期計(jì)算定時(shí)器配置的核心是算清楚預(yù)分頻值PSC和自動(dòng)重裝載值A(chǔ)RR。公式是定時(shí)周期 (PSC1) * (ARR1) / 定時(shí)器時(shí)鐘頻率。假設(shè)定時(shí)器時(shí)鐘 48MHz你要 1ms 中斷一次可以設(shè) PSC47ARR999。// bf7613_tim.c 中的定時(shí)器初始化 void TIM2_Init(void) { RCC-APB1ENR | RCC_APB1ENR_TIM2EN; // 使能 TIM2 時(shí)鐘 TIM2-PSC 47; // 預(yù)分頻 48 分頻計(jì)數(shù)時(shí)鐘 1MHz TIM2-ARR 999; // 自動(dòng)重裝載1ms 溢出一次 TIM2-DIER | TIM_DIER_UIE; // 使能更新中斷 TIM2-CR1 | TIM_CR1_CEN; // 啟動(dòng)定時(shí)器 NVIC_EnableIRQ(TIM2_IRQn); // 使能 NVIC 中斷 } // 中斷服務(wù)函數(shù) void TIM2_IRQHandler(void) { if(TIM2-SR TIM_SR_UIF) { TIM2-SR ~TIM_SR_UIF; // 清除中斷標(biāo)志 // 用戶代碼每 1ms 執(zhí)行一次 } }邏輯說(shuō)明PSC 和 ARR 都是 16 位寄存器最大值 65535如果你要更長(zhǎng)的定時(shí)得用多次中斷累加或者換 32 位定時(shí)器DIER 的 UIE 位使能更新中斷CR1 的 CEN 位啟動(dòng)計(jì)數(shù)NVIC 使能別忘了否則中斷進(jìn)不去。參數(shù)怎么改要 10ms 中斷ARR 改成 9999要 100usPSC 改成 4ARR 改成 959。中斷服務(wù)函數(shù)里清標(biāo)志位必須放在用戶代碼之前否則可能丟中斷。4.2 ADC 采樣與濾波處理ADC 配置比定時(shí)器多一步采樣時(shí)間設(shè)置BF7613BMXX 的 ADC 采樣時(shí)間寄存器通常有多個(gè)通道獨(dú)立配置。常見(jiàn)做法是采樣時(shí)間設(shè)長(zhǎng)一點(diǎn)犧牲速度換穩(wěn)定性尤其是高阻抗信號(hào)源。// bf7613_adc.c 中的 ADC 初始化 void ADC1_Init(void) { RCC-APB2ENR | RCC_APB2ENR_ADC1EN; ADC1-SMPR2 | ADC_SMPR2_SMP0_2 | ADC_SMPR2_SMP0_1; // 通道0 采樣時(shí)間 239.5 周期 ADC1-SQR1 ~ADC_SQR1_L; // 規(guī)則序列長(zhǎng)度 1 ADC1-SQR3 | 0; // 第一個(gè)轉(zhuǎn)換通道為 0 ADC1-CR2 | ADC_CR2_ADON; // 使能 ADC ADC1-CR2 | ADC_CR2_RSTCAL; // 復(fù)位校準(zhǔn) while(ADC1-CR2 ADC_CR2_RSTCAL); ADC1-CR2 | ADC_CR2_CAL; // 開(kāi)始校準(zhǔn) while(ADC1-CR2 ADC_CR2_CAL); } uint16_t ADC1_Read(void) { ADC1-CR2 | ADC_CR2_SWSTART; // 軟件觸發(fā)轉(zhuǎn)換 while(!(ADC1-SR ADC_SR_EOC)); // 等待轉(zhuǎn)換完成 return ADC1-DR 0xFFF; // 讀取 12 位結(jié)果 }邏輯說(shuō)明SMPR2 寄存器控制通道 0~9 的采樣時(shí)間這里設(shè)成 239.5 周期是較慢但穩(wěn)定的檔位SQR1 的 L 位設(shè)規(guī)則序列長(zhǎng)度單通道就設(shè) 0校準(zhǔn)步驟不能省否則零點(diǎn)漂移可能幾十個(gè) LSB。參數(shù)怎么改如果你要采多通道SQR3 里依次填通道號(hào)SQR1 的 L 改成通道數(shù)減一。濾波處理我一般會(huì)在讀回?cái)?shù)據(jù)后做 8 次平均簡(jiǎn)單有效比上卡爾曼省事。4.3 PWM 輸出與占空比調(diào)節(jié)PWM 本質(zhì)就是定時(shí)器加比較輸出配置時(shí)注意 PWM 模式和極性。BF7613BMXX 的定時(shí)器支持邊沿對(duì)齊和中心對(duì)齊做電機(jī)控制常用中心對(duì)齊做 LED 調(diào)光用邊沿對(duì)齊就夠了。// bf7613_pwm.c 中的 PWM 初始化 void PWM_Init(void) { RCC-APB1ENR | RCC_APB1ENR_TIM3EN; RCC-APB2ENR | RCC_APB2ENR_IOPBEN; // PB0 配置為復(fù)用推挽 GPIOB-CRL ~(0xFF 0); GPIOB-CRL | (0x0B 0); TIM3-PSC 47; // 1MHz 計(jì)數(shù) TIM3-ARR 999; // 1kHz PWM 頻率 TIM3-CCR3 500; // 通道3 占空比 50% TIM3-CCMR2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM 模式1 TIM3-CCER | TIM_CCER_CC3E; // 使能通道3 輸出 TIM3-CR1 | TIM_CR1_CEN; }邏輯說(shuō)明PSC 和 ARR 決定 PWM 頻率公式同定時(shí)器CCR3 決定占空比500/1000 就是 50%CCMR2 的 OC3M 位設(shè) PWM 模式1即計(jì)數(shù)值小于 CCR 時(shí)輸出有效電平CCER 的 CC3E 位使能輸出。參數(shù)怎么改要改頻率就調(diào) ARR要改占空比就調(diào) CCR3但注意 CCR3 不能大于 ARR。常見(jiàn)坑是忘了配 GPIO 復(fù)用波形出不來(lái)拿示波器一測(cè)發(fā)現(xiàn)引腳一直是低電平。5. 避坑與排查那些手冊(cè)上不會(huì)寫的翻車記錄例程跑通不代表沒(méi)問(wèn)題真正做項(xiàng)目時(shí)踩的坑往往藏在細(xì)節(jié)里。這一章我整理了 5 條實(shí)際調(diào)試中遇到的典型問(wèn)題每條按現(xiàn)象、原因、解決來(lái)寫你遇到類似情況可以直接對(duì)照。5.1 中斷進(jìn)不去程序卡在啟動(dòng)文件現(xiàn)象下載后程序不跑調(diào)試器顯示停在啟動(dòng)文件的 B 循環(huán)里。原因中斷向量表地址和實(shí)際 Flash 起始地址不匹配或者堆棧大小設(shè)小了導(dǎo)致溢出。解決檢查鏈接腳本里的 ROM 起始地址確認(rèn)和芯片手冊(cè)一致把堆棧大小從默認(rèn)的 0x400 改成 0x800 試試。5.2 串口發(fā)送正常但接收丟數(shù)據(jù)現(xiàn)象能收到單片機(jī)發(fā)的數(shù)據(jù)但單片機(jī)收上位機(jī)數(shù)據(jù)時(shí)偶爾丟包。原因接收中斷里沒(méi)有及時(shí)清標(biāo)志或者波特率誤差偏大。解決在中斷服務(wù)函數(shù)里先讀 DR 再清標(biāo)志順序反了會(huì)丟用示波器測(cè)一位時(shí)間誤差超過(guò) 3% 就調(diào) PLL 或者換晶振。5.3 ADC 采樣值跳動(dòng)超過(guò) 50 個(gè) LSB現(xiàn)象輸入電壓不變ADC 讀回值在幾十個(gè) LSB 范圍內(nèi)跳。原因采樣時(shí)間太短或者參考電壓不穩(wěn)。解決把采樣時(shí)間從 7.5 周期改成 239.5 周期在 VREF 引腳加 0.1uF 和 10uF 電容軟件上做 8 次平均。5.4 PWM 輸出波形有毛刺現(xiàn)象示波器看 PWM 上升沿有振鈴或者占空比偶爾跳變。原因GPIO 驅(qū)動(dòng)能力設(shè)太強(qiáng)或者 CCR 寄存器在運(yùn)行中被意外修改。解決把 GPIO 輸出速度從 50MHz 降到 2MHz檢查有沒(méi)有在中斷里改 CCR 值改的時(shí)候先關(guān)定時(shí)器。5.5 低功耗模式下喚醒后外設(shè)不工作現(xiàn)象進(jìn)入睡眠模式后按鍵喚醒但串口發(fā)不出數(shù)據(jù)。原因喚醒后系統(tǒng)時(shí)鐘默認(rèn)切回內(nèi)部 RC沒(méi)有重新配置 PLL。解決在喚醒中斷里重新調(diào)用 SystemInit或者手動(dòng)把時(shí)鐘切回 PLL 并等待穩(wěn)定。提示以上每一條都是我實(shí)際調(diào)試時(shí)記下來(lái)的你遇到新問(wèn)題可以先從時(shí)鐘、中斷標(biāo)志、GPIO 復(fù)用這三個(gè)方向查能覆蓋八成以上的異常。6. 進(jìn)階技巧用宏定義封裝寄存器操作與調(diào)試輸出例程用久了會(huì)發(fā)現(xiàn)直接寫寄存器雖然直觀但代碼可讀性和可移植性差。我一般會(huì)在例程基礎(chǔ)上加一層輕量封裝用宏定義把常用操作簡(jiǎn)化同時(shí)加一個(gè)條件編譯的調(diào)試輸出方便在不同階段切換。// bf7613_utils.h 中的封裝宏 #define GPIO_SET(port, pin) ((port)-BSRR (1 (pin))) #define GPIO_CLR(port, pin) ((port)-BRR (1 (pin))) #define GPIO_READ(port, pin) (((port)-IDR (pin)) 1) // 調(diào)試輸出開(kāi)關(guān) #define DEBUG_EN 1 #if DEBUG_EN #define DEBUG_PRINT(fmt, ...) printf(fmt, ##__VA_ARGS__) #else #define DEBUG_PRINT(fmt, ...) #endif邏輯說(shuō)明GPIO_SET 和 GPIO_CLR 利用 BSRR 和 BRR 寄存器實(shí)現(xiàn)原子操作比讀改寫 IDR 再寫 ODR 安全不會(huì)被打斷DEBUG_PRINT 用條件編譯控制發(fā)布版本把 DEBUG_EN 改成 0所有調(diào)試打印自動(dòng)消失不占 Flash 空間。參數(shù)怎么改printf 需要重定向 fputc 到串口這個(gè)在例程的 uart.c 里通常有現(xiàn)成實(shí)現(xiàn)你只要確認(rèn)串口初始化在 printf 之前調(diào)用就行。再分享一個(gè)驗(yàn)證時(shí)鐘配置對(duì)不對(duì)的小技巧把 MCO 引腳配置成輸出系統(tǒng)時(shí)鐘用示波器測(cè)頻率比看代碼算半天靠譜。配置方法是在 GPIO 復(fù)用寄存器里把對(duì)應(yīng)引腳設(shè)成 MCO 功能然后選時(shí)鐘源。這個(gè)功能在調(diào)試低功耗和波特率問(wèn)題時(shí)特別有用我每次改時(shí)鐘樹(shù)都會(huì)先測(cè) MCO確認(rèn)無(wú)誤再往下跑。從那以后我每次拿到新芯片的例程都強(qiáng)制自己先跑一遍 MCO 輸出和串口打印這兩個(gè)通了后面的外設(shè)才有意義。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取