量實(shí)戰(zhàn):定時(shí)器外部計(jì)數(shù)與輸入捕獲方案詳解)
簡(jiǎn)介為STM32開發(fā)者準(zhǔn)備的頻率測(cè)量代碼資源基于定時(shí)器輸入捕獲原理解決外部脈沖或時(shí)鐘信號(hào)頻率檢測(cè)需求。資源提供完整工程文件涵蓋TIM定時(shí)器模式選擇、輸入捕獲通道配置、中斷服務(wù)程序設(shè)計(jì)以及連續(xù)捕獲時(shí)間戳差值計(jì)算周期與頻率的實(shí)現(xiàn)方法并給出HAL庫(kù)關(guān)鍵API調(diào)用示例如HAL_TIM_IC_Init、HAL_TIM_IC_ConfigChannel與HAL_TIM_IC_GetCapturedValue稍作適配即可移植到實(shí)際項(xiàng)目中。資源包為zip壓縮包共125個(gè)文件以.h頭文件與.c源文件為主同時(shí)包含uvproj工程配置、hex燒錄文件及編譯中間文件等壓縮包整體約1.87MB。目前已有2143人學(xué)習(xí)下載適合具備一定STM32基礎(chǔ)、希望快速掌握定時(shí)器測(cè)頻技術(shù)的開發(fā)者也可作為學(xué)習(xí)定時(shí)器中斷及信號(hào)測(cè)量機(jī)制的實(shí)戰(zhàn)參考。 做STM32開發(fā)的人遲早都要寫一次測(cè)量頻率的代碼。不管是給畢設(shè)做轉(zhuǎn)速測(cè)量還是給工控板卡采集編碼器輸出甚至只是想把一個(gè)未知波形大概摸清楚stm32定時(shí)器就是你手里最趁手的工具。這篇文章不繞彎子直接從方案選型、原理、HAL庫(kù)代碼到常見踩坑給你捋一遍示例基于STM32F103思路通用于F4/G0系列。看完之后你不僅能寫出能跑的測(cè)量頻率代碼還能知道為什么這么寫、測(cè)出來(lái)不準(zhǔn)時(shí)該往哪個(gè)方向排查。1. 先判斷你的信號(hào)測(cè)周期還是數(shù)脈沖1.1 測(cè)量頻率的兩個(gè)基本思路頻率的本質(zhì)是單位時(shí)間內(nèi)重復(fù)次數(shù)。STM32測(cè)頻率繞不開兩種思路一是數(shù)脈沖固定一個(gè)時(shí)間窗口比如1秒數(shù)這個(gè)窗口里來(lái)了多少個(gè)上升沿個(gè)數(shù)就是頻率二是測(cè)周期捕獲兩次相鄰上升沿的時(shí)間差得到周期T再用f1/T換算出頻率。這兩條路各有各的適用場(chǎng)景沒(méi)有誰(shuí)絕對(duì)更好。數(shù)脈沖的思路適合高頻信號(hào)因?yàn)榇翱趦?nèi)脈沖多量化誤差就小測(cè)周期的思路適合低頻信號(hào)因?yàn)橹芷陂L(zhǎng)計(jì)時(shí)分辨率占比就高。你要是一上來(lái)不分青紅皂白用捕獲法去測(cè)1MHz的信號(hào)大概率會(huì)發(fā)現(xiàn)捕獲中斷根本忙不過(guò)來(lái)或者測(cè)量值跳得像過(guò)山車。1.2 三種硬件實(shí)現(xiàn)方案對(duì)比STM32的定時(shí)器模塊很靈活同一個(gè)測(cè)頻需求可以用三種方式實(shí)現(xiàn)定時(shí)器外部計(jì)數(shù)模式定時(shí)器由外部引腳脈沖驅(qū)動(dòng)計(jì)數(shù)配一個(gè)基本定時(shí)器做時(shí)間窗口。窗口結(jié)束時(shí)讀計(jì)數(shù)器得到脈沖個(gè)數(shù)。輸入捕獲模式配置某個(gè)通道捕獲上升沿記錄捕獲寄存器CCR的值相鄰兩次捕獲值之差就是周期。PWM輸入模式其實(shí)是輸入捕獲的變種用兩個(gè)通道同時(shí)捕獲周期和占空比。如果只需要頻率沒(méi)必要用它徒增配置復(fù)雜度。這三種方式在STM32F103上都能實(shí)現(xiàn)但占用的定時(shí)器資源、引腳、精度特性完全不同。我把它們整理成一張表方案測(cè)量原理適合頻率范圍核心誤差來(lái)源占用資源外部計(jì)數(shù)模式窗口內(nèi)數(shù)脈沖高頻1kHz窗口邊界±1個(gè)脈沖2個(gè)定時(shí)器輸入捕獲模式相鄰邊沿時(shí)間差低頻10kHz計(jì)時(shí)分辨率、邊沿抖動(dòng)1個(gè)定時(shí)器1個(gè)通道PWM輸入模式捕獲周期與占空比低頻-中頻同輸入捕獲1個(gè)定時(shí)器2個(gè)通道外部計(jì)數(shù)模式的精度公式很好算窗口T秒內(nèi)數(shù)到N個(gè)脈沖頻率fN/T。誤差最多就是窗口邊界處多一個(gè)少一個(gè)脈沖所以f的絕對(duì)誤差是1/T。1秒窗口就是±1Hz0.1秒窗口就是±10Hz。這個(gè)特性讓它天生適合高頻信號(hào)信號(hào)頻率越高相對(duì)誤差越小。輸入捕獲模式的精度取決于預(yù)分頻后的計(jì)時(shí)分辨率。假設(shè)定時(shí)器時(shí)鐘72MHz預(yù)分頻71那么計(jì)數(shù)器每1us加1。被測(cè)信號(hào)周期如果是10ms那么兩次捕獲差約10000誤差±1us就是0.01%精度很高。但如果被測(cè)信號(hào)是100kHz周期10us計(jì)數(shù)只有10個(gè)誤差直接變成10%。1.3 實(shí)際項(xiàng)目里的選型經(jīng)驗(yàn)我知道很多人上來(lái)就想找“萬(wàn)能方案”現(xiàn)實(shí)是沒(méi)有。我在實(shí)際項(xiàng)目里的做法是先粗測(cè)頻率范圍再?zèng)Q定具體方案。手里有示波器就用示波器看沒(méi)有示波器就先寫一個(gè)臨時(shí)外部計(jì)數(shù)程序窗口設(shè)長(zhǎng)一點(diǎn)把頻率量級(jí)估出來(lái)。小于1kHz的走輸入捕獲大于1kHz的走外部計(jì)數(shù)如果有占空比測(cè)量需求再考慮PWM輸入模式。工程上還有一點(diǎn)容易被忽略測(cè)的是干凈方波還是帶噪聲的傳感器信號(hào)。像編碼器輸出、霍爾傳感器輸出波形沿往往不夠陡甚至帶有抖動(dòng)。這種信號(hào)直接用定時(shí)器捕獲容易一次性觸發(fā)兩次測(cè)出來(lái)的頻率偏高。后面會(huì)專門講怎么處理波形整形的問(wèn)題。2. 測(cè)頻之前必須搞清楚的時(shí)鐘和引腳2.1 定時(shí)器時(shí)鐘從哪里來(lái)很多初學(xué)者把定時(shí)器當(dāng)作一個(gè)黑盒直接在CubeMX里給Prescaler和Period填數(shù)字。但測(cè)頻率這件事時(shí)鐘源錯(cuò)了后面全白搭。STM32F103的定時(shí)器時(shí)鐘分配有個(gè)特點(diǎn)掛在APB1上的定時(shí)器TIM2-TIM7等如果APB1預(yù)分頻不為1定時(shí)器時(shí)鐘是APB1的兩倍如果APB1預(yù)分頻是1那定時(shí)器時(shí)鐘就等于APB1。舉例來(lái)說(shuō)系統(tǒng)時(shí)鐘配到72MHz時(shí)APB1一般分頻到36MHz這時(shí)TIM2-TIM7的時(shí)鐘不是36MHz而是72MHz。你要是不了解這條規(guī)則以為定時(shí)器時(shí)鐘是36MHz預(yù)分頻和周期算出來(lái)的閘門時(shí)間就偏了一倍最后的頻率測(cè)量結(jié)果也會(huì)跟著偏一倍。建議在代碼里不要硬編碼時(shí)鐘數(shù)值直接調(diào)HAL_RCC_GetPCLK1Freq()或HAL_RCC_GetPCLK2Freq()再根據(jù)分頻關(guān)系換算成定時(shí)器時(shí)鐘。這樣即使換到F4或G0系列、改了系統(tǒng)時(shí)鐘測(cè)頻代碼的時(shí)鐘換算部分也不會(huì)出錯(cuò)。2.2 引腳映射波形進(jìn)不來(lái)一切白搭F103的定時(shí)器輸入引腳有好幾組默認(rèn)引腳和重映射引腳不同。比如TIM2_CH1默認(rèn)在PA0重映射后可以到PA15TIM3_CH1默認(rèn)在PA6重映射后到PB4。你用CubeMX配置時(shí)它會(huì)自動(dòng)分配但如果是手寫寄存器或移植別人的工程就要特別注意引腳是否被復(fù)用成了普通GPIO。這里有個(gè)常見坑PA15、PB3、PB4這幾個(gè)引腳在F103上默認(rèn)是JTAG調(diào)試引腳上電后不是普通GPIO。你要是把它們當(dāng)輸入捕獲引腳用必須先把AFIO的SWJ配置改為關(guān)閉JTAG、保留SWD否則引腳根本不受你控制。很多人的程序下載過(guò)一次之后第二次就報(bào)“no stm32 target found”也是這個(gè)原因后面詳細(xì)說(shuō)。2.3 晶振電容和頻率基準(zhǔn)的關(guān)系測(cè)頻率的本質(zhì)是拿被測(cè)信號(hào)和單片機(jī)內(nèi)部時(shí)鐘做對(duì)比。單片機(jī)內(nèi)部時(shí)鐘不準(zhǔn)測(cè)得再努力也白搭。F103的外部高速晶振HSE一般是8MHz晶振旁邊那兩個(gè)負(fù)載電容不是隨便焊上去的。匹配電容選得不對(duì)晶振起振頻率會(huì)偏移雖然偏移量很小但高頻測(cè)量時(shí)會(huì)被放大。無(wú)源晶振匹配電容的工程經(jīng)驗(yàn)公式是C1 C2 2 × CL - Cstray其中CL是晶振規(guī)格書里的負(fù)載電容Cstray是芯片引腳和PCB走線的寄生電容一般取3~5pF。比如8MHz晶振規(guī)格書標(biāo)CL12pF那么C1C2約等于2×12-420pF。實(shí)際項(xiàng)目中用12pF到22pF都常見關(guān)鍵是要選質(zhì)量靠譜的晶振和電容別在頻率基準(zhǔn)上省錢。3. 兩種核心測(cè)頻代碼的完整實(shí)現(xiàn)3.1 外部計(jì)數(shù)法1秒閘門測(cè)高頻先說(shuō)我最常用的外部計(jì)數(shù)方案。思路是TIM3工作在外部時(shí)鐘模式1由TI1引腳默認(rèn)PA6需要復(fù)用為TIM3_CH1的上升沿驅(qū)動(dòng)計(jì)數(shù)器。然后TIM6配置為1秒中斷一次在TIM6中斷里讀TIM3的計(jì)數(shù)器值這個(gè)值就是1秒內(nèi)的脈沖個(gè)數(shù)數(shù)值上等于頻率。CubeMX里TIM3的配置要點(diǎn)Clock Source選擇Internal ClockSlave Mode選擇External Clock Mode 1Trigger Source選擇TI1FP1Prescaler0Counter Period0xFFFF。注意這里的Clock Source雖然是Internal Clock但實(shí)際上外部脈沖會(huì)通過(guò)觸發(fā)源驅(qū)動(dòng)計(jì)數(shù)這是CubeMX中配置外部計(jì)數(shù)模式的常規(guī)做法。關(guān)鍵代碼如下// TIM3初始化省略重點(diǎn)看中斷處理邏輯 volatile uint32_t overflowCount 0; volatile uint32_t measuredFreq 0; // TIM3更新中斷外部脈沖導(dǎo)致計(jì)數(shù)器自然溢出時(shí)進(jìn)入 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM3) { overflowCount; } else if (htim-Instance TIM6) { uint32_t totalPulse overflowCount * 65536 __HAL_TIM_GET_COUNTER(htim3); overflowCount 0; measuredFreq totalPulse; // 窗口1秒脈沖數(shù)就是Hz __HAL_TIM_SET_COUNTER(htim3, 0); } }這段代碼里最容易漏掉的是overflowCount。外部脈沖頻率如果超過(guò)65535Hz1秒內(nèi)TIM3會(huì)溢出多次你不統(tǒng)計(jì)溢出次數(shù)讀出來(lái)的頻率就會(huì)周期性歸零。TIM6的1秒窗口到了之后先算總脈沖數(shù)再把overflowCount和CNT清零保證下一個(gè)窗口從零開始計(jì)。main函數(shù)里啟動(dòng)兩個(gè)定時(shí)器HAL_TIM_Base_Start_IT(htim6); // 1秒閘門 HAL_TIM_SlaveConfigSynchro(htim3, TIM_SLAVEMODE_EXTERNAL, sSlaveConfig); HAL_TIM_Base_Start(htim3); // 外部計(jì)數(shù)啟動(dòng)實(shí)測(cè)下來(lái)用這個(gè)方案測(cè)10kHz以上的信號(hào)非常穩(wěn)誤差就是±1Hz。唯一要注意的是TIM6的窗口不要用HAL_Delay去湊中斷里也不能做耗時(shí)操作否則窗口就不準(zhǔn)了。3.2 輸入捕獲法低頻信號(hào)測(cè)周期低頻信號(hào)用數(shù)脈沖方案很不劃算比如50Hz信號(hào)1秒窗口只有50個(gè)脈沖理論誤差就有1Hz相對(duì)誤差2%。這種情況改用輸入捕獲測(cè)周期精度高得多。配置TIM4_CH1默認(rèn)PA6注意和前面TIM3外部計(jì)數(shù)別沖突預(yù)分頻設(shè)為71這樣計(jì)數(shù)器頻率是1MHz計(jì)時(shí)分辨率1us。周期寄存器0xFFFF捕獲通道選擇上升沿觸發(fā)。// TIM4捕獲中斷 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM4) { static uint16_t lastCapt 0; uint16_t cur __HAL_TIM_GET_COMPARE(htim4, TIM_CHANNEL_1); uint16_t diff; if (cur lastCapt) { diff cur - lastCapt; } else { diff 65535 - lastCapt cur 1; } lastCapt cur; // diff單位是1usfreq單位是Hz measuredFreq 1000000UL / diff; } }啟動(dòng)部分配置好捕獲通道后調(diào)用HAL_TIM_IC_Start_IT(htim4, TIM_CHANNEL_1)開啟捕獲中斷。這段代碼處理了計(jì)數(shù)器回繞的情況。如果cur小于lastCapt說(shuō)明計(jì)數(shù)器從65535回繞到了0周期跨越了一次回繞要把差值補(bǔ)回來(lái)。實(shí)際中斷回調(diào)里還有更細(xì)的坑比如static變量lastCapt在系統(tǒng)初始化時(shí)要記得清零否則第一次捕獲算出來(lái)的頻率可能是錯(cuò)的。輸入捕獲方案測(cè)量50Hz信號(hào)理論頻率值是1000000/2000050Hz±1us的量化誤差帶來(lái)約0.005%的相對(duì)誤差和外部計(jì)數(shù)法的2%相比提升非常明顯。但要注意如果信號(hào)頻率上升到幾百kHzdiff值變得很小此時(shí)要適當(dāng)降低預(yù)分頻提高計(jì)時(shí)分辨率或者干脆切回外部計(jì)數(shù)法。3.3 精度調(diào)整的實(shí)操心得兩類方案的精度調(diào)整完全遵循一個(gè)原則讓測(cè)量窗口內(nèi)的計(jì)數(shù)值盡量大。外部計(jì)數(shù)法就是拉長(zhǎng)閘門時(shí)間1秒不夠就2秒代價(jià)是響應(yīng)變慢輸入捕獲法就是提高計(jì)時(shí)分辨率預(yù)分頻往小調(diào)代價(jià)是計(jì)數(shù)器溢出變快處理回繞的代碼不能少。實(shí)測(cè)過(guò)程中我還發(fā)現(xiàn)輸入捕獲法測(cè)頻率時(shí)測(cè)量結(jié)果在相鄰幾個(gè)值之間跳動(dòng)是正常的這是±1量化的正常表現(xiàn)。如果你看到結(jié)果跳變量很大那不是量化問(wèn)題大概率是信號(hào)沿不干凈需要去查波形。真正要做到高精度可以考慮多次測(cè)量取平均或者用DMA批量捕獲多組周期再做處理但一般應(yīng)用沒(méi)必要上這么復(fù)雜。4. 實(shí)測(cè)中容易踩的坑和排查速查表4.1 頻率亂跳波形整形問(wèn)題很多人測(cè)頻率遇到的最大問(wèn)題是“讀數(shù)不穩(wěn)定”。代碼寫得沒(méi)問(wèn)題定時(shí)器配置也對(duì)但頻率值一下高一下低。我遇到最多的情況是信號(hào)沿太差導(dǎo)致的。傳感器輸出、電機(jī)編碼器輸出這類信號(hào)上升沿可能非常緩慢而STM32引腳的施密特觸發(fā)器觸發(fā)閾值是固定的信號(hào)緩慢爬升時(shí)很容易在閾值附近抖動(dòng)造成一次觸發(fā)變成兩次。解決辦法有三個(gè)層次最簡(jiǎn)單的在輸入引腳和GND之間加一個(gè)10k下拉電阻把懸空噪聲拉低效果更好的加一個(gè)施密特觸發(fā)器芯片比如74HC14做波形整形把緩慢變化的信號(hào)變成陡峭的方波如果有條件優(yōu)先處理源頭看信號(hào)是不是負(fù)載太重串一個(gè)幾百歐的電阻再進(jìn)引腳。我在測(cè)電機(jī)編碼器時(shí)遇到過(guò)這類問(wèn)題加了74HC14之后讀數(shù)穩(wěn)定了很多。4.2 delay卡死測(cè)頻程序里的經(jīng)典翻車熱詞里有“stm32延時(shí)函數(shù)delay卡死”在測(cè)頻程序里真的太常見了。很多人的第一版代碼喜歡在while循環(huán)里先HAL_Delay(1000)再去讀計(jì)數(shù)值。結(jié)果程序跑起來(lái)經(jīng)常卡在HAL_Delay里出不來(lái)或者延時(shí)時(shí)間完全不對(duì)。原因基本出在時(shí)鐘配置上。HAL_Delay依賴SysTickSysTick的時(shí)鐘源在SystemClock_Config里沒(méi)更新的話HAL_Delay的時(shí)間基準(zhǔn)就是錯(cuò)的。更隱蔽的問(wèn)題是如果某個(gè)中斷優(yōu)先級(jí)太高在中斷服務(wù)函數(shù)里長(zhǎng)時(shí)間占用CPUSysTick的中斷無(wú)法及時(shí)響應(yīng)HAL_Delay就會(huì)表現(xiàn)出“卡死”。我給你的建議是測(cè)頻程序里不要用HAL_Delay做閘門時(shí)間老老實(shí)實(shí)開一個(gè)硬件定時(shí)器做時(shí)間窗口。這樣既精確又不會(huì)跟SysTick產(chǎn)生耦合。如果只是調(diào)試時(shí)用也要確認(rèn)SystemClock_Config正確并且不要在中斷回調(diào)里放HAL_Delay。4.3 連不上調(diào)試器error: no stm32 target found!熱詞里有一條“error: no stm32 target found! if your product embeds debug authentication”這個(gè)報(bào)錯(cuò)我見得太多了。最典型的場(chǎng)景程序里把某個(gè)引腳配置成普通GPIO恰好這個(gè)引腳是SWDIO或SWCLK第一次燒錄成功程序跑起來(lái)后占用了調(diào)試引腳第二次就再也連不上了。F103上要特別注意PB3、PB4、PA15這幾個(gè)引腳的復(fù)用配置。如果軟件里執(zhí)行了類似“完全關(guān)閉SWJ”的操作ST-Link會(huì)徹底失去和芯片的通信通道。遇到這種情況處理方法是用stlink工具配合復(fù)位信號(hào)連接按住板子復(fù)位鍵不放點(diǎn)擊燒錄/連接等軟件開始通信后再釋放復(fù)位鍵。另一種方案是把BOOT0拉高進(jìn)入ISP模式擦除芯片后再恢復(fù)正常模式。不管哪種方案只能算一次性的救急手段。治本的辦法是工程項(xiàng)目里默認(rèn)保留SWD調(diào)試功能只在量產(chǎn)固件里才關(guān)閉調(diào)試引腳。4.4 中斷進(jìn)一會(huì)就不進(jìn)了有朋友遇到過(guò)這樣的情況程序剛跑起來(lái)能測(cè)量過(guò)幾秒中斷就不進(jìn)來(lái)了頻率值停留在最后讀數(shù)上。排查思路分兩步走。第一看NVIC優(yōu)先級(jí)配沒(méi)配對(duì)定時(shí)器中斷優(yōu)先級(jí)如果被其他中斷長(zhǎng)期搶占回調(diào)執(zhí)行會(huì)非常滯后第二更常見的是中斷回調(diào)里干了太多事比如在回調(diào)里串口打印、處理浮點(diǎn)運(yùn)算導(dǎo)致回調(diào)執(zhí)行時(shí)間超過(guò)了被測(cè)信號(hào)周期捕獲事件被不斷錯(cuò)過(guò)。處理辦法是中斷回調(diào)里只記錄捕獲值、置一個(gè)標(biāo)志位主循環(huán)里檢測(cè)到標(biāo)志位再做頻率計(jì)算、串口打印、顯示這些耗時(shí)的活。我自己的代碼就是這么寫的回調(diào)里就兩三行絕不拖泥帶水。4.5 問(wèn)題排查速查表故障現(xiàn)象可能原因排查方向解決辦法測(cè)量值偏高或亂跳信號(hào)沿抖動(dòng)、引腳懸空示波器看波形沿加上下拉、施密特整形測(cè)量值周期性歸零計(jì)數(shù)器溢出未統(tǒng)計(jì)檢查溢出計(jì)數(shù)邏輯統(tǒng)計(jì)overflowCount低頻測(cè)不準(zhǔn)信號(hào)頻率低于量化粒度檢查閘門時(shí)間/分辨率改用輸入捕獲測(cè)周期高頻雙擊捕獲中斷來(lái)不及響應(yīng)看中斷回調(diào)代碼量回調(diào)精簡(jiǎn)只置標(biāo)志HAL_Delay卡死SysTick時(shí)鐘配置錯(cuò)誤檢查SystemClock_Config用硬件定時(shí)器做閘門調(diào)試器連不上SWD引腳被復(fù)用檢查PA15/PB3/PB4配置復(fù)位連接或ISP擦除頻率整體偏大/偏小時(shí)鐘基準(zhǔn)不對(duì)確認(rèn)HSE和APB分頻核對(duì)時(shí)鐘樹、晶振電容4.6 再補(bǔ)一個(gè)高頻測(cè)量的擴(kuò)展方案如果你要測(cè)的頻率超過(guò)定時(shí)器外部時(shí)鐘模式能夠可靠處理的范圍比如幾MHz以上可以加一個(gè)外部預(yù)分頻器芯片先把信號(hào)分頻再送給STM32軟件里把測(cè)到的頻率乘回分頻倍數(shù)即可。另外STM32外部時(shí)鐘模式1本身也支持ETR引腳的預(yù)分頻功能能夠在硬件層面對(duì)輸入脈沖做分頻這個(gè)功能很多人在CubeMX里沒(méi)注意到。啟用方法是在TIMx的SlaveMode配置里找到External Clock Mode 1然后在ETR相關(guān)配置里把Prescaler設(shè)成2、4或8。說(shuō)實(shí)話我在實(shí)際項(xiàng)目里很少直接去測(cè)超過(guò)1MHz的信號(hào)更多是把測(cè)頻功能當(dāng)作系統(tǒng)的一個(gè)模塊配合按鍵切換量程、配合OLED顯示結(jié)果。測(cè)頻代碼本身不復(fù)雜復(fù)雜的是把它穩(wěn)定地融到整個(gè)系統(tǒng)里。最后再分享一個(gè)我自己的封裝習(xí)慣把這套測(cè)頻邏輯封裝成一個(gè)獨(dú)立模塊對(duì)外只暴露Init、Start、GetFreq三個(gè)接口具體用哪個(gè)定時(shí)器、哪個(gè)引腳通過(guò)宏定義寫在頭文件頂部。這樣等下次換個(gè)項(xiàng)目、換塊板子只要改宏定義就能復(fù)用整套代碼。我踩過(guò)幾次“測(cè)頻調(diào)好了結(jié)果換了個(gè)板子全得重寫”的坑之后深深覺(jué)得正確的工作量應(yīng)該花在封裝上而不是每次從零開始抄寄存器。本文還有配套的精品資源點(diǎn)擊獲取