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