TMS320C6748_PWM

目录

1.主函数执行流程

2.外设使能配置

3.GPIO管脚复用配置

4.DSP中断初始化

5.PWM中断初始化

6.产生波形

6.1 时间基准配置/时钟配置

6.2 配置周期

6.3 禁用输入同步信号

6.4 禁用输出同步信号

6.5 仿真模式行为配置

6.6 配置计数比较器子模块

6.6.1 加载比较器A值

6.6.2 加载比较器B值

6.7 功能限定配置(输出引脚触发方式设定)

6.8 禁用死区模块

6.9 禁用斩波子模块

6.10 禁用错误控制事件

6.11 事件触发配置

6.11.1 每三次事件发生产生中断

6.11.2 时间基准等于有效计数比较寄存器B值产生事件

6.12 使能中断

6.13 禁用高精度子模块

7.斩波(可选)

7.1 设置斩波占空比

7.2 设置斩波频率

7.3 设置单个脉冲宽度

7.4 使能斩波子模块

8.中断服务函数

8.1 PWM事件中断服务函数

8.2 PWM错误事件中断服务函数

9.参考文献


1.主函数执行流程

此程序的作用是实现eHRPWM(高精度脉冲宽度调制器)输出功能。OMAPL138/TMS320C6748共有两个eHRPWM模块,此处测试模块1的EPWM1_A引脚。主函数执行流程如下:

主函数如下:

int main(void)
{
  // 外设使能配置
  PSCInit();
    
  // GPIO 管脚复用配置
  GPIOBankPinMuxSet();

  // DSP 中断初始化
  InterruptInit();

  // PWM 中断初始化
  PWMInterruptInit();

  // 产生波形
  PWM1ABasic(10000,50);

  // 斩波实验
  //  ChopperWaveform();

  // 主循环
  for(;;)
  {

  }
}

2.外设使能配置

函数首先使能外设,这里是eHRPWM模块1,外设使能配置函数PSCInit如下:

void PSCInit(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

3.GPIO管脚复用配置

将EHRPWM1模块所在的引脚的功能(function)配置为EHRPWM1功能,GPIO管脚复用配置函数GPIOBankPinMuxSet如下:

void GPIOBankPinMuxSet(void)
{
  EHRPWM1PinMuxSetup();
}

EHRPWM1PinMuxSetup函数在demo的Platform工程下的EHRPWM.c文件中,函数如下:

void EHRPWM1PinMuxSetup(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)

4.DSP中断初始化

DSP中断初始化函数InterruptInit如下:

void InterruptInit(void)
{
  // 初始化 DSP 中断控制器
  IntDSPINTCInit();

  // 使能 DSP 全局中断
  IntGlobalEnable();
}

函数细节参考这里

C6748_SPI_FLASH

5.PWM中断初始化

PWM中断初始化函数PWMInterruptInit如下:

void PWMInterruptInit(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%。

void PWM1ABasic(unsigned int pwm_clk,unsigned short 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如下:

void EHRPWMTimebaseClkConfig(unsigned int baseAddr,
                             unsigned int tbClk,
                             unsigned int moduleClk)

{
  unsigned int clkDiv = moduleClk/tbClk;
  unsigned int hspClkDiv;
  unsigned int 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如下:

void EHRPWMPWMOpFreqSet(unsigned int baseAddr,
                        unsigned int tbClk,
                        unsigned int pwmFreq,
                        unsigned int counterDir,
                        bool enableShadowWrite)
{
  unsigned int 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) = (unsigned short)tbPeriodCount/2;
  }
  else
  {
    HWREGH(baseAddr + EHRPWM_TBPRD) = (unsigned short)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如下:

void EHRPWMTimebaseSyncDisable(unsigned int 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如下:

void EHRPWMSyncOutModeSet(unsigned int baseAddr, unsigned int 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如下:

void EHRPWMTBEmulationModeSet(unsigned int baseAddr, unsigned int 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如下:

bool EHRPWMLoadCMPA(unsigned int baseAddr,
                    unsigned int CMPAVal,
                    bool enableShadowWrite,
                    unsigned int 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如下:

bool EHRPWMLoadCMPB(unsigned int baseAddr,
                    unsigned int CMPBVal,
                    bool enableShadowWrite,
                    unsigned int 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如下:

void EHRPWMConfigureAQActionOnA(unsigned int baseAddr,
                                unsigned int zero,
                                unsigned int period,
                                unsigned int CAUp,
                                unsigned int CADown,
                                unsigned int CBUp,
                                unsigned int CBDown,
                                unsigned int 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如下:

void EHRPWMDBOutput(unsigned int baseAddr, unsigned int 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如下:

void EHRPWMChopperDisable(unsigned int 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如下:

void EHRPWMTZTripEventDisable(unsigned int 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函数如下:

void EHRPWMETIntPrescale(unsigned int baseAddr, unsigned int 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如下:

void EHRPWMETIntSourceSelect(unsigned int baseAddr, unsigned int 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如下:

void EHRPWMETIntEnable(unsigned int baseAddr)
{
  HWREGH(baseAddr + EHRPWM_ETSEL) |= EHRPWM_ETSEL_INTEN;
}

6.13 禁用高精度子模块

EHRPWMHRDisable函数设置HRCNFG寄存器(HRPWM configuration register)的EDGEMODE位,禁用HRPWM功能。该API如下:

void EHRPWMHRDisable(unsigned int baseAddr)
{
  HWREGH(baseAddr + EHRPWM_HRCNFG) &= (~EHRPWM_HR_EDGEMODE);
}

                                                                            (指南P488)

7.斩波(可选)

    斩波函数如下:

void ChopperWaveform(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如下:

void EHRPWMConfigureChopperDuty(unsigned int baseAddr, unsigned int 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如下:

void EHRPWMConfigureChopperFreq(unsigned int baseAddr, unsigned int 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如下:

void EHRPWMChopperEnable(unsigned int baseAddr)
{
  HWREGH(baseAddr + EHRPWM_PCCTL) |= EHRPWM_PCCTL_CHPEN;
}

                                                                                  (指南P478)

8.中断服务函数

8.1 PWM事件中断服务函数

    PWM事件中断服务函数PWMEventIsr如下:

void PWMEventIsr(void)
{
  IntEventClear(SYS_INT_EHRPWM1);

  EHRPWMETIntClear(SOC_EHRPWM_1_REGS);
}

函数先是清除EVTFLAGn被置位的中断标志(SYS_INT_EHRPWM1位),IntEventClear函数在\demo\StarterWare\Source\StarterWare\SystemConfig 路径system_config工程下的interrupt.c文件中,函数如下:

void IntEventClear(unsigned int sysINT)
{
  unsigned int 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如下:

void EHRPWMETIntClear(unsigned int baseAddr)
{
    HWREGH(baseAddr + EHRPWM_ETCLR) |= EHRPWM_ETCLR_INT;
}

 (指南P485)

指南P485)

8.2 PWM错误事件中断服务函数

    PWM错误事件中断服务函数PWMTZIsr如下:

void PWMTZIsr(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函数如下:

void EHRPWMTZFlagClear(unsigned int baseAddr, unsigned int flagToClear)
{
  HWREGH(baseAddr + EHRPWM_TZCLR) = flagToClear &
      (EHRPWM_TZCLR_OST | EHRPWM_TZCLR_CBC | EHRPWM_TZCLR_INT);
}

(指南P482)

(指南P428)

9.参考文献

[1] TMS320F28027 之PWM 模块

[2]  PWM死区(Dead Zone)的作用和意义

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4 JTAG KeystoneⅠ上的JTAG接口用于和测试仿真系统通信,尽管JTAG对于系统运行不是必须的,但是强烈推荐所有设计上都使用JTAG接口。 4.1 JTAG/Emulation JTAG/Emulation相关的文档: Emulation and Trace Headers Technical Reference Manual (SPRU655) (but note differences defined below) Boundary Scan Test Specification (IEEE-1149.1) AC Coupled Net Test Specification (IEEE-1149.6) Clocking Design Guide for KeyStone Devices Application Report (SPRABI4) 4.1.1 JTAG/Emulation的配置 IEEE1149.1-1990标准,IEEE标准测试访问端口和边界扫描结构(JTAG)接口可以用于边界扫描和仿真。 边界扫描的实现和IEEE-1149.1以及IEEE1149.6(用于SerDes端口)。不管器件是什么样的配置,边界扫描都可以使用。 作为仿真接口,JTAG端口可以用于多种模式: 标准仿真模式:只需要5个标准JTAG信号【TCK,TDI,TD0,TMS,TRST】 HS-RTDX仿真模式:需要5个标准JTAG信号,加上EMU0 和/或 EMU1。在这种模式下,EMU0 和/或 EMU1在这种模式下是双向的。 Trace port:trace port支持实时复制特定的内部数据。Trace port使用EMU[18:00]引脚来输出trace数据,但是,使用的引脚数是可以配置的。 不管器件是什么样的配置,仿真功能都可以使用。 任何未使用的仿真信号可以悬空。 4.1.2 JTAG/Emulation 的系统实现 对于大多数的系统层次的实现细节,查看Emulation and Trace Headers Technical Reference Manual (SPRU655),不过KeystoneⅠ器件的实现和该文档中说明的有所不同。 尽管上述文档暗示了3.3V的信号,不过只要TVD源是1.8V的,1.8V的信号也是支持的。 【TVD全称Target Voltage Detect,对应于14针的JTAG的第5个引脚,较新的仿真器硬件可以调整电压以匹配目标器件的电压。所以对于6678,这个引脚接1.8V,给较新的仿真器来检测。】 对于未使用trace特性的单个器件的连接,可以使用标准14引脚的连接器以及非缓冲的连接【评估板上没有使用缓冲,但是没有14引脚连接器】。如果使用了trace特性(需要60引脚的仿真器连接),5个标准JTAG信号需要被缓冲并且TCLK和RTCLK需要被分别缓冲。建议在TCLK上接上并联交流终端匹配。EMU0和EMU1不能被缓冲,因为在HS-RTDX模式下,它们是双向信号。 对于有多个DSP而没有使用trace分析特性的系统,JTAG信号需要如上述一样被缓冲,但是可以使用14引脚连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值