F28335第十篇——增强型捕获模块(eCAP)
简介
F28335共有6个独立的捕获通道,如下表:
| eCAP | GPIO | 结构体变量 |
|---|---|---|
| 1 | 5/24/34 | ECap1Regs |
| 2 | 7/25/37 | ECap2Regs |
| 3 | 9/26 | ECap3Regs |
| 4 | 11/27 | ECap4Regs |
| 5 | 3/48 | ECap5Regs |
| 6 | 1/49 | ECap6Regs |
对应CMD中地址分配为:
ECAP1 : origin = 0x006A00, length = 0x000020 /* Enhanced Capture 1 registers */
ECAP2 : origin = 0x006A20, length = 0x000020 /* Enhanced Capture 2 registers */
ECAP3 : origin = 0x006A40, length = 0x000020 /* Enhanced Capture 3 registers */
ECAP4 : origin = 0x006A60, length = 0x000020 /* Enhanced Capture 4 registers */
ECAP5 : origin = 0x006A80, length = 0x000020 /* Enhanced Capture 5 registers */
ECAP6 : origin = 0x006AA0, length = 0x000020 /* Enhanced Capture 6 registers */
关于CMD文件更多知识,可以参见——F28335第四篇——存储器及CMD文件
除此之外,每个捕获通道还具有以下资源:
- 32位时钟计数器
- 4个32位时钟标识寄存器(CAP1到CAP4):这是四个寄存器,用来储存捕获事件时钟值。只是寄存器的名称命名为CAP1到CAP4,不要和捕获通道混淆。
- 可以为4个捕获事件设定独立的边沿极性。
- 配置单词捕获和连续捕获功能。
- 4个捕获事件都可以触发中断。
eCAP可以工作在两种模式:
- 捕获模式:用于获取属于信号时间属性,例如,信号周期,占空比等。
- 脉冲发生器模式(APWM):计数器只能工作在递增模式下,产生不对称的PWM波。加上ePWM模块的12路,F28335最多可以同时产生18路PWM波。
APWM模式
在APWM模式下,CAP1到CAP4分别用作:
- CAP1:周期当前寄存器(Period active reg)
- CAP2:比较当前寄存器(Compare active reg)
- CAP3:周期映射寄存器(Period shadow reg)
- CAP4:比较映射寄存器(Compare shadow reg)
对CAP1及CAP2进行写操作,同样的内容也会被写入到CAP3和CAP4中。如果对CAP3或CAP4进行写操作,将会启动映射模式。
在初始化过程中,必须首先当前寄存器。在程序运行过程中,可以通过写入映射寄存器来修改占空比或PWM周期。
在APWM模式中,可触发两种中断事件:
- CTR=PRD:计数器的值等于周期寄存器
- CTR=CMP:计数器的值等于比较寄存器

捕获模式
捕获模式分成单次捕获和连续捕获两种模式。可以通过ECCTL2[CONT/ONESHT]寄存器来选择模式类型。
32位时钟计数器及相位控制
直接由系统时钟SYSCLKOUT驱动。相位寄存器通过软件或者硬件的方式将多个eCAP模块计数器进行同步。
CAP1到CAP4寄存器
寄存器的输入端直接与32位时钟计数器相连。当捕获事件发生时,直接将时钟计数器的值装载入对应的CAP寄存器中。通过ECCTCL1[CAPLDEN]寄存器可以开启/禁止装载功能。
预分频
通过ECCTL1[PRESCALE]控制。一般选择不分频,以提高捕获精度。
边沿设定
可以分别将4个捕获事件配置成上升沿或者下降沿。在ECCTL1寄存器中设定。
MOD4计数器
- mod4计数器(2bit位)在捕获事件触发时进行增计数。
- 在连续模式下,mod4计数模式为:0-1-2-3-0,捕获值会连续不断放入到CAP1到CAP4寄存器中。
- 在单次模式下,mod4计数模式默认为由1到3停止。即共发生4次捕获,分别存入CAP1到CAP4寄存器中。可以通过ECCTL2[STOP_WRAP]寄存器来修改捕获的次数。

中断控制
eCAP模块共可以产生7种中断事件:
- CEVT1:CAP1发生捕获事件
- CETV2:CAP2发生捕获事件
- CETV3:CAP3发生捕获事件
- CETV4:CAP4发生捕获事件
- CNTOVF:计数器溢出事件
- CTR=PRD:计数器的值等于周期寄存器
- CTR=CMP:计数器的值等于比较计数器
其中,前5种工作在捕获模块,后2种工作在APWM模块。
寄存器
所有相关寄存器
struct ECAP_REGS
{
Uint32 TSCTR; // 时钟计数器:可读写,默认值0
Uint32 CTRPHS; //计数器相位寄存器:可读写,默认值0
Uint32 CAP1; // 捕获寄存器1:可读写,默认值0
Uint32 CAP2; // 捕获寄存器2:可读写,默认值0
Uint32 CAP3; // 捕获寄存器3:可读写,默认值0
Uint32 CAP4; // 捕获寄存器4:可读写,默认值0
Uint16 rsvd1[8]; // reserved
union ECCTL1_REG ECCTL1; // 捕获控制寄存器1
union ECCTL2_REG ECCTL2; // 捕获控制寄存器2
union ECEINT_REG ECEINT; // ECAP中断使能寄存器
union ECFLG_REG ECFLG; // ECAP中断标志寄存器
union ECFLG_REG ECCLR; // ECAP中断标志清除寄存器
union ECEINT_REG ECFRC; // ECAP中断强制寄存器(测试)
Uint16 rsvd2[6]; // reserved
};
ECCTL1
struct ECCTL1_BITS
{
Uint16 CAP1POL:1; // 0[R/W-0] 捕获事件1触发极性选择。0:上升沿触发,1:下降沿触发
Uint16 CTRRST1:1; // 1[R/W-0] 捕获事件1计数器复位控制。0:捕获发生不复位计数器(绝对时间模式),1:捕获发生复位计数器(相对时间模式)
Uint16 CAP2POL:1; // 2[R/W-0] 捕获事件2触发极性选择
Uint16 CTRRST2:1; // 3[R/W-0] 捕获事件2计数器复位控制
Uint16 CAP3POL:1; // 4[R/W-0] 捕获事件3触发极性选择
Uint16 CTRRST3:1; // 5[R/W-0] 捕获事件3计数器复位控制
Uint16 CAP4POL:1; // 6[R/W-0] 捕获事件4触发极性选择
Uint16 CTRRST4:1; // 7[R/W-0] 捕获事件4计数器复位控制
Uint16 CAPLDEN:1; // 8[R/W-0] 控制捕获事件发生时是否装载CAP1-CAP4。0:禁止装载,1:使能装载
Uint16 PRESCALE:5; // 13:9[R/W-0] 事件预分频控制位。0:不分频,0000-1111(k):2k分频
/*
* 仿真控制位。
* 00:仿真挂起时,TSCTR立即停止
* 01:仿真挂起时,TSCTR计数到0停止
* 1x:TSCTR不受影响
*/
Uint16 FREE_SOFT:2; //15:14[R/W-0]
};
ECCTL2
struct ECCTL2_BITS
{
Uint16 CONT_ONESHT:1; // 0[RW-0] 连续/单次捕获模式。0:连续模式,1:单次模式
/*
*00-11(k):
* 在单次模式下,捕获k+1次后停止。
* 在连续模式下,捕获k+1次后,mod4计数器归0。
* 总结:mod4计数器的最大值。即只使用到CAP(K+1)寄存器
*/
Uint16 STOP_WRAP:2; // 2:1[RW-11] 单次模式下停止值。
Uint16 REARM:1; // 3[RW-0] 重新装载控制位。0:无反应,1:将mod4复位到0,解冻mod4计数器,重新捕获
Uint16 TSCTRSTOP:1; // 4[RW-0] 时钟计数器使能。0:计数器停止;1:计数器继续计数
Uint16 SYNCI_EN:1; // 5[RW-0] 时钟计数器同步使能。0:禁止同步功能;1:使能同步功能
Uint16 SYNCO_SEL:2; // 7:6[RW-00] 同步输出使能。00:将SYNC_IN作为同步输出SYNC_OUT。
//01:CTR=PRD作为同步输出SYNC_OUT。1x:禁止同步输出
Uint16 SWSYNC:1; // 8[RW-0] 软件强制同步。0:无反应;1:产生一次强制同步信号
Uint16 CAP_APWM:1; // 9[RW-0] 工作模式选择。0:工作在铺货模式。1:工作在APWM模式。
Uint16 APWMPOL:1; // 10[RW-0] APWM输出极性选择。0:高电平有效。1:低电平有效
Uint16 rsvd1:5; // 15:11[R-0] 保留
};
ECINT
寄存器中除了保留位,所有都是可读写。0:禁止对应中断,1:使能对应中断。
struct ECEINT_BITS { // bits description
Uint16 rsvd1:1; // 0 reserved
Uint16 CEVT1:1; // 1 Capture Event 1 Interrupt Enable
Uint16 CEVT2:1; // 2 Capture Event 2 Interrupt Enable
Uint16 CEVT3:1; // 3 Capture Event 3 Interrupt Enable
Uint16 CEVT4:1; // 4 Capture Event 4 Interrupt Enable
Uint16 CTROVF:1; // 5 Counter Overflow Interrupt Enable
Uint16 CTR_EQ_PRD:1; // 6 Period Equal Interrupt Enable
Uint16 CTR_EQ_CMP:1; // 7 Compare Equal Interrupt Enable
Uint16 rsvd2:8; // 15:8 reserved
};
ECFLG
中断标志位。所有位都是只读的。0:无中断发生;1:有中断发生。
struct ECFLG_BITS { // bits description
Uint16 INT:1; // 0 Global Flag
Uint16 CEVT1:1; // 1 Capture Event 1 Interrupt Flag
Uint16 CEVT2:1; // 2 Capture Event 2 Interrupt Flag
Uint16 CEVT3:1; // 3 Capture Event 3 Interrupt Flag
Uint16 CEVT4:1; // 4 Capture Event 4 Interrupt Flag
Uint16 CTROVF:1; // 5 Counter Overflow Interrupt Flag
Uint16 CTR_EQ_PRD:1; // 6 Period Equal Interrupt Flag
Uint16 CTR_EQ_CMP:1; // 7 Compare Equal Interrupt Flag
Uint16 rsvd2:8; // 15:8 reserved
};
ECCLR
中断标志清除位。除了保留位,都是可读写。默认值为0。0:无反应,读取始终返回0;1:清除响应的中断标志位。寄存器位定义和ECFLG完全相同。
例程
功能
将eCAP1配置为APWM模式。输出PWM的频率为15K Hz,占空比为30%,并通过GPIO5输出。
将eCAP2配置为捕获模式。其中,CAP1和CAP3寄存器配置为上升沿捕获,CAP2和CAP4寄存器配置为下降沿捕获。使用绝对时间模式。使用GPIO25做为输入。
将GPIO5和GPIO25短接。通过eCAP2捕获eCAP1发出PWM波,获得每个PWM周期内的高电平与低电平时间。
源代码
主程序
/*
* main.c
*
* 主程序实现两种功能:
* 1.利用CAP模块发出PWM
* 2.利用CAP捕捉到PWM
*/
int main(void)
{
//1.系统初始化
InitSysCtrl();
//2.中断
//2.1关闭中断
DINT;
IER = 0x0000;
IFR = 0x0000;
InitPieCtrl();
InitPieVectTable();
//2.2开CAP2中断
EALLOW;
PieVectTable.ECAP2_INT = &IsrEcap2; //写入中断服务函数
EDIS;
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; //使能PIE向量表
PieCtrlRegs.PIEIER4.bit.INTx2 = 1; //打开第四组第二个中断
IER |= M_INT4; //打开CPUj级第四组中断
EINT;//打开全局中断
//3.初始化GPIO
InitECap1Gpio(); //用于生成PWM波
InitECap2Gpio(); //用于捕捉PWM
//4.自定义功能
InitECap();
while (1);
}
GPIO初始化
void InitECap1Gpio(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0; //上拉电阻使能
GpioCtrlRegs.GPAQSEL1.bit.GPIO5 = 0; //系统时钟同步输入
GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 3; //功能选择为eCAP1
EDIS;
}
void InitECap2Gpio(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO25 = 0; // 上拉电阻使能
GpioCtrlRegs.GPAQSEL2.bit.GPIO25 = 0; //系统时钟同步输入
GpioCtrlRegs.GPAMUX2.bit.GPIO25 = 1; // 功能选择为eCAP2
EDIS;
}
eCAP功能初始化
void InitECap(void)
{
/*CAP1配置输出PWM波*/
ECap1Regs.ECCTL2.bit.CAP_APWM = 1; //工作在APWM模式
ECap1Regs.ECCTL2.bit.APWMPOL = 0; //高电平有效(比较值决定高电平的时间,先高后低)
ECap1Regs.ECCTL2.bit.SYNCI_EN = 0; //禁止同步功能
ECap1Regs.ECCTL2.bit.SYNCO_SEL = 2; //禁止同步输出
ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; //使能计数器开始计数
ECap1Regs.TSCTR = 0; //时钟清零
//设置周期和占空比
ECap1Regs.CAP1 = 10000; //PWM周期为10K个时钟周期
ECap1Regs.CAP2 = 3000; //设置占空比
/*CAP2配置计数PWM波*/
ECap2Regs.TSCTR = 0; //时钟清零
ECap2Regs.ECCTL1.bit.PRESCALE = 0; //计时器使用系统时钟,不分频
ECap2Regs.ECCTL1.bit.CAPLDEN = 1; //使能捕获装载CAP
ECap2Regs.ECCTL1.bit.CTRRST1 = 0; //绝对时间试
ECap2Regs.ECCTL1.bit.CTRRST2 = 0; //绝对时间试
ECap2Regs.ECCTL1.bit.CTRRST3 = 0; //绝对时间试
ECap2Regs.ECCTL1.bit.CTRRST4 = 0; //绝对时间试
ECap2Regs.ECCTL1.bit.CAP1POL = 0; //上升沿触发捕获
ECap2Regs.ECCTL1.bit.CAP2POL = 1; //下降沿触发捕获
ECap2Regs.ECCTL1.bit.CAP3POL = 0; //上升沿触发捕获
ECap2Regs.ECCTL1.bit.CAP4POL = 1; //下降沿触发捕获
ECap2Regs.ECCTL2.bit.CAP_APWM = 0; //工作在捕获模式
ECap2Regs.ECCTL2.bit.SYNCI_EN = 0; //禁止同步功能
ECap2Regs.ECCTL2.bit.SYNCO_SEL = 2; //禁止同步输出信号
ECap2Regs.ECCTL2.bit.CONT_ONESHT = 0; //工作在连续模式下
ECap2Regs.ECCTL2.bit.TSCTRSTOP = 1; //计数器开始计数
//中断控制
ECap2Regs.ECEINT.all = 0x10; //只打开CEVT4中断
}
中断服务程序
Uint32 t1, t2, t3, t4;
long T1, T2, T3, T4;
interrupt void IsrEcap2()
{
PieCtrlRegs.PIEACK.bit.ACK4 = 1; //第四组已经响应中断
ECap2Regs.ECCLR.all = 0xFFFF; //将所有中断清除
t1 = ECap2Regs.CAP1;
T4 = t1 - t4;//上一次的第二个低电平时间
t2 = ECap2Regs.CAP2;
t3 = ECap2Regs.CAP3;
t4 = ECap2Regs.CAP4;
T1 = t2 - t1;//本次第一个高电平时间
T2 = t3 - t2;//本次第二个低电平时间
T3 = t4 - t3;//本次第二个高电平时间
}
结果

注意
关于APWM配置时候,TI官方文档有一处有问题。我花了一整天才找到问题所在,所以才下了决心写这篇博客。

其中,配置程序中,先设置PWM的周期时间,再配置其他寄存器是错误的。
//错误写法
//=======================
// ECAP module 1 config
//先配置PWM周期
ECap1Regs.CAP1 = 0x1000; // Set period value
ECap1Regs.CTRPHS = 0x0; // make phase zero
//配置其他寄存器
ECap1Regs.ECCTL2.bit.CAP_APWM = EC_APWM_MODE;
ECap1Regs.ECCTL2.bit.APWMPOL = EC_ACTV_HI; // Active high
ECap1Regs.ECCTL2.bit.SYNCI_EN = EC_DISABLE; // Synch not used
ECap1Regs.ECCTL2.bit.SYNCO_SEL = EC_SYNCO_DIS; // Synch not used
ECap1Regs.ECCTL2.bit.TSCTRSTOP = EC_RUN; // Allow TSCTR to run
正确的写法,应该是eCAP功能初始化中的设定方式。摘取如下:
/*CAP1配置输出PWM波*/
ECap1Regs.ECCTL2.bit.CAP_APWM = 1; //工作在APWM模式
ECap1Regs.ECCTL2.bit.APWMPOL = 0; //高电平有效(比较值决定高电平的时间,先高后低)
ECap1Regs.ECCTL2.bit.SYNCI_EN = 0; //禁止同步功能
ECap1Regs.ECCTL2.bit.SYNCO_SEL = 2; //禁止同步输出
ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; //使能计数器开始计数
ECap1Regs.TSCTR = 0; //时钟清零
//设置PWM周期和占空比
ECap1Regs.CAP1 = 10000; //PWM周期为10K个时钟周期
ECap1Regs.CAP2 = 3000; //设置占空比
智能推荐
【MySQL】第十篇:MySQL事务详解
事务是MySQL等关系型数据库区别于NoSQL的重要方面,是保证数据一致性的重要手段。本文将首先介绍MySQL事务相关的基础概念,然后介绍事务的ACID特性,并分析其实现原理。 一、基础概念 事务(Transaction)是访问和更新数据库的程序执行单元;事务中可能包含一个或多个sql语句,这些语句要么都执行,要么都不执行。作为一个关系型数据库,MySQL支持事务,本文介绍基于MySQL5.6。 ...
Postman第十篇:自动获取token
Postman请求自动获取token 添加一个环境 1 添加登录接口 添加一个集合 添加需要token的请求 在刚创建的集合中添加的请求, Headers中都会自动添加 token, 如果token失效, 重新请求一下登录接口即可...
Linux内核之进程调度3:进程调度
1. 吞吐率和响应 吞吐:单位时间内做的有用功; 响应:低延迟。 吞吐追求的整个系统CPU做有用功,响应追求的是某个特定任务的延迟低; 1GHZ的CPU切换线程保存恢复现场约几个微妙级别,看似消耗不了太多时间,但是由于系统的局部性原理,会保存当前线程数据的缓存,切换线程会打乱局部性引起cache miss,而CPU访问cache速度远大于内存访问,这样综合看来上下文切换花销还是很大的。无用功占用较...
restful+ci框架 实践
restful架构: 是就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。具体理论请看我上一篇写的restful理论。本篇主要记录下关于restful的实践。 restful实践: 工具: 这次在ci框架+restful 主要文件: 在控制器中添加控制器类:Restful.php。 在头部包含REST_Controller.php文件并继承...
Configuration, ConfigurationProperties和EnableConfigurationProperties用法
最近刚刚解决了个错误,突然又发现这个类在spring容器中找不到, 于是我就加一个 @Component的注解,哈哈直接启动成功,那我如果吧这个注解去掉,加上一个@Configuration的注解呢,哈哈还是可以的,毕竟里面已经有这个@Component的注解了。所以我就整理下Configuration,ConfigurationProperties,EnableConfigurationProp...
猜你喜欢
备战蓝桥杯--贪心算法刷题整理5
翻硬币(贪心算法) 看了一下网上的题解,感觉挺强,网友的做题思想值得借鉴,这里分享一下网友的链接,同时再分享一下自己的解题方案 链接:https://blog.csdn.net/qq_34594236/article/details/60326782 题目描述: 小明正在玩一个“翻硬币”的游戏。 桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母...
部署高可用RabbitMQ
安装 准备工作 这里我们使用三个RabbitMQ节点: 开通端口(具体见官方文档): 安装ErLang和RabbitMQ Server 安装文档见:https://www.rabbitmq.com/install-rpm.html。 采用RPM包而不是Repo的安装命令如下(以下的版本号可根据实际情况修改): 安装管理插件 安装文档见:https://www.rabbitmq.com/manage...
Opencv常用代码总结
文章目录 读取显示图像 保存图片 查看图片信息 读取视频 截取部分图像数据 颜色通道提取、融合与保留 边界填充 数值计算 图像融合 图像阈值 图像平滑(降噪) 形态学-腐蚀操作 形态学-膨胀操作 开运算与闭运算 梯度运算 礼帽与黑帽 图像梯度 Sobel算子 Scharr算子 laplacian算子 Canny边缘检测 图像金字塔 高斯金字塔:向下采样(缩小) 高斯金字塔:向上采样(放大) 拉普拉...
Numpy实现LDA
LDA与PCA的区别如下表: LDA的原理如下: 代码实现如下,这里使用的a,b是Nx2的二维点集合,经过LDA后,二维的点变为一维。更高维度的也是可以做到的。函数里的dim是原始数据的维度,d是想要降到的维度。 初始的数据如下图,红色点和蓝色点代表不同的分类。 经过LDA后,投影的一维数值如下图所示。 可见LDA实现了降维,而且两种分类的间距较大,类内的散度较小。...
Java反射机制
相关类型: java.lang.Class java.lang.reflect.Constructor java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Modifier 作用: 1、反编译 .class –> .java&n...
