PWM實(shí)驗(yàn):TIM1死區(qū)配置與波形實(shí)測)
1. 為什么六路互補(bǔ)PWM值得單獨(dú)做一次實(shí)驗(yàn)如果你正在用STM32G431做無刷電機(jī)驅(qū)動、數(shù)字電源或者三相逆變器六路互補(bǔ)PWM幾乎是繞不開的一道坎。它不是一個(gè)“配置完就能跑”的外設(shè)而是涉及定時(shí)器模式、死區(qū)插入、互補(bǔ)通道映射、中斷觸發(fā)、故障保護(hù)等一整套機(jī)制的協(xié)同工作。我見過太多人卡在“波形出不來”“上下橋臂直通”“死區(qū)沒生效”這類問題上最后只能換方案或者降頻湊合用。這次實(shí)驗(yàn)的核心目標(biāo)很明確用STM32G431的TIM1高級定時(shí)器生成三對互補(bǔ)PWM共六路帶可調(diào)死區(qū)時(shí)間并且驗(yàn)證中心對齊模式下波形的對稱性和中斷觸發(fā)行為。關(guān)鍵詞里的“六路互補(bǔ)”“TIM1”“STM32G431”“死區(qū)時(shí)間”正好覆蓋了從硬件選型到寄存器配置再到波形驗(yàn)證的完整鏈路。適合誰來參考如果你已經(jīng)會用CubeMX配置普通PWM但對互補(bǔ)輸出、死區(qū)、剎車功能還停留在“知道有但沒實(shí)際調(diào)過”的階段這篇內(nèi)容就是為你寫的。我會把配置邏輯、參數(shù)計(jì)算、實(shí)測波形、踩坑記錄全部攤開講盡量讓你看完就能在自己的板子上復(fù)現(xiàn)。2. 六路互補(bǔ)PWM的整體設(shè)計(jì)思路2.1 為什么選TIM1而不是普通定時(shí)器STM32G431屬于G4系列主打電機(jī)控制和數(shù)字電源片內(nèi)帶TIM1和TIM8兩個(gè)高級定時(shí)器。普通定時(shí)器比如TIM2/TIM3也能輸出PWM但它們沒有互補(bǔ)輸出和死區(qū)插入硬件要做六路互補(bǔ)只能靠軟件取反時(shí)序精度和安全性都不可靠。TIM1的高級特性正好匹配需求每個(gè)通道都有CHx和CHxN一對互補(bǔ)輸出硬件死區(qū)發(fā)生器死區(qū)時(shí)間可編程剎車輸入BKIN可快速封鎖輸出支持中心對齊模式適合電機(jī)FOC和LLC諧振變換器重復(fù)計(jì)數(shù)器和更新中斷可靈活觸發(fā)ADC采樣所以選TIM1不是“因?yàn)樗呒墶倍且驗(yàn)榛パa(bǔ)PWM的硬件需求只有高級定時(shí)器能滿足。用普通定時(shí)器加軟件方案在死區(qū)精度和故障響應(yīng)速度上會吃大虧。2.2 三對互補(bǔ)通道的映射關(guān)系TIM1有四個(gè)通道我們只用前三個(gè)就能湊出六路CH1PA8和CH1NPB13或PA7取決于復(fù)用CH2PA9和CH2NPB14或PB0CH3PA10和CH3NPB15或PB1在STM32G431上具體引腳要看數(shù)據(jù)手冊的AF映射表。我這次用的是PA8/PA9/PA10作為上橋臂PB13/PB14/PB15作為下橋臂這樣布局在常見的驅(qū)動板上比較順手。注意CHxN的極性可以通過CCER寄存器的CCxNP位獨(dú)立設(shè)置默認(rèn)是高電平有效。如果你的柵極驅(qū)動芯片是低電平開通這里必須改否則上電瞬間可能直通。2.3 中心對齊模式的選擇理由PWM模式有邊沿對齊和中心對齊兩種。邊沿對齊實(shí)現(xiàn)簡單但諧波分量集中在開關(guān)頻率及其倍數(shù)上對電機(jī)控制來說電流紋波更大。中心對齊模式下計(jì)數(shù)器先向上再向下PWM脈沖關(guān)于中心對稱等效開關(guān)頻率翻倍電流紋波更小FOC算法里的采樣時(shí)機(jī)也更規(guī)整。代價(jià)是中心對齊模式下更新事件發(fā)生在計(jì)數(shù)器到零和到ARR兩個(gè)點(diǎn)中斷頻率翻倍CPU負(fù)載略高。但對于G431這種帶FPU的Cortex-M4跑FOC完全夠用。我這次實(shí)驗(yàn)就是用的中心對齊模式1計(jì)數(shù)器在向上和向下計(jì)數(shù)時(shí)都產(chǎn)生比較動作。2.4 死區(qū)時(shí)間的計(jì)算邏輯死區(qū)時(shí)間不是隨便填的它由目標(biāo)死區(qū)時(shí)長和定時(shí)器時(shí)鐘頻率共同決定。公式是DTG[7:0] 死區(qū)時(shí)間 / T_dts其中T_dts是死區(qū)時(shí)鐘周期取決于TIM1的時(shí)鐘分頻。假設(shè)TIM1時(shí)鐘72MHz不分頻T_dts≈13.89ns。如果我要500ns死區(qū)那DTG值大約36。但DTG不是直接線性映射它分了幾段范圍需要查參考手冊的編碼表。實(shí)際配置時(shí)我一般先用CubeMX算個(gè)大概再用示波器實(shí)測微調(diào)。因?yàn)闁艠O驅(qū)動芯片和MOSFET的開關(guān)延遲也會吃掉一部分死區(qū)純理論計(jì)算往往偏樂觀。3. CubeMX配置與寄存器關(guān)鍵位解析3.1 時(shí)鐘樹和TIM1時(shí)鐘源設(shè)置G431的TIM1掛在APB2總線上。CubeMX里先把系統(tǒng)時(shí)鐘拉到170MHzG431的最大主頻APB2不分頻所以TIM1時(shí)鐘就是170MHz。這個(gè)頻率下T_dts≈5.88ns死區(qū)分辨率很高。但170MHz對柵極驅(qū)動來說可能太快實(shí)際開關(guān)頻率我設(shè)的是20kHzARR值用中心對齊模式計(jì)算ARR TIM1_CLK / (2 * F_pwm) 170MHz / (2 * 20kHz) 4250中心對齊模式下PWM頻率是時(shí)鐘除以2倍ARR這個(gè)別搞錯(cuò)否則實(shí)際頻率會差一倍。3.2 時(shí)基單元配置要點(diǎn)CubeMX里TIM1的配置項(xiàng)Counter Mode: Center Aligned 1Prescaler: 0Counter Period (ARR): 4250Internal Clock Division: No DivisionRepetition Counter: 0先不啟用重復(fù)計(jì)數(shù)Auto-reload preload: EnableRepetition Counter在電機(jī)控制里常用來每N個(gè)周期觸發(fā)一次更新中斷方便ADC采樣。這次實(shí)驗(yàn)先設(shè)為0保證每個(gè)周期都觸發(fā)。3.3 PWM通道和互補(bǔ)輸出配置每個(gè)通道的配置Mode: PWM Mode 1Pulse: 初始占空比比如ARR的一半Output compare preload: EnableFast Mode: Disable除非需要極短脈沖CH Polarity: HighCHN Polarity: HighIdle State: Reset互補(bǔ)輸出的關(guān)鍵在CCER寄存器CC1E1CC1NE1開啟CH1和CH1N輸出CC1P和CC1NP根據(jù)驅(qū)動芯片極性設(shè)置我用的柵極驅(qū)動是高電平開通所以兩個(gè)極性都設(shè)High。如果你用的是IR2104這類輸入高電平對應(yīng)輸出高那也設(shè)High。3.4 死區(qū)配置的寄存器細(xì)節(jié)死區(qū)寄存器BDTR的低8位是DTG高幾位控制OSSR、OSSI、BKE、BKP等。CubeMX里直接填Dead Time值它會自動算DTG編碼。我填的是500nsCubeMX算出DTG0x54左右。實(shí)測波形顯示上下橋臂之間確實(shí)有約520ns的間隔包含了驅(qū)動芯片的傳輸延遲基本符合預(yù)期。注意BDTR的MOE位主輸出使能必須置1否則所有輸出都是無效電平。CubeMX生成的代碼里會在HAL_TIM_PWM_Start之后自動設(shè)置MOE但如果你手動操作寄存器別忘了這一步。3.5 剎車功能和故障保護(hù)預(yù)留雖然這次實(shí)驗(yàn)沒接剎車引腳但BDTR里的BKE和BKP位建議先配好。BKE1開啟剎車功能BKP設(shè)置剎車輸入極性。一旦BKIN引腳被拉低或拉高取決于極性硬件會立刻封鎖所有輸出響應(yīng)時(shí)間只有幾個(gè)時(shí)鐘周期比軟件中斷快得多。實(shí)際做電機(jī)驅(qū)動時(shí)過流信號直接接到BKIN引腳比走ADC采樣再軟件關(guān)斷可靠得多。這個(gè)功能在調(diào)試階段可以先不啟用但量產(chǎn)固件里一定要加。4. 代碼實(shí)現(xiàn)與波形實(shí)測過程4.1 初始化代碼的關(guān)鍵片段CubeMX生成的初始化代碼里重點(diǎn)看這幾段htim1.Instance TIM1; htim1.Init.Prescaler 0; htim1.Init.CounterMode TIM_COUNTERMODE_CENTERALIGNED1; htim1.Init.Period 4250; htim1.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter 0; htim1.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE;死區(qū)配置在BDTR里sBreakDeadTimeConfig.OffStateRunMode TIM_OSSR_ENABLE; sBreakDeadTimeConfig.OffStateIDLEMode TIM_OSSI_ENABLE; sBreakDeadTimeConfig.LockLevel TIM_LOCKLEVEL_OFF; sBreakDeadTimeConfig.DeadTime 54; sBreakDeadTimeConfig.BreakState TIM_BREAK_DISABLE; sBreakDeadTimeConfig.BreakPolarity TIM_BREAKPOLARITY_HIGH; sBreakDeadTimeConfig.AutomaticOutput TIM_AUTOMATICOUTPUT_ENABLE;DeadTime54對應(yīng)的就是前面算的500ns左右。AutomaticOutput使能后MOE位會在下一個(gè)更新事件自動置1省去手動操作。4.2 啟動PWM輸出的順序啟動順序很重要搞錯(cuò)了可能瞬間直通先配置好所有通道的比較值和死區(qū)調(diào)用HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1)等啟動各通道最后調(diào)用HAL_TIMEx_PWMN_Start啟動互補(bǔ)通道如果需要調(diào)用__HAL_TIM_MOE_ENABLE(htim1)手動使能主輸出我實(shí)測下來CubeMX生成的代碼在HAL_TIM_PWM_Start內(nèi)部已經(jīng)處理了MOE但如果你用的是LL庫或直接寄存器操作一定要確認(rèn)MOE狀態(tài)。4.3 示波器實(shí)測波形分析用四通道示波器抓CH1、CH1N、CH2、CH2N的波形CH1和CH1N嚴(yán)格互補(bǔ)死區(qū)約520nsCH1和CH2之間相位差120度中心對齊模式下占空比50%時(shí)高電平時(shí)間約25us周期50us死區(qū)期間兩路都是低電平?jīng)]有重疊這里有個(gè)細(xì)節(jié)中心對齊模式下CH1的上升沿在計(jì)數(shù)器向上計(jì)數(shù)到比較值時(shí)產(chǎn)生下降沿在向下計(jì)數(shù)到比較值時(shí)產(chǎn)生。所以脈沖是關(guān)于中心對稱的用示波器的延遲觸發(fā)能看得很清楚。4.4 更新中斷的觸發(fā)行為開啟TIM1更新中斷后在中心對齊模式下每個(gè)PWM周期會觸發(fā)兩次中斷一次在計(jì)數(shù)器到ARR一次在到0。中斷頻率是PWM頻率的兩倍即40kHz。這個(gè)特性在FOC里很有用可以在計(jì)數(shù)器到0時(shí)觸發(fā)ADC采樣此時(shí)電流紋波最小。但要注意中斷服務(wù)程序里別做太多事40kHz下留給CPU的時(shí)間只有25us。void TIM1_UP_TIM16_IRQHandler(void) { if (__HAL_TIM_GET_FLAG(htim1, TIM_FLAG_UPDATE) ! RESET) { __HAL_TIM_CLEAR_FLAG(htim1, TIM_FLAG_UPDATE); // 這里放ADC觸發(fā)或換相邏輯 } }4.5 占空比動態(tài)調(diào)整測試用__HAL_TIM_SET_COMPARE動態(tài)改比較值觀察波形變化。從10%到90%掃一遍死區(qū)時(shí)間保持不變互補(bǔ)關(guān)系也沒有破壞。這說明硬件死區(qū)發(fā)生器是獨(dú)立于比較值的改占空比不會影響死區(qū)。但要注意如果比較值接近ARR或0可能會吃掉一部分死區(qū)。比如占空比99%時(shí)高電平時(shí)間幾乎占滿整個(gè)周期死區(qū)仍然存在但有效占空比會略低于設(shè)定值。這是正?,F(xiàn)象計(jì)算效率時(shí)要考慮進(jìn)去。5. 常見問題與排查技巧實(shí)錄5.1 波形出不來或只有一路輸出最常見的原因是MOE位沒置1或者CCxE/CCxNE沒使能。排查順序讀BDTR寄存器確認(rèn)MOE1讀CCER寄存器確認(rèn)CC1E1且CC1NE1檢查GPIO復(fù)用是否正確PA8應(yīng)該配成AF1TIM1_CH1確認(rèn)HAL_TIM_PWM_Start和HAL_TIMEx_PWMN_Start都調(diào)用了我遇到過一種情況只調(diào)了HAL_TIM_PWM_Start忘了調(diào)互補(bǔ)通道的啟動函數(shù)結(jié)果CH1有波形CH1N一直是低電平。補(bǔ)上HAL_TIMEx_PWMN_Start就好了。5.2 死區(qū)時(shí)間不對或沒有死區(qū)先確認(rèn)BDTR的DTG值是否寫進(jìn)去了。CubeMX有時(shí)會因?yàn)闀r(shí)鐘配置變化重新計(jì)算DTG如果你手動改過時(shí)鐘樹要重新檢查。另一個(gè)坑是死區(qū)時(shí)間只在互補(bǔ)輸出之間生效如果你把CH1和CH1N都配成同相輸出那死區(qū)不會插入。必須確保CC1P和CC1NP設(shè)置正確讓兩路是反相關(guān)系。5.3 上下橋臂直通燒管這是最危險(xiǎn)的情況。除了死區(qū)沒配好還有幾個(gè)可能柵極驅(qū)動芯片的使能引腳沒控制好上電瞬間兩路都開通死區(qū)時(shí)間太短小于MOSFET的關(guān)斷延遲剎車功能沒啟用過流時(shí)沒有硬件封鎖我的經(jīng)驗(yàn)是第一次上電一定要用限流電源先不接功率管只測驅(qū)動芯片輸出。確認(rèn)死區(qū)正常后再接母線電壓。另外死區(qū)時(shí)間建議留足余量比如MOSFET關(guān)斷需要200ns那死區(qū)至少設(shè)500ns。5.4 中心對齊模式下頻率不對中心對齊模式的PWM頻率公式是F_pwm TIM_CLK / (2 * ARR)不是TIM_CLK / ARR。很多人按邊沿對齊的公式算結(jié)果實(shí)際頻率只有預(yù)期的一半。我一開始也踩過這個(gè)坑示波器一測發(fā)現(xiàn)是10kHz而不是20kHz回頭改ARR才對上。5.5 中斷頻率翻倍導(dǎo)致CPU過載中心對齊模式下更新中斷是PWM頻率的兩倍。如果你在中斷里做了太多浮點(diǎn)運(yùn)算40kHz下CPU可能跑不過來。解決辦法用重復(fù)計(jì)數(shù)器降低中斷頻率把非關(guān)鍵邏輯移到主循環(huán)用DMA觸發(fā)ADC減少中斷里的事我實(shí)測在170MHz的G431上40kHz中斷里只做ADC觸發(fā)和簡單換相CPU占用不到5%。但如果加PID運(yùn)算和坐標(biāo)變換就要考慮優(yōu)化了。5.6 互補(bǔ)輸出極性搞反不同柵極驅(qū)動芯片的輸入極性不一樣。有的高電平開通有的低電平開通。如果搞反了上電就是直通。排查方法很簡單不接功率管用示波器看驅(qū)動芯片輸出。如果上橋臂輸出高時(shí)下橋臂也輸出高那就是極性反了改CCxNP位即可。6. 實(shí)操心得與參數(shù)優(yōu)化建議6.1 死區(qū)時(shí)間的實(shí)測微調(diào)方法理論計(jì)算的死區(qū)時(shí)間只是起點(diǎn)。實(shí)際調(diào)試時(shí)我會先把死區(qū)設(shè)大一點(diǎn)比如1us用示波器確認(rèn)互補(bǔ)關(guān)系正常然后逐步減小到目標(biāo)值。每減一次觀察驅(qū)動芯片輸出是否還有重疊。最終值通常比理論值大20%到50%因?yàn)橐采w驅(qū)動芯片的傳輸延遲和MOSFET的關(guān)斷拖尾。6.2 開關(guān)頻率與死區(qū)時(shí)間的權(quán)衡開關(guān)頻率越高死區(qū)占空比損失越大。比如20kHz下死區(qū)500ns占空比損失約1%。如果提到100kHz同樣500ns死區(qū)損失就到5%了。所以高頻應(yīng)用要選低柵極電荷的MOSFET和快速驅(qū)動芯片把死區(qū)壓到200ns以內(nèi)。6.3 用DMA自動更新比較值如果要做正弦波調(diào)制手動改比較值太慢??梢杂肈MA把預(yù)先算好的正弦表搬到CCR寄存器。TIM1的更新事件觸發(fā)DMA請求每個(gè)PWM周期自動更新一次CPU幾乎不參與。這個(gè)方案在FOC和SPWM里都很常用。6.4 剎車輸入的硬件保護(hù)設(shè)計(jì)BKIN引腳建議直接接過流比較器的輸出不要經(jīng)過軟件。硬件剎車響應(yīng)時(shí)間只有幾個(gè)時(shí)鐘周期軟件中斷至少幾微秒差距很大。調(diào)試時(shí)可以先禁用剎車量產(chǎn)固件里一定要啟用并且把剎車后的狀態(tài)設(shè)成安全電平。6.5 示波器抓波形的觸發(fā)技巧六路互補(bǔ)PWM用四通道示波器抓不全可以分兩次抓先抓CH1/CH1N/CH2/CH2N再抓CH2/CH2N/CH3/CH3N。觸發(fā)源選CH1的上升沿時(shí)基設(shè)成10us/div能看清死區(qū)和相位關(guān)系。如果要測死區(qū)精確值把時(shí)基打到100ns/div用光標(biāo)測量。6.6 常見參數(shù)速查表參數(shù)推薦值說明PWM頻率20kHz電機(jī)驅(qū)動常用兼顧效率和噪聲死區(qū)時(shí)間500ns根據(jù)MOSFET和驅(qū)動芯片調(diào)整時(shí)鐘分頻不分頻170MHz下死區(qū)分辨率約5.88ns計(jì)數(shù)模式中心對齊1電流紋波小適合FOCARR值4250對應(yīng)20kHz中心對齊重復(fù)計(jì)數(shù)器0每周期觸發(fā)更新中斷MOE使能必須置1才有輸出剎車使能過流保護(hù)用這套參數(shù)在我自己的G431驅(qū)動板上跑得很穩(wěn)帶一個(gè)24V/10A的BLDC電機(jī)死區(qū)波形干凈沒有直通現(xiàn)象。如果你用的是不同的MOSFET或驅(qū)動芯片死區(qū)時(shí)間需要重新微調(diào)但整體配置邏輯是一樣的。