TMS320C6748_PWM_ECAP

1.主函数流程

此程序的作用是实现eCAP(增强型捕获模块)的输入捕获功能,将ECAP2_APWM2设置为输入捕获模式,检测由EPWM1_A管脚输出的方波频率。将EPWMN0_TZ[0](ECAP2_APWM2和EPWMN0_TZ[0]引脚功能复用)和EPWM1_A短接,即可看到串口输出EPWMN0_TZ[0]脚所捕获到的EPWM1_A引脚输入的方波频率信息。主函数如下:

int main(void)
{
  // 外设使能配置
  PSCInit();

  // 初始化串口终端 使用串口2
  UARTStdioInit();
    
  // GPIO 管脚复用配置
  GPIOBankPinMuxSet();

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

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

  unsigned char i;
  unsigned int j;

  UARTPuts("Tronlong PWM_ECAP Application......\r\n", -1);
  UARTPuts("------------------------------------------------------------\r\n", -1);
  UARTPuts("                    C6748 PWM Test\r\n\r\n", -1);
  // 产生波形
  PWM1ABasic(25000,50);

  UARTPuts("                    C6748 PWM Test Over!\r\n",-1);
  UARTPuts("------------------------------------------------------------\r\n", -1);


  UARTPuts("------------------------------------------------------------\r\n", -1);
  UARTPuts("                    C6748 ECAP Test\r\n", -1);
  // ECAP 捕获初始化
  ECAPInit();
  UARTPuts("Initialize ECAP.......\r\n",-1);
  for(i=0;i<5;i++)
  {
    for(j=0x00FFFFFF;j>0;j--);            // 延时
    ECAPRead();
  }
  UARTPuts("\r\n",-1);
  UARTPuts("                    C6748 ECAP Test Over!\r\n",-1);
  UARTPuts("------------------------------------------------------------\r\n", -1);

  // 主循环
  for(;;)
  {

  }
}

2.外设使能配置

    函数首先在PSC模块中使能外设,这里是eHRPWM模块1和eCAP0/1/2。外设使能配置函数PSCInit如下:

void PSCInit(void)
{
  // 使能  EHRPWM 和 ECAP 模块
  // 对相应外设模块的使能也可以在 BootLoader 中完成
  PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_EHRPWM, PSC_POWERDOMAIN_ALWAYS_ON, 
    PSC_MDCTL_NEXT_ENABLE);

  PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_ECAP0_1_2, PSC_POWERDOMAIN_ALWAYS_ON, 
    PSC_MDCTL_NEXT_ENABLE);
}

函数在PSC中使能HW_PSC_EHRPWM(#17)模块和HW_PSC_ECAP0_1_2(#20)模块,这两个模块的Power Domain是ALWAYS_ON域(POWER DOMAIN 0),PSCModuleControl细节可参考这里:

C6748_UART_EDMA

(指南P163)

3.初始化串口终端

    程序初始化串口终端,使用串口2,打印输出PWM波相关信息,UARTStdioInit函数细节参考这里:

C6748_UART_EDMA

4.GPIO管脚复用配置

    将EHRPWM模块和ECAP模块所在的引脚的功能配置为EHRPWM功能和ECAP功能,GPIO管脚复用配置函数GPIOBankPinMuxSet函数如下:

void GPIOBankPinMuxSet(void)
{
  EHRPWM1PinMuxSetup();

  // OMAPL138 / DSP C6748 有三个增强捕获模块(ECAP)
  // 作为捕获功能时管脚方向为输入
  // 作为辅助脉宽调制时管脚方向为输出
  // ECAP2 / APWM2
  ECAPPinMuxSetup(2);

  // ECAP2 / APWM2方向设置为输入
  GPIODirModeSet(SOC_GPIO_0_REGS, 8, GPIO_DIR_INPUT);     //  GPIO0[7]
}

EHRPWM1PinMuxSetup函数参考这里的第3节:

C6748_PWM

ECAPPinMuxSetup函数参考这里的第3节:

C6748_ECAP_APWM

调用GPIODirModeSet函数,将ECAP2/APWM2管脚方向设置为输入方向,则启用ECAP模块的模式为捕获模式(capture mode)。

5.DSP中断初始化

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

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

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

函数细节参考这里

C6748_SPI_FLASH

6.PWM中断初始化

PWM中断初始化函数PWMInterruptInit可参考这里的第5节:

C6748_PWM

7.产生波形

产生波形函数PWM1ABasic (25000,50)如下,其中第一个参数25000表示产生的PWM波的频率为25000Hz(25KHz),第二个参数50表示波形占空比为50%。细节可参考这里的第6节。

C6748_PWM

8.ECAP捕获初始化

    ECAP捕获初始化函数ECAPInit如下:

void ECAPInit(void)
{
  /*-----设置 ECCTL1-----*/
  // 使能CAP寄存器装载
  ECAPCaptureLoadingEnable(SOC_ECAP_2_REGS);
  // 设置预分频值.
  ECAPPrescaleConfig(SOC_ECAP_2_REGS, 0);
  // 上升沿触发捕获事件
  ECAPCapeEvtPolarityConfig(SOC_ECAP_2_REGS, 0,0,0,0);
  // 输入捕获后重新装载计数器值.
  ECAPCaptureEvtCntrRstConfig(SOC_ECAP_2_REGS, 1,1,1,1);

  /*-----设置 ECCTL2-----*/
  // 连续模式
  ECAPContinousModeConfig(SOC_ECAP_2_REGS);
  // ECAP计数器TSCTR持续计数
  ECAPCounterControl(SOC_ECAP_2_REGS,ECAP_COUNTER_FREE_RUNNING);
  // 禁用同步输出和同步输入
  ECAPSyncInOutSelect(SOC_ECAP_2_REGS, ECAP_SYNC_IN_DISABLE,ECAP_SYNC_OUT_DISABLE);
  // 配置 ECAP 2 为 CAPTURE 模式
  ECAPOperatingModeSelect(SOC_ECAP_2_REGS, ECAP_CAPTURE_MODE);

  // 使能中断
  // ECAPIntEnable(SOC_ECAP_2_REGS, 
  ECAP_ECEINT_CEVT1|ECAP_CEVT2_INT|ECAP_CEVT3_INT|ECAP_CEVT4_INT);
}

8.1 设置ECCTL1

8.1.1 使能CAP寄存器模块

    ECAPCaptureLoadingEnable函数设置ECCTL1[8](CAPLDEN)位为1,使能捕获事件(capture event)发生时CAPs寄存器装载(loading)。这里使能的是ECAP2模块。该API如下:

void ECAPCaptureLoadingEnable(unsigned int baseAdd)
{
  HWREGH(baseAdd + ECAP_ECCTL1) |= ECAP_ECCTL1_CAPLDEN; 
}

(指南P366)

(指南P340)

8.1.2 设置预分频值

ECAPPrescaleConfig函数设置ECCTL1[PRESCALE]位,设置事件的预分频值,这里设为0,即不分频,信号旁通(by-pass)过预分频器(prescaler)。该API如下:

void ECAPPrescaleConfig(unsigned int baseAdd, unsigned int prescale)
{
  HWREGH(baseAdd + ECAP_ECCTL1) &= 0xffffc1ff;
  HWREGH(baseAdd + ECAP_ECCTL1) |= (prescale << ECAP_ECCTL1_PRESCALE_SHIFT);
}

(指南P341)

(指南P366)

8.1.3 上升沿触发捕获事件

ECAPCapeEvtPolarityConfig函数设置ECCTL1的CAP1POL、CAP2POL、CAP3POL、CAP4POL位,设置CAP1-CAP4的捕获事件CEVT1-CEVT4。这里程序把这四位都设为0,即上升沿触发捕获事件。该API如下:

void ECAPCapeEvtPolarityConfig(unsigned int baseAdd, unsigned int capEvt1pol,
                               unsigned int capEvt2pol, unsigned int capEvt3pol,
                               unsigned int capEvt4pol)
{
  HWREGH(baseAdd + ECAP_ECCTL1) |= capEvt1pol << 0;
  HWREGH(baseAdd + ECAP_ECCTL1) |= capEvt2pol << 2;
  HWREGH(baseAdd + ECAP_ECCTL1) |= capEvt3pol << 4;
  HWREGH(baseAdd + ECAP_ECCTL1) |= capEvt4pol << 6;
}

(指南P367)

8.1.4 输入捕获后重新装载计数器值

ECAPCaptureEvtCntrRstConfig函数设置ECCTL1的CTRRST1-CTRRST4位,设置计数器(TSCRT,time-stamp counter)在捕获事件(capture event)CEVT1-CEVT4发生时是否复位(即清除为0)。这里程序全部设为1,则全部复位。该API如下:

void ECAPCaptureEvtCntrRstConfig(unsigned int baseAdd, unsigned int CounterRst1,
                                 unsigned int CounterRst2,unsigned int CounterRst3,
                                 unsigned int CounterRst4)
{
  HWREGH(baseAdd + ECAP_ECCTL1) |= CounterRst1 << 1;
  HWREGH(baseAdd + ECAP_ECCTL1) |= CounterRst2 << 3;
  HWREGH(baseAdd + ECAP_ECCTL1) |= CounterRst3 << 5;
  HWREGH(baseAdd + ECAP_ECCTL1) |= CounterRst4 << 7;
}

(指南P367)

8.2 设置ECCTL2

8.2.1 连续模式

ECAPContinousModeConfig函数设置ECCTL2[0](CONT/ONESHT)位为0,配置ECAP模块为连续模式。则当捕获完一轮事件(CEVT1-CEVT4)之后,ECAP又继续捕获下一次事件序列(event sequence)。该API如下:

void ECAPContinousModeConfig(unsigned int baseAdd)
{
    HWREGH(baseAdd + ECAP_ECCTL2) &= ~ECAP_ECCTL2_CONT_ONESHT;  
}

(指南369)

8.2.2 ECAP计数器TSCTR持续计数

ECAPCounterControl函数设置ECCTL2[TSCTRSTOP]位,从而启动或停止计数器TSCTR(time stamp counter),这里程序设置该位为1,即启动TSCTR,TSCTR置位运行状态(free-running)。该API如下:

void ECAPCounterControl(unsigned int baseAdd, unsigned int flag)
{
  if(flag)
  {
    HWREGH(baseAdd + ECAP_ECCTL2) |= ECAP_ECCTL2_TSCTRSTOP;
  }
  else
  {
    HWREGH(baseAdd + ECAP_ECCTL2) &= ~ECAP_ECCTL2_TSCTRSTOP;
  }
}

(指南P368)

8.2.3 禁用同步输出和同步输入

ECAPSyncInOutSelect函数设置ECCTL2[SYNCO_SEL]位和ECCTL2[SYNCI_SEL]位,配置同步输入和同步输出,这里程序将ECCTL2[SYNCI_SEL]位设为0,即禁用同步输入,将ECCTL2[SYNCO_SEL]位设为10(2进制的10,即2h),禁用同步输出。该API如下:

void ECAPSyncInOutSelect(unsigned int baseAdd, unsigned int syncIn,
                         unsigned int syncOut)
{
  HWREGH(baseAdd + ECAP_ECCTL2) &= 0xffffffdf;
  HWREGH(baseAdd + ECAP_ECCTL2) |= syncIn;
  HWREGH(baseAdd + ECAP_ECCTL2) &= 0xffffff3f;
  HWREGH(baseAdd + ECAP_ECCTL2) |= syncOut;
}

(指南P368)

(指南P343)

8.2.4 配置ECAP2为CAPTURE模式

    ECAPOperatingModeSelect函数设置ECCTL2[9]位(CAP/APWM),选择ECAP模块的运行模式(operating mode),这里程序将该位设为0,即选择捕获模式(capture mode)。该API如下:

void ECAPOperatingModeSelect(unsigned int baseAdd, unsigned int modeSelect)
{
  if(modeSelect)
  {
    HWREGH(baseAdd + ECAP_ECCTL2) &= ~ECAP_ECCTL2_CAP_APWM;
  }
  else
  {
    HWREGH(baseAdd + ECAP_ECCTL2) |=  ECAP_ECCTL2_CAP_APWM;
  }
}

(指南P368)

9.取得捕获结果

    经过一段延时后,程序调用ECAPRead函数读取捕获结果,ECAPRead函数如下:

unsigned int ECAPRead(void)
{
  unsigned int capvalue;
  unsigned long frequency;

  // Event1 中断标志
  if(ECAPIntStatus(SOC_ECAP_2_REGS, ECAP_CEVT1_INT))
  {
    // 取得捕获计数
    EcapContextSave(SOC_ECAP_2_REGS,0,&ECAPResult);
    capvalue = ECAPResult.cap1;

    // CAPTRUE 模块 228M 时钟主频
    frequency  =  228000000/capvalue;
    UARTprintf("ECAPRead:frequency = %d\r\n",frequency);

    ECAPIntStatusClear(SOC_ECAP_2_REGS, ECAP_ECEINT_CEVT1);
    //      IntEventClear(SYS_INT_ECAP2);
  }
  return frequency;
}

ECAPIntStatus函数读取ECFLG寄存器,返回指定的中断,这里返回CEVT1事件中断。当CEVT1事件中断标志为1时(即发生了CEVT1),程序读取捕获计数。该API如下:

unsigned int ECAPIntStatus(unsigned int baseAdd, unsigned int flag)
{
  return (HWREGH(baseAdd + ECAP_ECFLG) & flag);
}

EcapContextSave函数读取CAP1和CAP2的捕获计数结果,该API如下:

void EcapContextSave(unsigned int ecapBase, unsigned int pwmssBase,
                     ECAPCONTEXT *contextPtr)
{
  contextPtr->pwm0ssclkconfig =  HWREG(pwmssBase + PWMSS_CLOCK_CONFIG);
  contextPtr->tsctr = HWREG(ecapBase + ECAP_TSCTR);
  contextPtr->eceint = HWREGH(ecapBase + ECAP_ECEINT);
  contextPtr->ecclr = HWREGH(ecapBase + ECAP_ECCLR);
  contextPtr->ecctl2 = HWREGH(ecapBase + ECAP_ECCTL2);
  contextPtr->cap1 = HWREG(ecapBase + ECAP_CAP1);
  contextPtr->cap2 = HWREG(ecapBase + ECAP_CAP2);
}

然后程序将CAP1的值存到capvalue中,该值即为从ECAP输入引脚捕获的PWM波的一个周期的时钟数(ECAP模块时钟为228MHz)。从而可以计算出捕获的PWM波频率为228000000/capvalue。

最后ECAPIntStatusClear函数清除ECFLG中的标志,这里清除CEVT1位。

10.参考文献

[1]  stm32 输入捕获学习(一)

[2]  stm32 PWM input捕获输入模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值