C6748_PWM
来源:互联网 发布:python win32ui 编辑:程序博客网 时间:2024/06/13 01:01
主函数执行流程
此程序的作用是实现eHRPWM(高精度脉冲宽度调制器)输出功能。OMAPL138/TMS320C6748共有两个eHRPWM模块,此处测试模块1的EPWM1_A引脚。主函数执行流程如下:
主函数如下:
intmain(void)
{
//外设使能配置
PSCInit();
// GPIO管脚复用配置
GPIOBankPinMuxSet();
// DSP中断初始化
InterruptInit();
// PWM中断初始化
PWMInterruptInit();
//产生波形
PWM1ABasic(10000,50);
//斩波实验
// ChopperWaveform();
//主循环
for(;;)
{
}
}
外设使能配置
函数首先使能外设,这里是eHRPWM模块1,外设使能配置函数PSCInit如下:
voidPSCInit(void)
{
//使能 EHRPWM模块
//对相应外设模块的使能也可以在 BootLoader中完成
PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_EHRPWM, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE);
}
函数在PSC中使能HW_PSC_EHRPWM(#17)模块,该模块的Power Domain是ALWAYS_ON域(POWER DOMAIN 0),PSCModuleControl细节可参考这里:
C6748_UART_EDMA
GPIO管脚复用配置
将EHRPWM1模块所在的引脚的功能(function)配置为EHRPWM1功能,GPIO管脚复用配置函数GPIOBankPinMuxSet如下:
voidGPIOBankPinMuxSet(void)
{
EHRPWM1PinMuxSetup();
}
EHRPWM1PinMuxSetup函数在demo的Platform工程下的EHRPWM.c文件中,函数如下:
voidEHRPWM1PinMuxSetup(void)
{
// EPWM1A
HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(5))=
(HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(5))& (~(SYSCFG_PINMUX5_PINMUX5_3_0)))|
(PINMUX5_EPWM1A_ENABLE);
// EPWM1B
HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(5))=
(HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(5))& (~(SYSCFG_PINMUX5_PINMUX5_7_4)))|
(PINMUX5_EPWM1B_ENABLE);
// EPWM1TZ[0]
HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(2))=
(HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(2))& (~(SYSCFG_PINMUX2_PINMUX2_3_0)))|
(PINMUX2_EPWM1TZ0_ENABLE);
// EPWMSYNCO
HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(3))=
(HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(3))& (~(SYSCFG_PINMUX3_PINMUX3_15_12)))|
(PINMUX3_EPWMSYNCO_ENABLE);
// EPWMSYNCI
HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(3))=
(HWREG(SOC_SYSCFG_0_REGS+SYSCFG0_PINMUX(3))& (~(SYSCFG_PINMUX3_PINMUX3_11_8)))|
(PINMUX3_EPWMSYNCI_ENABLE);
//使能 PWM时钟
HWREG(SOC_SYSCFG_0_REGS+ SYSCFG0_CFGCHIP1) |= SYSCFG_CFGCHIP1_TBCLKSYNC;
}
函数将EPWM1模块的相关引脚配置为EPWM1A、EPWM1B、EPWM1TZ[0]、EPWMSYNCO、EPWMSYNCI功能引脚,然后设置CFGCHIP1(Chip Configuration 1 Register)寄存器的TBCLKSYNC位,将所有被使能的eHRPWM模块同步到时基时钟(time base clock,TBCLK),使能PWM时钟。
(指南P228)
(指南P222)
(指南P224)
(CFGCHIP1,指南P266)
DSP中断初始化
DSP中断初始化函数InterruptInit如下:
voidInterruptInit(void)
{
//初始化 DSP中断控制器
IntDSPINTCInit();
//使能 DSP全局中断
IntGlobalEnable();
}
函数细节参考这里
C6748_SPI_FLASH
PWM中断初始化
PWM中断初始化函数PWMInterruptInit如下:
voidPWMInterruptInit(void)
{
//注册中断服务函数
IntRegister(C674X_MASK_INT4, PWMEventIsr);
IntRegister(C674X_MASK_INT5, PWMTZIsr);
//映射中断到 DSP可屏蔽中断
IntEventMap(C674X_MASK_INT4, SYS_INT_EHRPWM1);
IntEventMap(C674X_MASK_INT5, SYS_INT_EHRPWM1TZ);
//使能 DSP可屏蔽中断
IntEnable(C674X_MASK_INT4);
IntEnable(C674X_MASK_INT5);
}
函数将CPU可屏蔽中断C674X_MASK_INT4和C674X_MASK_INT5的中断服务函数注册为PWMEventIsr和PWMTZIsr。然后将中断事件SYS_INT_EHRPWM1(#18,PWM1中断)和SYS_INT_EHRPWM1TZ(#23,PWM1错误处理中断)分别映射到CPU中断INT4和INT5,最后使能INT4和INT5。关于IntRegister、IntEventMap、IntEnable等函数可参考这里。
C6748_EDMA_GPIO_中断学习笔记
(手册P93)
6.产生波形
产生波形函数PWM1ABasic (10000,50)如下,其中第一个参数10000表示产生的PWM波的频率为10000Hz(10KHz),第二个参数50表示波形占空比为50%。
voidPWM1ABasic(unsignedint pwm_clk,unsignedshort duty_ratio)
{
//时间基准配置
//时钟配置
EHRPWMTimebaseClkConfig(SOC_EHRPWM_1_REGS, SOC_EHRPWM_1_MODULE_FREQ/CLOCK_DIV_VAL , SOC_EHRPWM_1_MODULE_FREQ);
//配置周期
EHRPWMPWMOpFreqSet(SOC_EHRPWM_1_REGS, SOC_EHRPWM_1_MODULE_FREQ/CLOCK_DIV_VAL,
pwm_clk, EHRPWM_COUNT_UP, EHRPWM_SHADOW_WRITE_DISABLE);
//禁用输入同步信号
EHRPWMTimebaseSyncDisable(SOC_EHRPWM_1_REGS);
//禁用输出同步信号
EHRPWMSyncOutModeSet(SOC_EHRPWM_1_REGS, EHRPWM_SYNCOUT_DISABLE);
//仿真(DEBUG)模式行为配置
EHRPWMTBEmulationModeSet(SOC_EHRPWM_1_REGS, EHRPWM_STOP_AFTER_NEXT_TB_INCREMENT);
//配置计数比较器子模块
//加载比较器 A值
EHRPWMLoadCMPA(SOC_EHRPWM_1_REGS, (SOC_EHRPWM_1_MODULE_FREQ/CLOCK_DIV_VAL/pwm_clk)*duty_ratio/100, EHRPWM_SHADOW_WRITE_DISABLE,
EHRPWM_COMPA_NO_LOAD, EHRPWM_CMPCTL_OVERWR_SH_FL);
//加载比较器 B值
EHRPWMLoadCMPB(SOC_EHRPWM_1_REGS,0, EHRPWM_SHADOW_WRITE_DISABLE,
EHRPWM_COMPB_NO_LOAD, EHRPWM_CMPCTL_OVERWR_SH_FL);
//功能限定配置(输出引脚触发方式设定)
//时间基准计数等于有效计数比较寄存器 A/B值时EPWM1_A翻转,波形由EPWM1_A输出
EHRPWMConfigureAQActionOnA(SOC_EHRPWM_1_REGS, EHRPWM_AQCTLA_ZRO_DONOTHING, EHRPWM_AQCTLA_PRD_DONOTHING,
EHRPWM_AQCTLA_CAU_EPWMXATOGGLE, EHRPWM_AQCTLA_CAD_DONOTHING, EHRPWM_AQCTLA_CBU_EPWMXATOGGLE,
EHRPWM_AQCTLA_CBD_DONOTHING, EHRPWM_AQSFRC_ACTSFA_DONOTHING);
//禁用(旁路,信号直接输出到斩波子模块)死区模块
EHRPWMDBOutput(SOC_EHRPWM_1_REGS, EHRPWM_DBCTL_OUT_MODE_BYPASS);
//禁用斩波子模块
EHRPWMChopperDisable(SOC_EHRPWM_1_REGS);
//禁用错误控制事件
EHRPWMTZTripEventDisable(SOC_EHRPWM_1_REGS, EHRPWM_TZ_ONESHOT);
EHRPWMTZTripEventDisable(SOC_EHRPWM_1_REGS, EHRPWM_TZ_CYCLEBYCYCLE);
//事件触发配置
//每三次事件发生产生中断
EHRPWMETIntPrescale(SOC_EHRPWM_1_REGS, EHRPWM_ETPS_INTPRD_THIRDEVENT);
//时间基准计数等于有效计数比较寄存器 B值产生事件
EHRPWMETIntSourceSelect(SOC_EHRPWM_1_REGS, EHRPWM_ETSEL_INTSEL_TBCTREQUCMPBINC);
//使能中断
EHRPWMETIntEnable(SOC_EHRPWM_1_REGS);
//禁用高精度子模块
EHRPWMHRDisable(SOC_EHRPWM_1_REGS);
}
6.1 时间基准配置/时钟配置
要输出PWM波,首先要配置时间基准,EHRPWMTimebaseClkConfig函数在Drivers工程下的ehrpwm.c文件中,API如下:
voidEHRPWMTimebaseClkConfig(unsignedint baseAddr,
unsignedint tbClk,
unsignedint moduleClk)
{
unsignedint clkDiv= moduleClk/tbClk;
unsignedint hspClkDiv;
unsignedint lspClkDiv, lspClkDivSetting=0;
if(clkDiv> EHRPWM_TBCTL_HSPCLKDIV_14)
{
hspClkDiv= EHRPWM_TBCTL_HSPCLKDIV_DIVBY14;/* reg setting */
lspClkDiv= clkDiv/EHRPWM_TBCTL_HSPCLKDIV_14;/* divider */
/* reg setting */
while(lspClkDiv>1)
{
lspClkDiv= lspClkDiv >>1;
lspClkDivSetting++;
}
}
else
{
hspClkDiv= clkDiv/2;/* reg setting */
/* divide by 1 */
lspClkDivSetting= EHRPWM_TBCTL_HSPCLKDIV_DIVBY1;
}
HWREGH(baseAddr+ EHRPWM_TBCTL) = (HWREGH(baseAddr+ EHRPWM_TBCTL) &
(~EHRPWM_TBCTL_CLKDIV))| ((lspClkDivSetting <<
EHRPWM_TBCTL_CLKDIV_SHIFT)& EHRPWM_TBCTL_CLKDIV);
HWREGH(baseAddr+ EHRPWM_TBCTL) = (HWREGH(baseAddr+ EHRPWM_TBCTL) &
(~EHRPWM_TBCTL_HSPCLKDIV))| ((hspClkDiv <<
EHRPWM_TBCTL_HSPCLKDIV_SHIFT)& EHRPWM_TBCTL_HSPCLKDIV);
}
该函数配置时基模块(Time base module)的时钟分频器(clock divider),baseAddr是PWM模块寄存器组的基地址,tbClk为要产生的时基时钟,moduleClk是输入到PWM模块的时钟(sysclk2)。时基时钟TBCLK(Time-base Clock)计算公式为:TBCLK = SYSCLKOUT/(HSPCLKDIV × CLKDIV)。HSPCLKDIV和CLKDIV是TBCTL寄存器的位,则时钟分频值clkdiv=SYSCLKOUT/TBCLK=HSPCLKDIV x CLKDIV。
函数先计算时钟分频值clkdiv,如果CLKDIV大于HSPCLKDIV所能设置的最大分频值14(HSPCLKDIV=7h)时,则还需要计算TBCTL的CLKDIV部分。否则,HSPCLKDIV分频值就是clkdiv,CLKDIV分频值为1。这里设置tbclk为1MHz,eHRPWM1模块的输入时钟为228MHz(sysclk/2)。
(指南P465)
(指南P131)
6.2 配置周期
配置周期函数EHRPWMPWMOpFreqSet如下:
voidEHRPWMPWMOpFreqSet(unsignedint baseAddr,
unsignedint tbClk,
unsignedint pwmFreq,
unsignedint counterDir,
bool enableShadowWrite)
{
unsignedint tbPeriodCount= tbClk/pwmFreq;
HWREGH(baseAddr+ EHRPWM_TBCTL) = (HWREGH(baseAddr+ EHRPWM_TBCTL) &
(~EHRPWM_PRD_LOAD_SHADOW_MASK))| ((enableShadowWrite <<
EHRPWM_TBCTL_PRDLD_SHIFT)& EHRPWM_PRD_LOAD_SHADOW_MASK);
HWREGH(baseAddr+ EHRPWM_TBCTL) = (HWREGH(baseAddr+ EHRPWM_TBCTL) &
(~EHRPWM_COUNTER_MODE_MASK))| ((counterDir <<
EHRPWM_TBCTL_CTRMODE_SHIFT)& EHRPWM_COUNTER_MODE_MASK);
if(EHRPWM_COUNT_UP_DOWN== counterDir)
{
HWREGH(baseAddr+ EHRPWM_TBPRD) = (unsignedshort)tbPeriodCount/2;
}
else
{
HWREGH(baseAddr+ EHRPWM_TBPRD) = (unsignedshort)tbPeriodCount;
}
}
该函数配置输出的PWM频率/周期。周期计数器决定了最后输出波形的周期。对给定的周期值,在UP 和 DOWN模式下,所装载的周期值就是给定的周期值,在UP_DOWN模式下,所装载的周期值是给定的周期值的一半。pwmFreq是PWM输出波形的频率,如果计数器的方向是up-down,该值必须为输出频率的一半,这样最终输出的信号频率才能等于输出频率。CounterDir是计数器的计数方向(up,down,up-down),enableShadowWrite指明是否使能写往周期寄存器的影子寄存器。
(指南P338)
函数先是计算周期计数值tbPeriodCount,然后设置TBCTL的PRDLD位确定周期寄存器TBPRD的值是否从Shadow寄存器中加载;设置TBCTL的CTRMODE位,确定计数器模式,是向上计数还是向下计数还是上下计数。最后根据计数方向,确定存入周期寄存器TBPRD的值tbPeriodCount是否要减半(这里设置up和down计数模式的tbPeriodCount好像少减了1?)。这里程序设置TBCTL[CTRMODE]位为0h,即time-base计数器计数模式为Up-count mode。设置TBCTL[PRDLD]位为1,即直接加载TBPRD而不使用影子寄存器。设置TBPRD为100(1MHz/10KHz=tbclkFREQ/pwmclkFREQ),即PWM波频率为10KHz。
(指南P388)
6.3 禁用输入同步信号
EHRPWMTimebaseSyncDisable函数设置TBCTL的PHSEN位(counter Register Load From Phase Register Enable)为0,禁用EHRPWM1的输入同步信号,即使EPWM1SYNCI引脚有同步信号输入,EPWM1也不会把相位寄存器TBPHS(TB phase register)的值装入到计数器TBCNT(time-base counter)中。
(指南P389)
(指南P390)
(指南P466)
该API如下:
voidEHRPWMTimebaseSyncDisable(unsignedint baseAddr)
{
HWREGH(baseAddr+ EHRPWM_TBCTL) &= (~EHRPWM_SYNC_ENABLE);
}
6.4 禁用输出同步信号
EHRPWMSyncOutModeSet函数设置TBCTL的SYNCOSEL位为3h,禁用EPWM1的输出同步信号EPWM1SYNCO,输出同步信号产生的条件可以是EPWM1SYNCIN、CTR=0、CTR=CMPB三个。
(指南P386)
(指南P387)
(指南P465)
该API如下:
voidEHRPWMSyncOutModeSet(unsignedint baseAddr, unsignedint syncOutMode)
{
HWREGH(baseAddr+ EHRPWM_TBCTL) = (HWREGH(baseAddr+ EHRPWM_TBCTL) &
(~EHRPWM_SYNCOUT_MASK))| syncOutMode;
}
6.5 仿真模式行为配置
EHRPWMTBEmulationModeSet函数设置TBCTL的FREE、SOFT位,配置EPWM的仿真模式行为(即在调试时timebase的行为),这里将FREE、SOFT位设为0,则在仿真事件(emulation event)发生后,ePWM的时基计数器(time-base counter)将在下一次增量(increment)或减量(decrement)发生后停止。
(指南P465)
该API如下:
voidEHRPWMTBEmulationModeSet(unsignedint baseAddr, unsignedint mode)
{
HWREGH(baseAddr+ EHRPWM_TBCTL) = (HWREGH(baseAddr+ EHRPWM_TBCTL) &
(~EHRPWM_TBCTL_FREE_SOFT))| (mode & EHRPWM_TBCTL_FREE_SOFT);
}
6.6 配置计数比较器子模块
6.6.1 加载比较器A值
计数器比较子模块(counter-compare submodule)接收时基计数器(time-base counter)的值作为输入,这个值不断地同比较计数器(counter-compare)A和比较计数器B寄存器相比较。当时基计数器的值等于其中一个比较寄存器时,这个计数器比较单元就会产生相应的事件,将事件信号输出到AQ模块中(Action Qualifier)。
(指南P394)
加载比较器A值函数EHRPWMLoadCMPA如下:
boolEHRPWMLoadCMPA(unsignedint baseAddr,
unsignedint CMPAVal,
bool enableShadowWrite,
unsignedint ShadowToActiveLoadTrigger,
bool OverwriteShadowFull)
{
bool status=FALSE;
if((OverwriteShadowFull)||
((HWREGH(baseAddr+EHRPWM_CMPCTL)& EHRPWM_CMPCTL_SHDWAFULL)==
EHRPWM_SHADOW_A_EMPTY))
{
HWREGH(baseAddr+ EHRPWM_CMPCTL) = (HWREGH(baseAddr+ EHRPWM_CMPCTL) &
(~EHRPWM_CMPCTL_SHDWAMODE))| ((enableShadowWrite <<
EHRPWM_CMPCTL_SHDWAMODE_SHIFT)& EHRPWM_CMPCTL_SHDWAMODE);
HWREGH(baseAddr+ EHRPWM_CMPCTL) = (HWREGH(baseAddr+ EHRPWM_CMPCTL) &
(~EHRPWM_COMPA_LOAD_MASK))|((ShadowToActiveLoadTrigger<<
EHRPWM_CMPCTL_LOADAMODE_SHIFT)& EHRPWM_COMPA_LOAD_MASK);
HWREGH(baseAddr+ EHRPWM_CMPA) = CMPAVal & EHRPWM_CMPA_CMPA;
status=TRUE;
}
return status;
}
函数先判断OverwriteShadowFull标志是否为1(真),如果为真,则不管Counter-compare A(CMPA)影子寄存器(shadow register)是否为满(SHDWAFULL=1),都往里overwrite,又或者CMPA影子寄存器为空(SHDWAFULL),也往CMPA Shadow register所在地址写数据。
(指南P469)
CMPA shadow register与CMPA active register共享同一地址,往该地址写数据时,到底往哪一个寄存器写是通过CMPCTL寄存器的SHDWAMODE位(CMPA寄存器操作模式)来决定的。这里程序把该位设为了1,即选择immediate模式,往该地址写数据直接往active register写。然后程序又设置CMPCTL的LOADAMODE位(active counter-compare A load from shadow select mode)为3h,则freeze加载行为,CMPA的active register将不从shadow register加载。
(指南P469)
最后将要写往CMPA active register的值CMPAVal写入到CMPA active register中。这里
(指南P470)
6.6.2 加载比较器B值
加载比较器B值函数EHRPWMLoadCMPB如下:
boolEHRPWMLoadCMPB(unsignedint baseAddr,
unsignedint CMPBVal,
bool enableShadowWrite,
unsignedint ShadowToActiveLoadTrigger,
bool OverwriteShadowFull)
{
bool status=FALSE;
if((OverwriteShadowFull)||
((HWREGH(baseAddr+EHRPWM_CMPCTL)& EHRPWM_CMPCTL_SHDWBFULL)==
EHRPWM_SHADOW_B_EMPTY))
{
HWREGH(baseAddr+ EHRPWM_CMPCTL) = (HWREGH(baseAddr+ EHRPWM_CMPCTL)
& (~EHRPWM_CMPCTL_SHDWBMODE))| ((enableShadowWrite <<
EHRPWM_CMPCTL_SHDWBMODE_SHIFT)& EHRPWM_CMPCTL_SHDWBMODE);
HWREGH(baseAddr+ EHRPWM_CMPCTL) = (HWREGH(baseAddr+ EHRPWM_CMPCTL) &
(~EHRPWM_COMPB_LOAD_MASK))| ((ShadowToActiveLoadTrigger<<
EHRPWM_CMPCTL_LOADBMODE_SHIFT)& EHRPWM_COMPB_LOAD_MASK);
HWREGH(baseAddr+ EHRPWM_CMPB) = CMPBVal & EHRPWM_CMPB_CMPB;
status=TRUE;
}
return status;
}
函数与加载比较器A值函数基本一致,不同的只是判断的条件变成了CMPB shadow register是否满。设置的位变成了CMPCTL的SHDWBMODE和LOADBMODE位,比较器数据写往了CMPB。这里不再细述。
6.7 功能限定配置(输出引脚触发方式设定)
函数EHRPWMConfigureAQActionOnA设定输出引脚触发方式,这里设置时间基准计数等于有效计数比较寄存器A/B值时EPWM1_A翻转,波形由EPWM1_A输出。该API如下:
voidEHRPWMConfigureAQActionOnA(unsignedint baseAddr,
unsignedint zero,
unsignedint period,
unsignedint CAUp,
unsignedint CADown,
unsignedint CBUp,
unsignedint CBDown,
unsignedint SWForced)
{
HWREGH(baseAddr+ EHRPWM_AQCTLA) =
((CBDown<< EHRPWM_AQCTLA_CBD_SHIFT)& EHRPWM_AQCTLA_CBD) |
((CBUp<< EHRPWM_AQCTLA_CBU_SHIFT)& EHRPWM_AQCTLA_CBU) |
((CADown<< EHRPWM_AQCTLA_CAD_SHIFT)& EHRPWM_AQCTLA_CAD) |
((CAUp<< EHRPWM_AQCTLA_CAU_SHIFT)& EHRPWM_AQCTLA_CAU) |
((period<< EHRPWM_AQCTLA_PRD_SHIFT)& EHRPWM_AQCTLA_PRD) |
((zero<< EHRPWM_AQCTLA_ZRO_SHIFT)& EHRPWM_AQCTLA_ZRO);
HWREGH(baseAddr+ EHRPWM_AQSFRC) = (HWREGH(baseAddr+ EHRPWM_AQSFRC) &
(~EHRPWM_AQSFRC_ACTSFA))| ((SWForced <<
EHRPWM_AQSFRC_ACTSFA_SHIFT)& EHRPWM_AQSFRC_ACTSFA);
}
该函数设置AQCTLA寄存器的CBD、CBU、CAD、CAU、PRD、ZRO位,配置EPWM模块的A通道在相应事件发生时的动作。然后设置AQSFRC寄存器的ACTSFA位,配置EPWM1_A在One-time Force A被invoke时的动作(action)。
(指南P472)
(指南P474)
这里程序设置在TBCNT向上计数等于CMPA和CMPB时EPWM1_A输出翻转,其它时候不动作。
6.8 禁用死区模块
EHRPWMDBOutput函数选择死区模块的输出模式,这里禁用死区模块,由AQ模块(action qualifier)输出的信号在通过死区模块(dead band)时,被旁路,不做任何处理,信号被直接输出到斩波(PC,PWM chopper)子模块,注意图中DB的虚线,虚线表示旁路处理。
(指南P417)
通过设置DBCTL[OUT_MODE]位可以控制信号是否旁路,如图:
(指南P418)
该API如下:
voidEHRPWMDBOutput(unsignedint baseAddr, unsignedint DBgenOpMode)
{
HWREGH(baseAddr+ EHRPWM_DBCTL) =
(HWREGH(baseAddr+ EHRPWM_DBCTL) & (~EHRPWM_DBCTL_OUT_MODE))|
((DBgenOpMode<< EHRPWM_DBCTL_OUT_MODE_SHIFT)& EHRPWM_DBCTL_OUT_MODE);
}
函数通过设置DBCTL[OUT_MODE]位可以设置4种不同的输出模式,分别确定A通道和B通道信号是否要旁路。
(指南P476)
6.9 禁用斩波子模块
EHRPWMChopperDisable函数设置PCCTL的CHPEN位为0,禁用PWM斩波子模块的PWM斩波功能,信号经过斩波子模块时,直接被bypass,不作任何处理。该API如下:
voidEHRPWMChopperDisable(unsignedint baseAddr)
{
HWREGH(baseAddr+ EHRPWM_PCCTL) &= (~EHRPWM_PCCTL_CHPEN);
}
(指南P422)
(指南P478)
6.10 禁用错误控制事件
EHRPWMTZTripEventDisable函数禁用错误控制事件(trip event),当TZ引脚输入了错误信号时,错误处理模块(Trip Zone)将不会作任何处理。这里,程序设置TZSEL[OSHT1]位和TZSEL[CBC1]位为0,禁用了EPWM1模块的Trip Zone子模块产生CBC事件(Cycle-by-Cycle)和OSHT事件(One-Shot)。该API如下:
voidEHRPWMTZTripEventDisable(unsignedint baseAddr, bool osht_CBC)
{
if(EHRPWM_TZ_ONESHOT== osht_CBC)
{
HWREGH(baseAddr+ EHRPWM_TZSEL) &= (~EHRPWM_TZSEL_OSHT1);
}
if(EHRPWM_TZ_CYCLEBYCYCLE== osht_CBC)
{
HWREGH(baseAddr+ EHRPWM_TZSEL) &= (~EHRPWM_TZSEL_CBC1);
}
}
(指南P428)
(指南P479)
6.11 事件触发配置
6.11.1 每三次事件发生产生中断
EHRPWMETIntPrescale函数设置事件触发(event trigger,ET)子模块的ETPS寄存器(event prescale),设置ETPS[INTPRD]位对要产生中断的事件进行预分频处理(即发生多少次事件才产生一次中断),这里程序设置为3次,即每3次事件发生,产生1次中断。ET子模块接收由时基子模块(time-base)和计数器比较子模块(counter-compare)所产生的事件信号输入,并产生中断信号给CPU。要产生中断的事件由ETSEL[INTSEL]位选择。EHRPWMETIntPrescale函数如下:
voidEHRPWMETIntPrescale(unsignedint baseAddr, unsignedint prescale)
{
HWREGH(baseAddr+ EHRPWM_ETPS) =
(HWREGH(baseAddr+ EHRPWM_ETPS) & (~EHRPWM_ETPS_INTPRD))|
((prescale<< EHRPWM_ETPS_INTPRD_SHIFT)& EHRPWM_ETPS_INTPRD);
}
(指南P484)
6.11.2 时间基准等于有效计数比较寄存器B值产生事件
EHRPWMETIntSourceSelect函数设置产生EPWM中断的源(source),函数设置ETSEL[INTSEL]位,确定什么事件发生时,ETPS[INTCNT]会加1。这里程序设置源为CTRU=CMPB,即TBCTR向上计数到等于CMPB时产生一次事件。该API如下:
voidEHRPWMETIntSourceSelect(unsignedint baseAddr, unsignedint selectInt)
{
HWREGH(baseAddr+ EHRPWM_ETSEL) =
(HWREGH(baseAddr+ EHRPWM_ETSEL) & (~EHRPWM_ETSEL_INTSEL))|
((selectInt<< EHRPWM_ETSEL_INTSEL_SHIFT)& EHRPWM_ETSEL_INTSEL);
}
(指南P432)
(指南P483)
6.12 使能中断
EHRPWMETIntEnable函数设置ETSEL[INTEN]位为1,使能EPWMx_INT中断信号的产生。该API如下:
voidEHRPWMETIntEnable(unsignedint baseAddr)
{
HWREGH(baseAddr+ EHRPWM_ETSEL) |= EHRPWM_ETSEL_INTEN;
}
6.13 禁用高精度子模块
EHRPWMHRDisable函数设置HRCNFG寄存器(HRPWM configuration register)的EDGEMODE位,禁用HRPWM功能。该API如下:
voidEHRPWMHRDisable(unsignedint baseAddr)
{
HWREGH(baseAddr+ EHRPWM_HRCNFG) &= (~EHRPWM_HR_EDGEMODE);
}
(指南P488)
7.斩波(可选)
斩波函数如下:
voidChopperWaveform(void)
{
// 50%占空比
EHRPWMConfigureChopperDuty(SOC_EHRPWM_1_REGS, EHRPWM_CHP_DUTY_50_PER);
// 4分频
EHRPWMConfigureChopperFreq(SOC_EHRPWM_1_REGS, EHRPWM_PCCTL_CHPFREQ_DIVBY4);
//单个脉冲宽度
EHRPWMConfigureChopperOSPW(SOC_EHRPWM_1_REGS,0xF);
//使能斩波子模块
EHRPWMChopperEnable(SOC_EHRPWM_1_REGS);
}
7.1 设置斩波占空比
EHRPWMConfigureChopperDuty函数设置PCCTL[CHPDUTY]位,设置斩波PSCLK的占空比,这里设为3h,即50%,该API如下:
voidEHRPWMConfigureChopperDuty(unsignedint baseAddr, unsignedint dutyCycle)
{
HWREGH(baseAddr+ EHRPWM_PCCTL) =
(HWREGH(baseAddr+ EHRPWM_PCCTL) & (~EHRPWM_PCCTL_CHPDUTY))|
((dutyCycle<< EHRPWM_PCCTL_CHPDUTY_SHIFT)& EHRPWM_PCCTL_CHPDUTY);
}
(指南P424)
7.2 设置斩波频率
EHRPWMConfigureChopperFreq函数设置PCCTL[CHPFREQ],通过设置分频细述,设置斩波频率,斩波频率是从SYSCLKOUT(即CPU时钟频率)分频得来的。该API如下:
voidEHRPWMConfigureChopperFreq(unsignedint baseAddr, unsignedint freqDiv)
{
if(freqDiv> EHRPWM_PCCTL_CHPFREQ_DIVBY8)
{
freqDiv= EHRPWM_PCCTL_CHPFREQ_DIVBY8;
}
HWREGH(baseAddr+ EHRPWM_PCCTL) =
(HWREGH(baseAddr+ EHRPWM_PCCTL) & (~EHRPWM_PCCTL_CHPFREQ))|
((freqDiv<< EHRPWM_PCCTL_CHPFREQ_SHIFT)& EHRPWM_PCCTL_CHPFREQ);
}
(指南P422)
(指南P478)
7.3 设置单个脉冲宽度
EHRPWMConfigureChopperOSPW函数设置PCCTL[OSHTWTH]位,设置one-shot pulse width,这里设为0x0F,即one-shot脉冲宽度为16 x SYSCLKOUT/8。
(指南P423)
(指南P478)
7.4 使能斩波子模块
EHRPWMChopperEnable函数设置PCCTL[CHPEN]位为1,使能斩波子模块,该API如下:
voidEHRPWMChopperEnable(unsignedint baseAddr)
{
HWREGH(baseAddr+ EHRPWM_PCCTL) |= EHRPWM_PCCTL_CHPEN;
}
(指南P478)
8.中断服务函数
8.1 PWM事件中断服务函数
PWM事件中断服务函数PWMEventIsr如下:
voidPWMEventIsr(void)
{
IntEventClear(SYS_INT_EHRPWM1);
EHRPWMETIntClear(SOC_EHRPWM_1_REGS);
}
函数先是清除EVTFLAGn被置位的中断标志(SYS_INT_EHRPWM1位),IntEventClear函数在\demo\StarterWare\Source\StarterWare\SystemConfig 路径system_config工程下的interrupt.c文件中,函数如下:
voidIntEventClear(unsignedint sysINT)
{
unsignedint dspintcREG;
/* Check the system event number */
ASSERT((sysINT<=127));
/* Get the address of the correct event register */
dspintcREG= SOC_INTC_0_REGS +DSPINTC_EVTCLR((sysINT>>5));
/* Clear the corresponding bit within the event clear register */
HWREG(dspintcREG)=DSPINTC_EVTCLR_EC(sysINT);
}
细节可参考这篇博文。
C6748_EDMA_GPIO_中断学习笔记
然后EHRPWMETIntClear函数往ETCLR寄存器的INT位写1,清除ETFLG[INT]位,清除ePWM中断标志。该API如下:
voidEHRPWMETIntClear(unsignedint baseAddr)
{
HWREGH(baseAddr+ EHRPWM_ETCLR) |= EHRPWM_ETCLR_INT;
}
(指南P485)
(指南P485)
8.2 PWM错误事件中断服务函数
PWM错误事件中断服务函数PWMTZIsr如下:
voidPWMTZIsr(void)
{
IntEventClear(SYS_INT_EHRPWM1TZ);
EHRPWMTZFlagClear(SOC_EHRPWM_1_REGS, EHRPWM_TZ_CYCLEBYCYCLE_CLEAR);
}
首先在EVTFLAGn寄存器中清除SYS_INT_EHRPWM1TZ(#23)对应的中断标志位,然后EHRPWMTZFlagClear函数设置TZCLR的相应位,清除相应错误标志,这里设置TZCLR[CBC]和TZCLR[INT]位,清除CBC trip latch标志和ePWM模块trip-interrupt中断标志TZFLG[INT]。EHRPWMTZFlagClear函数如下:
voidEHRPWMTZFlagClear(unsignedint baseAddr, unsignedint flagToClear)
{
HWREGH(baseAddr+ EHRPWM_TZCLR) = flagToClear &
(EHRPWM_TZCLR_OST| EHRPWM_TZCLR_CBC | EHRPWM_TZCLR_INT);
}6748_PWMT]weTZ,Q/pwmclkFREQ
(指南P482)
(指南P428)
9.参考文献
[1] TMS320F28027 之PWM 模块
[2] PWM死区(Dead Zone)的作用和意义
- C6748_PWM
- could not find java se runtime environment
- 实验吧-逆向-该题不简单
- 基于51单片机的计算器写代码遇到的问题及解决办法
- maven常用的中央仓库
- 训练日记
- C6748_PWM
- 测试文章
- Ajax框架之DWR学习(异常处理案例、Bean传递参数、多个Service)-yellowcong
- MVC、MVP、MVVM
- [RTSP]WPF用VLC显示RTSP视频
- Linux进程虚拟内存简介
- 写篇博客
- 安卓中为了获取context的方法和区别(getContext,getActivity,this,mainActivity.this等)
- C++中的委托构造