PWM配置詳解:從死區(qū)時間到電機(jī)驅(qū)動實(shí)戰(zhàn))
1. 從需求到方案為什么需要互補(bǔ)PWM在電機(jī)驅(qū)動、逆變電源這些強(qiáng)電應(yīng)用里直接用一個引腳輸出的PWM波去控制一個橋臂的開關(guān)管是行不通的。想象一下一個H橋的上管和下管如果控制信號完全同步上管導(dǎo)通PWM高電平時下管也導(dǎo)通那結(jié)果就是電源正負(fù)極直接短路瞬間產(chǎn)生巨大的“直通”電流輕則燒毀MOS管重則炸機(jī)。為了避免這種災(zāi)難性的情況我們引入了“互補(bǔ)PWM”的概念?;パa(bǔ)PWM的核心思想很簡單控制同一個橋臂的兩個開關(guān)管的信號必須是反相的。當(dāng)上管導(dǎo)通時下管必須關(guān)斷反之亦然。這樣就能保證電流總是流經(jīng)負(fù)載電機(jī)或電感而不是在電源內(nèi)部短路。但是僅僅反相就夠了嗎還不夠。半導(dǎo)體開關(guān)管如MOSFET、IGBT從導(dǎo)通到關(guān)斷或從關(guān)斷到導(dǎo)通都需要一個短暫的過渡時間。如果上一個管子還沒完全關(guān)斷下一個管子就開始導(dǎo)通了在這段重疊的時間里依然會形成瞬間的直通短路。為了解決這個問題我們必須在兩路互補(bǔ)的PWM信號之間插入一段兩者都為低電平的“死區(qū)時間”Dead Time。在這段時間里上下兩個管子都處于關(guān)斷狀態(tài)為開關(guān)狀態(tài)的切換提供了安全緩沖。所以一個完整的電機(jī)驅(qū)動PWM方案通常需要兩路互補(bǔ)的、帶可調(diào)死區(qū)時間的PWM信號。對于STM8這類微控制器這個任務(wù)通常由其高級控制定時器在STM8中通常是Timer1來承擔(dān)。它內(nèi)置了專門的互補(bǔ)輸出通道和死區(qū)時間發(fā)生器硬件自動生成帶死區(qū)的互補(bǔ)波形極大地減輕了CPU的負(fù)擔(dān)并保證了時序的精確性。接下來我們就以STM8S207系列為例拆解如何配置Timer1來實(shí)現(xiàn)這個功能。2. STM8定時器體系與Timer1的定位STM8的定時器資源根據(jù)型號有所不同常見的有TIM1、TIM2、TIM3、TIM4等。其中TIM1是一個16位的高級控制定時器是唯一一個支持互補(bǔ)PWM輸出和死區(qū)插入的定時器這也是我們本次實(shí)驗(yàn)的核心。其他的定時器如TIM2/TIM3通常用作通用定時器支持基本的PWM輸出但沒有互補(bǔ)和死區(qū)功能。理解Timer1的通道結(jié)構(gòu)是關(guān)鍵。以最常見的三相互補(bǔ)輸出為例Timer1擁有3個互補(bǔ)通道對CH1/CH1N CH2/CH2N CH3/CH3N。這里的CHx是主輸出通道CHxN是其對應(yīng)的互補(bǔ)輸出通道。例如CH1和CH1N就是一對它們的波形是互補(bǔ)的考慮死區(qū)后。此外TIM1還有一個獨(dú)立的CH4通道但它沒有互補(bǔ)輸出端。這些通道的輸出引腳是復(fù)用在GPIO上的具體映射關(guān)系需要查閱對應(yīng)型號的數(shù)據(jù)手冊。例如在STM8S207C8T6上TIM1_CH1 對應(yīng) PC1TIM1_CH1N 對應(yīng) PC2TIM1_CH2 對應(yīng) PC3TIM1_CH2N 對應(yīng) PC4TIM1_CH3 對應(yīng) PC5TIM1_CH3N 對應(yīng) PC6配置的第一步就是將這些需要用到的GPIO引腳初始化為推挽輸出模式并且設(shè)置為高速輸出以提供足夠的驅(qū)動能力和邊沿速度。// 以配置CH1和CH1N為例 void GPIO_Config(void) { // 使能GPIOC時鐘 CLK-PCKENR2 | CLK_PCKENR2_TIM1; // 配置PC1 (TIM1_CH1) 為推挽輸出高速模式 PC_DDR | (1 1); // 輸出模式 PC_CR1 | (1 1); // 推挽輸出 PC_CR2 | (1 1); // 高速輸出 // 配置PC2 (TIM1_CH1N) 為推挽輸出高速模式 PC_DDR | (1 2); PC_CR1 | (1 2); PC_CR2 | (1 2); }注意STM8的GPIO配置寄存器是分端口如PC的每個端口有DDR數(shù)據(jù)方向、ODR輸出數(shù)據(jù)、IDR輸入數(shù)據(jù)、CR1和CR2控制寄存器。CR1和CR2的組合決定了具體模式懸浮輸入、上拉輸入、開漏輸出、推挽輸出以及輸出速度。3. Timer1核心寄存器配置詳解配置Timer1輸出互補(bǔ)PWM主要圍繞幾個核心寄存器展開時基單元、捕獲/比較模式寄存器、剎車與死區(qū)寄存器以及控制寄存器。我們一步步來。3.1 時基單元配置ARR與PSC時基單元決定了PWM波的頻率。它由自動重裝載寄存器ARR和預(yù)分頻器PSC共同控制。PSC (TIM1_PSCRH/L)對系統(tǒng)時鐘fMASTER進(jìn)行分頻得到計(jì)數(shù)器時鐘CK_CNT。公式CK_CNT fMASTER / (PSC 1)。PSC是一個16位寄存器。ARR (TIM1_ARRH/L)決定了計(jì)數(shù)器的周期。計(jì)數(shù)器從0計(jì)數(shù)到ARR然后歸零或向下計(jì)數(shù)形成一個周期。PWM頻率的計(jì)算公式為Fpwm CK_CNT / (ARR 1)。假設(shè)主頻fMASTER16MHz我們想要一個16kHz的PWM頻率可以設(shè)置PSC0不分頻那么CK_CNT16MHz。ARR 16MHz / 16kHz - 1 1000 - 1 999。// 配置PWM頻率為16kHz (假設(shè)主頻16MHz) #define PWM_FREQ 16000 #define F_MASTER 16000000 #define PWM_PERIOD (F_MASTER / PWM_FREQ - 1) // 計(jì)算ARR值 void TIM1_BaseConfig(void) { // 設(shè)置預(yù)分頻器為0 (不分頻) TIM1-PSCRH 0; TIM1-PSCRL 0; // 設(shè)置自動重裝載值決定PWM周期 TIM1-ARRH (uint8_t)((PWM_PERIOD) 8); TIM1-ARRL (uint8_t)(PWM_PERIOD); }3.2 捕獲/比較模式配置CCMR與CCER這部分配置決定了通道的工作模式此處為PWM模式和輸出極性。對于每個通道x1, 2, 3都有一個對應(yīng)的捕獲/比較模式寄存器TIM1_CCMRx和捕獲/比較使能寄存器TIM1_CCER。配置PWM模式 (TIM1_CCMRx)我們需要將通道配置為PWM模式1或模式2。這兩種模式的區(qū)別在于輸出電平與比較結(jié)果的關(guān)系。通常使用PWM模式1當(dāng)計(jì)數(shù)器值小于比較寄存器CCRx值時輸出有效電平由極性決定大于或等于時輸出無效電平。需要設(shè)置OCxM位域?yàn)?10PWM模式1。配置輸出使能與極性 (TIM1_CCER)CCxE位使能主輸出通道CHx。CCxNE位使能互補(bǔ)輸出通道CHxN。CCxP位設(shè)置主輸出通道的極性。0為高電平有效1為低電平有效。CCxNP位設(shè)置互補(bǔ)輸出通道的極性。極性配置需要根據(jù)你驅(qū)動的硬件電路來決定。常見的用法是設(shè)置主輸出高電平有效互補(bǔ)輸出低電平有效或者都設(shè)置為高有效但靠死區(qū)錯開。這里我們設(shè)置主輸出高有效互補(bǔ)輸出低有效。void TIM1_OC_Config(void) { // 以通道1為例 // 1. 配置CCMR1寄存器設(shè)置CH1為PWM模式1 TIM1-CCMR1 (0x6 4); // OC1M 110 (PWM mode 1) // 同時CCMR1中的OC1PE位需要置1開啟預(yù)裝載防止修改CCR時產(chǎn)生毛刺 TIM1-CCMR1 | (1 3); // OC1PE 1 // 2. 配置CCER寄存器使能輸出并設(shè)置極性 // CC1E 1 (使能CH1輸出) // CC1NE 1 (使能CH1N輸出) // CC1P 0 (CH1高電平有效) // CC1NP 1 (CH1N低電平有效) TIM1-CCER1 | (1 0) | (1 2); // 使能CC1E和CC1NE TIM1-CCER1 ~(1 1); // CC1P0 TIM1-CCER1 | (1 3); // CC1NP1 // 3. 設(shè)置比較寄存器CCR1決定占空比 // 占空比 CCR1 / (ARR 1) // 例如設(shè)置50%占空比 uint16_t duty PWM_PERIOD / 2; TIM1-CCR1H (uint8_t)(duty 8); TIM1-CCR1L (uint8_t)(duty); }3.3 死區(qū)時間配置BDTR寄存器這是互補(bǔ)PWM安全性的核心。死區(qū)時間由TIM1_BKR剎車和死區(qū)寄存器中的DTG[7:0]位域控制。STM8的死區(qū)時間計(jì)算公式相對固定取決于DTG位的設(shè)置如果DTG[7:5] 0xx 死區(qū)時間 DTG[6:0] * T_dts。其中T_dts是定時器時鐘周期。如果DTG[7:5] 10x 死區(qū)時間 (64 DTG[5:0]) * T_dts。如果DTG[7:5] 110 死區(qū)時間 (32 DTG[4:0]) * 2 * T_dts。如果DTG[7:5] 111 死區(qū)時間 (32 DTG[4:0]) * 8 * T_dts。T_dts通常是系統(tǒng)時鐘周期如果TIM1_CKD[1:0]00。假設(shè)系統(tǒng)時鐘16MHzT_dts 1/16M 62.5ns。我們需要根據(jù)驅(qū)動MOS管的開關(guān)速度來計(jì)算所需的死區(qū)時間。例如常用的IRF540 MOSFET其導(dǎo)通延遲上升時間約幾十ns關(guān)斷延遲下降時間也類似。為了安全通常設(shè)置死區(qū)時間為200ns到1us。我們以500ns為例進(jìn)行計(jì)算所需死區(qū)周期數(shù) 500ns / 62.5ns 8個時鐘周期。 查看公式DTG[7:5]000時死區(qū)時間 DTG[6:0] * T_dts。所以設(shè)置DTG[6:0] 8即可即DTG 0x08。void TIM1_DeadTime_Config(void) { // 配置死區(qū)時間DTG 0x08對應(yīng)約500ns死區(qū) (16MHz主頻) TIM1-BKR | (0x08 0); // 設(shè)置DTG位域 // 同時必須使能剎車功能即使不用剎車也要置位MOE位來使能輸出 TIM1-BKR | TIM1_BKR_MOE; // 主輸出使能 }重要提示MOE主輸出使能位必須置1否則所有TIM1的輸出通道包括互補(bǔ)通道都會被強(qiáng)制禁止。這在調(diào)試時如果忘了設(shè)置會導(dǎo)致完全沒有波形輸出是一個常見的坑。3.4 控制寄存器與啟動最后我們需要配置計(jì)數(shù)模式并啟動定時器。TIM1_CR1配置計(jì)數(shù)模式。中心對齊模式用于電機(jī)控制減少諧波或邊沿對齊模式。我們使用邊沿對齊模式默認(rèn)向上計(jì)數(shù)。TIM1_CR2輸出空閑狀態(tài)控制等暫時用默認(rèn)值。TIM1_EGR通過置位UG位來產(chǎn)生更新事件將預(yù)裝載寄存器ARR, CCR的值更新到影子寄存器。TIM1_CR1置位CEN位啟動計(jì)數(shù)器。void TIM1_Start(void) { // 產(chǎn)生一個更新事件更新所有預(yù)裝載寄存器 TIM1-EGR | TIM1_EGR_UG; // 開啟自動重裝載預(yù)裝載使能ARPE確保修改ARR時平滑過渡 TIM1-CR1 | TIM1_CR1_ARPE; // 啟動計(jì)數(shù)器 TIM1-CR1 | TIM1_CR1_CEN; }4. 完整代碼整合與實(shí)測波形分析將上述所有配置函數(shù)整合并在main函數(shù)中調(diào)用一個完整的互補(bǔ)PWM輸出程序就完成了。#include stm8s.h #define PWM_FREQ 16000 #define F_MASTER 16000000 #define PWM_PERIOD (F_MASTER / PWM_FREQ - 1) void GPIO_Config(void); void TIM1_BaseConfig(void); void TIM1_OC_Config(void); void TIM1_DeadTime_Config(void); void TIM1_Start(void); void main(void) { // 初始化系統(tǒng)時鐘假設(shè)使用內(nèi)部16MHz HSI CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); // 1分頻16MHz GPIO_Config(); TIM1_BaseConfig(); TIM1_OC_Config(); TIM1_DeadTime_Config(); TIM1_Start(); while (1) { // 主循環(huán)中可以動態(tài)修改CCR1來改變占空比 // TIM1-CCR1H ...; // TIM1-CCR1L ...; } } // ... 上述各個配置函數(shù)的實(shí)現(xiàn) ...將程序編譯下載到STM8S207C8T6核心板用示波器同時測量PC1CH1和PC2CH1N的波形你應(yīng)該能看到類似下圖的波形CH1 (高有效): |ˉˉˉ|___|ˉˉˉ|___|ˉˉˉ|___| --高電平-- --死區(qū)-- --低電平-- CH1N(低有效): |___|ˉˉˉ|___|ˉˉˉ|___|ˉˉˉ| --低電平-- --死區(qū)-- --高電平-- 時間軸 ------------------------------------波形解讀互補(bǔ)關(guān)系CH1為高電平時CH1N為低電平CH1為低電平時CH1N為高電平。兩者相位相反。死區(qū)插入在電平跳變的邊緣有一段兩個信號都為低電平無效電平的區(qū)域。對于高有效的CH1在從高變低后會插入一段低電平死區(qū)然后CH1N才從低變高。反之亦然。這確保了在任何切換瞬間上下管都有一小段共同關(guān)斷的時間。占空比控制通過修改TIM1_CCR1寄存器的值可以改變CH1高電平的時間即占空比CH1N的波形會自動互補(bǔ)調(diào)整。5. 進(jìn)階話題與避坑指南在實(shí)際項(xiàng)目中僅僅輸出波形只是第一步。下面分享幾個從實(shí)際調(diào)試中總結(jié)出來的經(jīng)驗(yàn)和容易踩的坑。5.1 死區(qū)時間計(jì)算與實(shí)測驗(yàn)證理論計(jì)算死區(qū)時間是一回事實(shí)際測量又是另一回事。強(qiáng)烈建議用示波器測量死區(qū)時間是否與設(shè)定值相符。方法是用示波器的兩個通道分別測量CH1和CH1N使用邊沿觸發(fā)和光標(biāo)功能測量從CH1下降沿到CH1N上升沿之間的時間以及從CH1N下降沿到CH1上升沿之間的時間。這兩個時間應(yīng)該基本相等且接近你計(jì)算的值。如果實(shí)測死區(qū)時間偏差很大請檢查系統(tǒng)時鐘頻率你代碼中F_MASTER的定義是否準(zhǔn)確STM8啟動后默認(rèn)是2分頻的HSI8MHz如果你沒有重新配置時鐘那么實(shí)際主頻是8MHz計(jì)算就會出錯。定時器時鐘使能是否通過CLK-PCKENR2寄存器使能了TIM1的時鐘如果沒有使能定時器根本不工作。GPIO速度如果GPIO輸出模式?jīng)]有設(shè)置為高速CR2相應(yīng)位置1輸出邊沿會有延遲這可能會被誤認(rèn)為是死區(qū)時間的一部分或者影響死區(qū)時間的精度。5.2 動態(tài)調(diào)整占空比與同步更新在電機(jī)控制中我們需要實(shí)時調(diào)整PWM占空比。直接寫入CCR1寄存器是立即生效的這可能會在PWM周期中間產(chǎn)生一個“斷裂”的脈沖導(dǎo)致電流畸變。為了解決這個問題我們之前配置中開啟了OC1PE輸出比較預(yù)裝載使能。正確做法是使用預(yù)裝載功能確保TIM1_CCMR1中的OC1PE1。在修改占空比時寫入的是預(yù)裝載寄存器TIM1_CCR1。這個新值會在下一個更新事件UEV發(fā)生時從預(yù)裝載寄存器傳輸?shù)接白蛹拇嫫髡嬲鹱饔玫募拇嫫鲝亩鴮?shí)現(xiàn)所有通道占空比的同步更新。你可以通過軟件產(chǎn)生更新事件TIM1-EGR | TIM1_EGR_UG;但更常見的做法是等待定時器自然溢出產(chǎn)生更新事件。對于多通道同步例如三相電機(jī)這至關(guān)重要。5.3 剎車功能與故障安全高級定時器的“剎車”功能用于在硬件檢測到故障如過流、過壓時立即強(qiáng)制將所有輸出通道置于一個安全狀態(tài)通常是無輸出的狀態(tài)。這是硬件級別的保護(hù)響應(yīng)速度極快。剎車功能通常通過一個特定的引腳BKIN來觸發(fā)。當(dāng)BKIN引腳檢測到有效電平可配置高或低有效剎車電路會動作立即將輸出置為無效狀態(tài)或空閑狀態(tài)由MOE、OSSI等位控制??梢援a(chǎn)生剎車中斷通知CPU處理故障。即使你不用剎車輸入引腳MOE位也必須置1才能使能輸出這是很多新手容易忽略的地方。如果發(fā)現(xiàn)配置完全正確但沒有波形輸出第一個要檢查的就是TIM1_BKR寄存器中的MOE位。5.4 中心對齊模式與移相PWM我們上面的例子是邊沿對齊模式向上計(jì)數(shù)。在電機(jī)控制中為了減小電流諧波和開關(guān)損耗經(jīng)常使用中心對齊模式又稱對稱PWM。在中心對齊模式下計(jì)數(shù)器先向上計(jì)數(shù)到ARR再向下計(jì)數(shù)到0。PWM波形關(guān)于中心對稱。這種模式下PWM頻率的計(jì)算公式變?yōu)镕pwm CK_CNT / (2 * ARR)。配置方法是在TIM1_CR1寄存器中設(shè)置CMS[1:0]位為非00的值例如01為中心對齊模式1并設(shè)置DIR位為0向上計(jì)數(shù)起始。中心對齊模式的互補(bǔ)PWM波形更“干凈”對EMI更友好。關(guān)于網(wǎng)絡(luò)熱詞中提到的“STM32 3路PWM移相”這在STM8的Timer1上也能實(shí)現(xiàn)。移相的本質(zhì)是讓多個通道的PWM脈沖起點(diǎn)相位不同。通過設(shè)置不同通道的捕獲/比較寄存器CCRx的初始值就可以實(shí)現(xiàn)固定的相位差。例如設(shè)置CCR10 CCR2ARR/3 CCR32*ARR/3那么三個通道的PWM波就彼此相差120度非常適合三相無刷電機(jī)的驅(qū)動。5.5 調(diào)試技巧當(dāng)沒有波形輸出時檢查時鐘樹確認(rèn)CLK_CKDIVR時鐘分頻寄存器和CLK_PCKENR2外設(shè)時鐘使能寄存器2的TIM1位是否配置正確。沒有時鐘一切免談。檢查GPIO復(fù)用STM8的引腳功能是復(fù)用的。除了配置GPIO模式還需要確保定時器功能映射到了這個引腳。對于TIM1_CH1它默認(rèn)就是映射到PC1的通常不需要額外的重映射配置部分型號支持重映射需查手冊。檢查MOE位這是最高頻的原因。確認(rèn)TIM1_BKR寄存器的MOE位已經(jīng)置1。檢查輸出使能位確認(rèn)TIM1_CCER1寄存器中的CC1E和CC1NE位已經(jīng)置1。檢查計(jì)數(shù)器是否運(yùn)行讀取TIM1_CR1的CEN位或者直接讀取TIM1_CNTRH/L計(jì)數(shù)器值看它是否在變化。使用調(diào)試器如果有ST-Link和調(diào)試環(huán)境如IAR for STM8可以單步運(yùn)行查看上述關(guān)鍵寄存器的值是最直接的排查手段。配置互補(bǔ)PWM輸出是STM8應(yīng)用于電機(jī)控制類項(xiàng)目的基石。理解每個寄存器位背后的硬件意義而不僅僅是拷貝代碼才能在各種復(fù)雜場景下游刃有余。從示波器上看到第一組干凈、帶死區(qū)的互補(bǔ)波形時那種成就感就是嵌入式開發(fā)的樂趣所在。希望這篇筆記能幫你繞過我當(dāng)年踩過的那些坑。