模拟比较器模块由模拟比较器和支持电路组成,用于功率应用,如峰值电流模式控制、开关模式功率、功率因数校正、电压跳闸监测等。
例程功能:
Comparator1A和Comparator1作为输入引脚,配置ePWM1
当COMP1B的电压>COMP1A的电压时,DCAEVT1和DCAEVT2事件触发
//! In this example:
//! - ePWM1 has DCAEVT1 and DCBEVT1 as one shot trip sources.
//! DCAEVT1 will pull EPWM1A high.
//! DCBEVT1 will pull EPWM1B low.
单周期跳闸源
DCAEVT1拉高EPWM1A
DCAEVT2拉低EPWM1B
//! Initially make the voltage level at COMP1A to be higher than that of
//! COMP1B. Increase voltage on inverting side of comparator(COMP1B pin) to
//! trigger a DCAEVT1, and DCBEVT1. ePWM1 will react to DCAEVT1 and DCBEVT1 as
//! a 1 shot trip. View the EPWM1A/B waveforms on an oscilloscope to see the
//! effect of the events.
设置COMP1A的初始值大于COMP1B,增加COMP1B引脚的值来触发DCAEVT1和DCAEVT2,ePWM1将根据DCAEVT1和DCAEVT2单步跳闸,通过示波器观察ePWM1A/B的波形。
//! \b External \b Connections \n
//! - EPWM1A is on GPIO0
//! - EPWM1B is on GPIO1
//! - COMP1A is on ADCA2
//! - COMP1B is on ADCB2
//! - pull COMP1B to a higher voltage level than COMP1A.
COMP1A接至ADCA2
COMP1B接至ADCB2
主函数配置步骤:
步骤1:
使能系统控制
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2803x_SysCtrl.c file.
//
InitSysCtrl();
步骤2:
配置GPIO,本例中配置ePWM1、ePWM2和TZ引脚
// Step 2. Initialize GPIO:
// This example function is found in the DSP2803x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
// InitGpio(); // Skipped for this example
//
// For this case just init GPIO pins for ePWM1, ePWM2, and TZ pins
//
InitEPwm1Gpio();
具体内容为:
- 禁用GPIO0(EPWM1A)和GPIO1(EPWM1B)引脚的内部上拉
- 配置GPIO0、GPIO1为EPWM1A和EPWM1B
void
InitEPwm1Gpio(void)
{
EALLOW;
//
// Disable internal pull-up for the selected output pins
// for reduced power consumption
// Pull-ups can be enabled or disabled by the user.
// Comment out other unwanted lines.
//
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1; // Disable pull-up on GPIO0 (EPWM1A)
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1; // Disable pull-up on GPIO1 (EPWM1B)
//
// Configure EPWM-1 pins using GPIO regs
// This specifies which of the possible GPIO pins will be
// EPWM1 functional pins.
// Comment out other unwanted lines.
//
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B
EDIS;
}
GPAMUX1
步骤3:
清除所有中断,初始化PIE中断向量表
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
DINT;
//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2803x_PieCtrl.c file.
//
InitPieCtrl();
//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
IER = 0x0000;
IFR = 0x0000;
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in DSP2803x_DefaultIsr.c.
// This function is found in DSP2803x_PieVect.c.
//
InitPieVectTable();
本例中使用的EPWM中断重映射到中断服务函数
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.EPWM1_TZINT = &epwm1_tzint_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
步骤4:
初始化所有的外设,使能ADC时钟:
// Step 4. Initialize all the Device Peripherals:
// Not required for this example
//
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // Enable Clock to the ADC
使能铁芯内的带隙缓冲器电路,比较器和ADC共享同一个内部BG参考,所以即使ADC未用到也要使能ADC,延时以稳定BG参考:
//
// Comparator shares the internal BG reference of the ADC,
// must be powered even if ADC is unused
//
AdcRegs.ADCCTL1.bit.ADCBGPWD = 1;
DELAY_US(1000L); // Delay to allow BG reference to settle.
比较器1时钟使能,DAC使能:
// Enable clock to the Comparator 1 block
//
SysCtrlRegs.PCLKCR3.bit.COMP1ENCLK = 1;
Comp1Regs.COMPCTL.bit.COMPDACEN = 1; // Power up Comparator 1 locally
反向输入连接到外部引脚(COMP1B):
//
// Connect the inverting input to pin COMP1B
//
Comp1Regs.COMPCTL.bit.COMPSOURCE = 1;
另外一种选择为:将反向输入连接到内部DAC,设置DAC的值,取值范围为0-1023:
//
// Uncomment following 2 lines to use DAC instead of pin COMP1B
//
// Connect the inverting input to the internal DAC
//
//Comp1Regs.COMPCTL.bit.COMPSOURCE = 0;
//Comp1Regs.DACVAL.bit.DACVAL = 512; // Set DAC output to midpoint
//
使能ePWM的四个步骤:
- 第一步“使能ePWM模块时钟”在InitSysCtrl()的InitPeripheralClocks()中设置的。
- 第二步:ePWM的时基时钟停止
- 第三步:配置预分频器值和ePWM模式,具体内容为:时基周期寄存器的值设置为6000;设置ePWM的时基相位为0;当前时基计数器的值设置为0;
EALLOW;
EPwm1Regs.TBPRD = 6000; // Set timer period
EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
EPwm1Regs.TBCTR = 0x0000;
设置时基时钟寄存器:
设置时基计数器的模式为上下计数;不从时基相位寄存器(TBPHS)加载时基计数器(TBCTR);时钟分频系数为4*4=16
//
// Setup TBCLK
//
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up/down
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV4; // Clock ratio to SYSCLKOUT
EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV4;
ePWMA和ePWMB均设置为影子模式,并且在计数器为0时重载。
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // Load registers every ZERO
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
设置CMPA的值为3000
//
// Setup compare
//
EPwm1Regs.CMPA.half.CMPA = 3000;
ePWM1A/B的AQ的设置:当计数器增加到3000即=CMPA的值时,ePWM1A,ePWM1B输出高电平
//
// Set actions
//
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on CAU
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on CAD
EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR; // Clear PWM1B on CAU
EPwm1Regs.AQCTLB.bit.CAD = AQ_SET; // Set PWM1B on CAD
定义事件1(基于TZ1和TZ2),
DCAH—>COMP1OUT;DCAL—>TZ2;(这里的TZ2时干嘛的?—好像没用到DCAL)
// DCAH = Comparator 1 output
//
EPwm1Regs.DCTRIPSEL.bit.DCAHCOMPSEL = DC_COMP1OUT;
EPwm1Regs.DCTRIPSEL.bit.DCALCOMPSEL = DC_TZ2; // DCAL = TZ2
数字比较事件1:当DCAH(上一步中设置为了“比较器的输出”)为低时,数字比较事件1发生。
//
// DCAEVT1 = DCAH low (will become active as Comparator output goes low)
//
EPwm1Regs.TZDCSEL.bit.DCAEVT1 = TZ_DCAH_LOW;
DCAEVT1源信号选择为DCAEVT1;信号源为非同步信号:
//
// DCAEVT1 = DCAEVT1 (not filtered)
//
EPwm1Regs.DCACTL.bit.EVT1SRCSEL = DC_EVT1;
EPwm1Regs.DCACTL.bit.EVT1FRCSYNCSEL = DC_EVT_ASYNC; // Take async path
同样的方法设置DCBEVT1:
//
// DCBH = Comparator 1 output
//
EPwm1Regs.DCTRIPSEL.bit.DCBHCOMPSEL = DC_COMP1OUT;
EPwm1Regs.DCTRIPSEL.bit.DCBLCOMPSEL = DC_TZ2; // DCAL = TZ2
//
// DCBEVT1 = (will become active as Comparator output goes low)
//
EPwm1Regs.TZDCSEL.bit.DCBEVT1 = TZ_DCBH_LOW;
//
// DCBEVT1 = DCBEVT1 (not filtered)
//
EPwm1Regs.DCBCTL.bit.EVT1SRCSEL = DC_EVT1;
EPwm1Regs.DCBCTL.bit.EVT1FRCSYNCSEL = DC_EVT_ASYNC; // Take async path
DCAEVT1和DCBEVT1设置为one shot trip
//
// Enable DCAEVT1 and DCBEVT1 are one shot trip sources
// Note: DCxEVT1 events can be defined as one-shot.
// DCxEVT2 events can be defined as cycle-by-cycle.
//
EPwm1Regs.TZSEL.bit.DCAEVT1 = 1;
EPwm1Regs.TZSEL.bit.DCBEVT1 = 1;
DCAEVT1发生时,EPWM1A输出高电平;DCBEVT1发生时,EPWM1B输出低电平。(为什么用TZA和TZB?)
//
// What do we want the DCAEVT1 and DCBEVT1 events to do?
// DCAEVTx events can force EPWMxA
// DCBEVTx events can force EPWMxB
//
EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_HI; // EPWM1A will go high
EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO; // EPWM1B will go low
DCAEVT1/DCBEVT1发生后,进入EPWM1_TZINT one shot中断
//
// Enable TZ interrupt
//
EPwm1Regs.TZEINT.bit.OST = 1;
EDIS;
进中断后计数,并使配置为可以进行下次中断的状态。(可以观察进入中断的次数来看事件发生过多少次)
__interrupt void
epwm1_tzint_isr(void)
{
EPwm1TZIntCount++;
//
// Leave these flags set so we only take this
// interrupt once
//
// EALLOW;
// EPwm1Regs.TZCLR.bit.OST = 1;
// EPwm1Regs.TZCLR.bit.INT = 1;
// EDIS;
//
// Acknowledge this interrupt to receive more interrupts from group 2
//
PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
}
- 第四步:ePWM的时基时钟启用,使其和时基时钟同步。
步骤5:
进中断次数变量置0;使能ePWM1对应的CPU PIE中断
//
// Step 5. User specific code, enable interrupts
// Initialize counters:
//
EPwm1TZIntCount = 0;
//
// Enable CPU INT3 which is connected to EPWM1-3 INT:
//
IER |= M_INT2;
//
// Enable EPWM INTn in the PIE: Group 2 interrupt 1-3
//
PieCtrlRegs.PIEIER2.bit.INTx1 = 1;
//
// Enable global Interrupts and higher priority real-time debug events:
//
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
步骤6:
进入循环
//
// Step 6. IDLE loop. Just sit and loop forever (optional):
//
for(;;)
{
__asm(" NOP");
}
参考文献:
1.MS320F2803x Piccolo Technical Reference Manual
dsp新手,用于记录学习过程,如有错误还请指出,非常感谢!