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();// 初始化串口终端 使用串口2UARTStdioInit();// 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 / APWM2ECAPPinMuxSetup(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捕获输入模式

最新文章

  1. [Android实例] 最全的Android开发资源整理--进阶必备
  2. 如何在签约之前搞定难缠的客户
  3. QML基础类型之list
  4. 1.Swift教程翻译系列——关于Swift
  5. Oracle中ascii为0的陷阱
  6. laravel并行访问MySQL_laravel实现多数据库连接配置
  7. 允许活动内容在我的计算机上,然后就看到选项允许活动内容在我的计算机上的文件中运行...
  8. Linux万兆网络配置
  9. 笔记本上的小键盘计算机怎样用,笔记本小键盘如何关闭和开启 小键盘不能用了怎么办...
  10. 绘制地图其实并不难!如何绘制地图?看看Smartbi的制作方法
  11. 论文后面的参考文献格式应该如何写
  12. uva 1589 - Xiangqi(象棋)
  13. android 短信超链接,Android处理网页的短信链接
  14. 大数据人才培养的规划之路如何走
  15. 05.python学习系列——画图库turtle(啥是小猪佩奇)
  16. 函数节流(Throttle)和防抖(Debounce)解析及其OC实现
  17. Linux系统级IO②:RIO-带缓冲区IO实现
  18. ShaderJoy —— 多物体 Raymarching (图形拼接 + 地面投影)入门 【GLSL】
  19. 利用python对批量修改文件名
  20. C++统计程序运行时间

热门文章

  1. 获取官方win10系统镜像方法
  2. 掌握Haproxy原理并搭建
  3. 分析Padavan的代码二
  4. 【设计模式】-状态模式->APP抽奖活动(源码与类图解析)
  5. pyftpdlib 创建ftpserver
  6. [车联网安全自学篇] Android安全之Android中常用权限手册「必备」
  7. 文件夹访问被拒绝,您需要权限来执行操作
  8. 图片转Word文档怎么转?这两种转换方法学起来
  9. github网站进不去怎么办
  10. 安恒月赛-dasctf 部分writeup