[资料分享] DSP28335-ePWM

Jacktang   2017-12-22 21:22 楼主
#include "DSP28x_Project.h" // Configure the period for each timer #define EPWM1_TIMER_TBPRD 3750 // Period register 系统始终为150MHZ,下面的程序进行了4分频,即为37.5MHZ,这样得到的是10KHZ #define EPWM1_START_CMPA 1900//设置PWM通道A初始占空比 #define EPWM1_START_CMPB 1900//设置PWM通道B初始占空比 void ChangeDuty(Uint16 Duty)//改变占空比函数 { if(Duty > EPWM1_TIMER_TBPRD) Duty = EPWM1_TIMER_TBPRD; if(Duty < 0) Duty = 0; EPwm1Regs.CMPA.half.CMPA = Duty; // Set compare A value EPwm1Regs.CMPB = Duty; // Set Compare B value } void PWM1_Init()//初始化PWM { /*首先进行的是PWM1引脚的初始化,因为PWM1的引脚为GPIO0和GPIO1,这两个引脚可以是普通的IO口,也可以复用输出PWM,这里选用复用功能*/ EALLOW; GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0; // Enable pull-up on GPIO0 (EPWM1A) GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0; // Enable pull-up on GPIO1 (EPWM1B) GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A复用功能设置,为0代表是普通IO口 GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B EDIS; EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Stop all the TB clocks EDIS; // Setup TBCLK EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD - 1; // 设置周期 EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // 这个代表的是相位,不明白什么东西 EPwm1Regs.TBCTR = 0x0000; // Clear counter // Set Compare values EPwm1Regs.CMPA.half.CMPA = EPWM1_START_CMPA; // Set compare A value EPwm1Regs.CMPB = EPWM1_START_CMPB; // Set Compare B value // Setup counter mode EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; //计数模式 EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2; // 这里是进行2分频 EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2; //这里也是2分频 // Setup shadowing EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; //采用影子寄存器跟新 EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Load on Zero EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // Set actions EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Set PWM1A on event A, up count EPwm1Regs.AQCTLA.bit.CAD = AQ_SET; // Clear PWM1A on event A, down count EPwm1Regs.AQCTLB.bit.CBU = AQ_SET; // Set PWM1B on event B, up count EPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR; // Clear PWM1B on event B, down count EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Start all the timers synced EDIS; } void All_Init() { InitSysCtrl(); DINT; InitPieCtrl(); IER = 0x0000; IFR = 0x0000; InitPieVectTable(); PWM1_Init(); EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM } Uint16 Duty = 1900; void main(void) { All_Init(); while(1) { ChangeDuty(Duty); } }
产生PWM主要需要三个部件, 第一个是周期PRD,通过设定EPwm1Regs.TBPRD的值,来得到周期,我的代码中设定的是3750,系统时钟是150 M hz,经过四分频得到的是37.5Mhz,即1/(37.5M)秒,计数器每个时间间隔加一,加到3750需要的时间是3750 * 1 / (37.5M) = (1 / 10K)秒,即为计数周期,可知频率为10K。
第二个是计数器CTR,计数器根据设定的时钟频率不断累加,我设定计数时钟频率是10K,即每过0.00001s,计数器自动加一。我这里设定的计数模式是增减模式,即计数器加到EPwm1Regs.TBPRD时再自动开始减小,当减到0时,又开始增加。
第三个是比较器COMPA,COMPA是我们自己设定的比较值,当这里设定的初始值1900,当计数器计数到1900的时候会产生事件,比如讲输出引脚置为1或者清为0。
这里采用了影子(映射)寄存器(EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;),映射提供了一个保持寄存器与硬件同步更新的方法,当使用映射模式时,只能在特定的事件处更新当前工作的寄存器,这就防止了由于软件异步修改寄存器内容而引发的错误。 计算器不断的累加,当计数器的值等于比较值时,就输出为1,当计数器的值等于周期值时,就输出为0.从图中也很容易看出方波的周期和占空比。
本帖最后由 Jacktang 于 2017-12-22 21:23 编辑

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复