一般工程的底層代碼搭建好之後,大部分應用程序中用到的PWM功能可以用以下三個函數表示:
* 修改PWM佔空比、周期
typedef struct{
Uint16 TBPRD7;
Uint16 TBPRD8;
Uint16 TBPRD9;
Uint16 TBPRD10;
Uint16 TBPRD11;
Uint16 TBPRD12;
Uint16 CmpA7;
Uint16 CmpA8;
Uint16 CmpA9;
Uint16 CmpA10;
Uint16 CmpA11;
Uint16 CmpA12;}
PwmData;
void PwmManage(PwmData*data){
EPwm7Regs.TBPRD = data->TBPRD7;
EPwm8Regs.TBPRD = data->TBPRD8;
EPwm9Regs.TBPRD = data->TBPRD9;
EPwm10Regs.TBPRD = data->TBPRD10;
EPwm11Regs.TBPRD = data->TBPRD11;
EPwm12Regs.TBPRD = data->TBPRD12;
EPwm7Regs.CMPA.bit.CMPA = data->CmpA7;
EPwm8Regs.CMPA.bit.CMPA = data->CmpA8;
EPwm9Regs.CMPA.bit.CMPA = data->CmpA9;
EPwm10Regs.CMPA.bit.CMPA = data->CmpA10;
EPwm11Regs.CMPA.bit.CMPA = data->CmpA11;
EPwm12Regs.CMPA.bit.CMPA = data->CmpA12;}
* 釋放PWM
void PwmEnable(void){
EALLOW;
EPwm1Regs.TZCLR.bit.OST = 1;
EPwm2Regs.TZCLR.bit.OST = 1;
EPwm3Regs.TZCLR.bit.OST = 1;
EPwm4Regs.TZCLR.bit.OST = 1;
EPwm5Regs.TZCLR.bit.OST = 1;
EPwm6Regs.TZCLR.bit.OST = 1;
EPwm7Regs.TZCLR.bit.OST = 1;
EPwm8Regs.TZCLR.bit.OST = 1;
EPwm9Regs.TZCLR.bit.OST = 1;
EPwm10Regs.TZCLR.bit.OST = 1;
EPwm11Regs.TZCLR.bit.OST = 1;
EPwm12Regs.TZCLR.bit.OST = 1;
EDIS; }
* 閉鎖PWM
void PwmDisable(void){
EALLOW;
EPwm1Regs.TZFRC.bit.OST = 1;
EPwm2Regs.TZFRC.bit.OST = 1;
EPwm3Regs.TZFRC.bit.OST = 1;
EPwm4Regs.TZFRC.bit.OST = 1;
EPwm5Regs.TZFRC.bit.OST = 1;
EPwm6Regs.TZFRC.bit.OST = 1;
EPwm7Regs.TZFRC.bit.OST = 1;
EPwm8Regs.TZFRC.bit.OST = 1;
EPwm9Regs.TZFRC.bit.OST = 1;
EPwm10Regs.TZFRC.bit.OST = 1;
EPwm11Regs.TZFRC.bit.OST = 1;
EPwm12Regs.TZFRC.bit.OST = 1;
EDIS; }
上面代碼中釋放與閉鎖PWM的功能是由軟件TRIP實現的。
以上三個函數基本在兩電平或者三電平逆變器上用的比較多,除此之外PWM還有很多其他功能,接下來筆者慢慢列舉。
PWM啓動ADC
這是一個比較常用的功能,基本上如果使用DSP的片內ADC,大部分都會用PWM觸發ADC,或者外部中斷啓動ADC。
PWM啓動ADC,主要是考慮啓動ADC的週期,常規的做法啓動ADC轉換的週期就是PWM的週期,這種做法適用於PWM週期比較長的情況下,如果PWM週期比較短,可能需要隔好幾個PWM週期,再啓動一次ADC轉換。
//ADC SOC EPwm1Regs.ETSEL.bit.SOCAEN = 1;
// Enable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = 1;
// When TBCTR == 0x0000,EPWMxSOCA pulse will be //generated EPwm1Regs.ETPS.bit.SOCAPRD = 1;
// Generate pulse on 1st event
* PWM觸發中斷
一般DSP系統中的主中斷,都是ADC轉換完成後觸發的主中斷,因爲大部分的應用需求,都是希望DSP進入主中斷後能夠讀取ADCRESULT,所以採用ADC觸發的中斷,一點都不浪費時間。
但有人認爲ADC是個不穩定的東西,他們認爲ADC轉換過程中有機率出現問題,這種情況下,會導致系統無法進入主中斷,而產生一系列問題?所以也有人用PWM的CMPB觸發的中斷作爲主中斷,但CMPB要在ADC轉換完成之後才能觸發中斷,,這是爲了進入主中斷後讀取的ADCRESULT,是當前週期轉換的,而不是上個週期的。
EPwm1Regs.ETSEL.bit.INTSEL = 6; // time-base counter equal to //CMPB when the timer //is incrementin EPwm1Regs.ETPS.bit.INTPRD = 1; // Generate interrupt on 1st event EPwm1Regs.CMPB = 1000;
* PWM的TRIP模塊
TRIP這個詞,不好翻譯,暫時還是用英文吧,筆者也沒有看過特別合適的中文翻譯,PWM的TRIP模塊,主要功能是關係到PWM的釋放與閉鎖,閉鎖一般是使PWM的A、B 引腳輸出低電平。
然後TRIP分爲硬件TRIP、軟件TRIP,這兩者實現的功能是相同的,只是觸發TRIP事件的源頭不同。硬件TRIP事件是怎麼產生的,把DSP的一個GPIO設置爲TRIP引腳,當該引腳的電平被拉低時,立即產生TRIP事件,此時PWM即會被閉鎖。硬件TRIP閉鎖PWM的速度很快,軟件閉鎖,可能至少需要幾十us或者一箇中斷週期才能夠閉鎖PWM。
軟件TRIP就是實現人爲的閉鎖、釋放PWM功能。
EPwm1Regs.TZSEL.bit.OSHT1 = 1; // one-shit
EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; //Force EPWMxA to a low state
EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // Force EPWMxB to a low state
* PWM的脈衝同步性
PWM的同步性,主要是針對各個PWM模塊而說的,比如PWM1與PWM12模塊,希望這兩個PWM模塊的脈衝能夠同步,這裏同步就是指兩者的波形能夠重合,沒有us級的差別。
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master module
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module
* PWM的引腳輸出模式
一個PWM模塊有PWM_A引腳,也有PWM_B引腳,這兩個引腳的輸出模式可以設置爲互補模式,也可以設置爲獨立模式。
//獨立模式
EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; //大於比較值爲0,小於比較值爲1
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.CBD = AQ_SET;
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HI;
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_DISABLE; //互補模式
EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; //大於比較值爲0,小於比較值爲1
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.CBD = AQ_NO_ACTION;
EPwm1Regs.AQCTLB.bit.CBU = AQ_NO_ACTION;
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
* PWM的相位
不同PWM模塊之間的相位,可以同步,也可以相互錯開,這種模式筆者測試過,還沒有正式在項目中使用過,這種模式的設置應該和PWM的相位寄存器設置有關。
* PWM的死區
// Active Low PWMs - Setup Deadband
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; //
EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; //DB_ACTV_HIC
EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL; //EPWMxA In (from the action-qualifier) is the //source for both falling-edge and rising-edge delay EPwm1Regs.DBRED = 400; EPwm1Regs.DBFED = 400; // TBCLK = SYSCLK 5.00 μS