TI-C2000-捕获模块ECAP应⽤-以欧姆龙E6B2-CWZ6C测速编码器为例
基于TI的F2833xD的捕获模块应⽤
⽂章信息
撰写⽇期2018.12.20
完稿⽇期2018.12.20
最近维护2019.07.14
本⽂作者multimicro
联系⽅式
GitHub
本⽂地址
开发环境
环境说明详细信息备注信息
操作系统Win10_x64
CCS版本Code Compor Studio v8
cloyoureyescontrolSUITE controlSUITE for C2000 MCUs
F28335硬汉F28335开发板(150MHz时钟频率)
欧姆龙E6B2编码器E6B2-CWZ6C 1000 P/R
捕获模块简介
F28335的Ecap模块捕获过程如下
该定时器是捕获模块专⽤定时器,在设定好捕获事件后,每捕获⼀个事件,对应的各级捕获寄存器就会把时间记录在捕获寄存器⾥⾯,通过这些时间信息即可计算出速度信息。
Ecap模块中⽐较重要的寄存器
eCAP控制寄存器ECCTL1
⽤于配置触发捕获事件的条件和对应的计数器(⼀共四级,详见程序注释)
eCAP控制寄存器ECCTL2
⽤于配置eCAP的⼯作模式,包括进⼊中断的⽅式等
eCAP捕获寄存器eCAPx
⽤于记录各级捕获事件发⽣时的时间
其余寄存器在代码中查看其作⽤
对与F2837xD,其配置捕获模块的程序和F28335的程序完全⼀样,唯⼀的不同就是配置Ecap输⼊引脚⽅式不同,F28335有固定的Ecap输⼊引脚,⽽F2837xD的捕获输⼊因为加⼊了Crossbar(X-BAR)机
制,使得配置输⼊引脚其他C2000系列DSP更加灵活,可以使⽤任何⼀个GPIO⼝作为捕获输⼊,在TI官⽅的F2837xD⽂档上⾯可以看到如下配置捕获引脚的说明(P1955):
F2837xD配置捕获输⼊的GPIO⼝的程序就两⾏:
若想进⼀步了解X-BAR,参考上⾯提到的⽂档P1151页。
attack是什么意思详细代码
/*
* ecap.c
*
* Created on: 2018年12⽉14⽇
* Author: multimicro
*/
#include "project.h"
aunt怎么读
void InitECapture()
{
InitECapture1();
InitECapture2();
InitECapture3();
}
void InitECapture1()
{
ECap1Regs.ECEINT.all = 0x0000; // Disable all capture interrupts
ECap1Regs.ECCLR.all = 0xFFFF; // Clear all CAP interrupt flags
ECap1Regs.ECCTL1.bit.CAPLDEN = 0; // Disable CAP1-CAP4 register loads
ECap1Regs.ECCTL2.bit.TSCTRSTOP = 0; // Make sure the counter is stopped
// Configure peripheral registers
ECap1Regs.ECCTL2.bit.CONT_ONESHT = 1; // 单次模式
ECap1Regs.ECCTL2.bit.STOP_WRAP = 3; // Stop at 4 events
ECap1Regs.ECCTL2.bit.SWSYNC = 1; //同步所有的Ecap时钟
//以下CAP1POL是配置捕获单元的极性
/*
* ____ ____ ____
* | | | | | |
* ____| |____| |____| |____
* ↑↓↑↓
* A B C D
* */
ECap1Regs.ECCTL1.bit.CAP1POL = 0; // Rising edge 0
ECap1Regs.ECCTL1.bit.CAP2POL = 1; // Falling edge 1
ECap1Regs.ECCTL1.bit.CAP3POL = 0; // Rising edge 0
ECap1Regs.ECCTL1.bit.CAP4POL = 1; // Falling edge 1
ECap1Regs.ECCTL1.bit.CTRRST1 = 0; // 完成此次捕获后不重置计数器
ECap1Regs.ECCTL1.bit.CTRRST2 = 0; // 完成此次捕获后不重置计数器
ECap1Regs.ECCTL1.bit.CTRRST3 = 0; // 完成此次捕获后不重置计数器
ECap1Regs.ECCTL1.bit.CTRRST4 = 1; // 完成此次捕获后重置计数器
ECap1Regs.ECCTL2.bit.SYNCI_EN = 1; // Enable sync in
ECap1Regs.ECCTL2.bit.SYNCO_SEL = 0; // Pass through
ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // Enable capture units
ECap1Regs.ECCTL2.bit.CAP_APWM = 0; //⼯作在CAP捕获模式
ECap1Regs.ECCTL2.bit.REARM = 1; // arm one-shot
ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // Enable CAP1-CAP4 register loads // ECap1Regs.ECEINT.bit.CEVT4 = 1; // 4 events = interrupt
// ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // Start Counter
}
void InitECapture2()
{
ECap2Regs.ECEINT.all = 0x0000; // Disable all capture interrupts
ECap2Regs.ECCLR.all = 0xFFFF; // Clear all CAP interrupt flags
ECap2Regs.ECCTL1.bit.CAPLDEN = 0; // Disable CAP1-CAP4 register loads ECap2Regs.ECCTL2.bit.TSCTRSTOP = 0; // Make sure the counter is stopped
// Configure peripheral registers
ECap2Regs.ECCTL2.bit.CONT_ONESHT = 1; // 单次模式
ECap2Regs.ECCTL2.bit.STOP_WRAP = 3; // Stop at 4 events
ECap2Regs.ECCTL2.bit.SWSYNC = 1; //同步所有的Ecap时钟
//以下CAP2POL是配置捕获单元的极性
/*
* ____ ____ ____
* | | | | | |
* ____| |____| |____| |____
* ↑↓↑↓
* A B C D
*
* */
ECap2Regs.ECCTL1.bit.CAP1POL = 0; // Rising edge 0
ECap2Regs.ECCTL1.bit.CAP2POL = 1; // Falling edge 1
ECap2Regs.ECCTL1.bit.CAP3POL = 0; // Rising edge 0
ECap2Regs.ECCTL1.bit.CAP4POL = 1; // Falling edge 1
ECap2Regs.ECCTL1.bit.CTRRST1 = 0; // 完成此次捕获后不重置计数器
ECap2Regs.ECCTL1.bit.CTRRST2 = 0; // 完成此次捕获后不重置计数器
ECap2Regs.ECCTL1.bit.CTRRST3 = 0; // 完成此次捕获后不重置计数器
ECap2Regs.ECCTL1.bit.CTRRST4 = 1; // 完成此次捕获后重置计数器
ECap2Regs.ECCTL2.bit.SYNCI_EN = 1; // Enable sync in
ECap2Regs.ECCTL2.bit.SYNCO_SEL = 0; // Pass through
ECap2Regs.ECCTL1.bit.CAPLDEN = 1; // Enable capture units
ECap2Regs.ECCTL2.bit.CAP_APWM = 0; //⼯作在CAP捕获模式
ECap2Regs.ECCTL2.bit.REARM = 1; // arm one-shot
ECap2Regs.ECCTL1.bit.CAPLDEN = 1; // Enable CAP1-CAP4 register loads // ECap2Regs.ECEINT.bit.CEVT4 = 1; // 4 events = interrupt
// ECap2Regs.ECCTL2.bit.TSCTRSTOP = 1; // Start Counter
}
靠岸
void InitECapture3()
ECap3Regs.ECEINT.all = 0x0000; // Disable all capture interrupts
ECap3Regs.ECCLR.all = 0xFFFF; // Clear all CAP interrupt flags
ECap3Regs.ECCTL1.bit.CAPLDEN = 0; // Disable CAP1-CAP4 register loads
ECap3Regs.ECCTL2.bit.TSCTRSTOP = 0; // Make sure the counter is stopped
// Configure peripheral registers
ECap3Regs.ECCTL2.bit.CONT_ONESHT = 0; // 连续模式
ECap3Regs.ECCTL2.bit.STOP_WRAP = 1; // Stop at 2 events
ECap3Regs.ECCTL2.bit.SWSYNC = 1; //同步所有的Ecap时钟
//以下CAP3POL是配置捕获单元的极性
/*
* ________
* | |
* _____| |________________________
* ↑↓
* A B
*
* */
ECap3Regs.ECCTL1.bit.CAP1POL = 0; // Rising edge 0
ECap3Regs.ECCTL1.bit.CAP2POL = 1; // Falling edge 1
ECap3Regs.ECCTL1.bit.CTRRST1 = 0; // 完成此次捕获后不重置计数器
ECap3Regs.ECCTL1.bit.CTRRST2 = 1; // 完成此次捕获后重置计数器dandelion是什么软件
ECap3Regs.ECCTL2.bit.SYNCI_EN = 1; // Enable sync in
ECap3Regs.ECCTL2.bit.SYNCO_SEL = 0; // Pass through
ECap3Regs.ECCTL1.bit.CAPLDEN = 1; // Enable capture units3g什么意思
ECap3Regs.ECCTL2.bit.CAP_APWM = 0; //⼯作在CAP捕获模式
ECap3Regs.ECCTL2.bit.REARM = 1; // arm one-shot
ECap3Regs.ECCTL1.bit.CAPLDEN = 1; // Enable CAP1-CAP4 register loads
ECap3Regs.ECEINT.bit.CEVT2 = 1; // 2 events = interrupt
ECap3Regs.ECCTL2.bit.TSCTRSTOP = 1; // Start Counter
赋闲的意思}
/*******************************************************************************************************
* Ecap 的基准时钟在150MHz的主频下约为6.67ns
* 也就是说每过6.67ns ECap1Regs.CAPx的值就会递增1,通过CAP1和CAP3的时间差可以计算出速度
*******************************************************************************************************
* 1. 该 E6B2-CWZ6C 的分辨率为 1000 P/R 即改编码器每转⼀圈,固定输出1000个脉冲
* 2. 若1s内转⼀圈,则每个脉冲的周期为: 1s/1000 = 1ms (下图中A→C的时间 , 从 A → C 为⼀个完整的脉冲)
* 3. 由 E6B2-CWZ6C 技术⽂档可知,输出⼀共有三相A、B、Z相输出,其中Z相为同步相
* 4. 计算转速时只需要A相或者B相⼀个即可。但计算转动⽅向时,需要配合A相和B相,必须⽤到Z相,下⾯会解释 *
* ____ ____ ____ ____
the gift
* | | | | | | |
* |____| |____| |____| |____
* ↓↑↓↑
* A B C D
*
* 当 A 事件(捕获第⼀个下降沿)发⽣时 Ecap模块把当前时间记录在 ECap1Regs.CAP1中
* 当 B 事件(捕获第⼀个上升沿)发⽣时 Ecap模块把当前时间记录在 ECap1Regs.CAP2中
* 当 C 事件(捕获第⼆个下降沿)发⽣时 Ecap模块把当前时间记录在 ECap1Regs.CAP3中
* 当 D 事件(捕获第⼆个上升沿)发⽣时 Ecap模块把当前时间记录在 ECap1Regs.CAP4中
*******************************************************************************************************
* 下⾯说明⼀下正转和反转时的三相输出波形
in the groove
*
* 捕获器1和2配置的
*
* 1. 正转(forward)
* _____ _____ _____
* A | | | | | |
* _____| |_____| |_____| |_____...
* ↑↓↑↓
* A1 B1 C1 D1
*
* 以下变量可在函数中查看
* A1: Ecap1_TS1
* C1: Ecap1_TS3
* _____ _____ _____
* B | | | | | |
* _______| |_____| |_____| |_____...
* ↑↓↑↓
* A2 B2 C2 D2
*
* 以下变量可在函数中查看
* A2: Ecap2_TS1
* B2: Ecap2_TS2
*
* ___________
* Z | |
* _____| |____________________________...
* ↑↓
* A3 B3
*
* 没⽤到Ecap3的计数寄存器
*
* 2. 反转(backward)
* 标注见上
* _____ _____ _____
* A | | | | | |
* _____| |_____| |_____| |_____...
* ↑↓↑↓
* A1 B1 C1 D1
* _____ _____ _____
* B | | | | | |
* ____| |_____| |_____| |_____...
* ↑↓↑↓
* A2 B2 C2 D2
* ___________
* Z | |
* _____| |____________________________
* ↑↓
* A3 B3
*
*
* 需要注意,此种状态捕获模块捕获 B 相的上升沿如上图所⽰,⽽不是同步信号到来时的第⼀个上升沿
* 应该是因为延时的原因,不影响测向。
*
* 同步相到来时,才会启动捕获模块1和2来捕获A相和B相的脉冲,捕获器完成⼀次捕获事件后就停⽌⼯作
* 等待下⼀次的同步信号再⼀次启动捕获
*/
accountant
__interrupt void ecap1_isr(void)
{
// 参考链接:blog.csdn/chenjiayu938/article/details/81349866
ecap1_count = (++ ecap1_count) % 5;
Ecap1_TS1 = ECap1Regs.CAP1;
Ecap1_TS3 = ECap1Regs.CAP3;
calc_pul = Ecap1_TS3 - Ecap1_TS1;
// calc_time unit is millconds
// 因为计数器每6.67ns递增⼀次,所以 ( ⼀个脉冲时间间隔内的计数器数值 ÷ 6.67 ) 就是⼀个脉冲持续的时间(ns),然后在除以1000000就换算得到ms
// 此编码器的分辨率为 1000 P/R 转⼀圈固定输出1000个脉冲,1s转⼀圈输出的脉冲周期为1ms,因此可⽤ ( 1(ms) / 当前的脉冲周期(ms) ) 来求得转速(r/s )
calc_time = calc_pul * 667.0 / 100.0 / 1000000.0;