This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F28377S:eQEP,tms320f28377s 编码器

Guru**** 2394295 points
Other Parts Discussed in Thread: C2000WARE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1292721/tms320f28377s-eqep-encoder-for-tms320f28377s

器件型号:TMS320F28377S
主题中讨论的其他器件:C2000WARE

您能解释一下 eQEP 的 GPIO 初始化问题吗?因为 POSITION_NOW 未得到更新,我已经对它进行了调试,但无法找到速度。

#include "F28x_Project.h"
#include "math.h"
#define SYS_CLK 200000000
#define PI 3.14159265358979323846
void Setup_GPIO();
void initEQEP();
void InitEQep1Gpio();
void delay_loop ();
uint16_t value1 = 0;
uint16_t value2 = 0;
uint16_t 值3 = 0;
uint16_t 值4 = 0;

int spcnt = 0;
浮点 wr_mech = 0;
浮动 RAD_PER_COUNT = 0.000785;//编码器每转脉冲数
浮点 lPrevPos = 0;
float lNowPos = 0;
INT B=0;
浮点 lDifference = 0;
// uint32_t pulseCount = 0;

外部中断 void cpu_timer0_isr (void);
INT A=0;
空 main (void)
{
//初始化系统时钟、GPIO 和其它必要外设

//初始化 eQEP 模块
InitGpio();
//编码器
// GPIO_SetupPinMux (105、GPIO_MUX_CPU1、0);
// GPIO_SetupPinOptions (105、GPIO_output、GPIO_PushPull);
// GpioDataRegs.GPDSET.bit.GPIO105 = 1;

initEQEP();
InitSysCtrl();
// InitEQep1Gpio();
Dint;

//设置 ADC 以进行软件转换

InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EALLOW;
PieVectTable.TIMER0_INT =&CPU_timer0_ISR;
EDIS;
InitCpuTimers ();
ConfigCpuTimer (&CpuTimer 0,200,100);
CpuTimer0Regs.tcr.all = 0x4000;
IER |= M_INT1;
IER |= M_INT3;
PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
EINT;
ERTM;
while (1)
{



浮点读编码器()
{
浮动 position_now;
position_now = EQep1Regs.QPOSCNT;
立即返回 position_now;

void InitEQep1Gpio()
//{
///// Page 959 Table Mux,第965页寄存器和 spruhm8i.pdf -技术参考
EALLOW;
//
// GpioCtrlRegs.GPAMUX1.all = 0;
// GpioCtrlRegs.GPAMUX2.all = 0;
// GpioCtrlRegs.GPAPUD.bit.GPIO20 = 1;//禁用 GPIO10上的上拉电阻(EQEP1A)
// GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0;//将 GPIO10同步到 SYSCLK (EQEP1A)
GpioCtrlRegs.GPAGMUX2.bit.GPIO20 = 1;//将 GPIO6配置为 EQEP1A
// GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 1;//将 GPIO6配置为 EQEP1A
////
// GpioCtrlRegs.GPAPUD.bit.GPIO21 = 1;//禁用 GPIO7上的上拉电阻(EQEP1B)
// GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0;//将 GPIO7同步到 SYSCLK (EQEP1B)
GpioCtrlRegs.GPAGMUX2.bit.GPIO21= 1;//将 GPIO7配置为 EQEP1B
// GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 1;//将 GPIO7配置为 EQEP1B
////
// GpioCtrlRegs.GPAPUD.bit.GPIO22 = 1;//禁用 GPIO7上的上拉电阻(EQEP1B)
// GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 0;//将 GPIO7同步到 SYSCLK (EQEP1B)
GpioCtrlRegs.GPAGMUX2.bit.GPIO22= 1;//将 GPIO7配置为 EQEP1B
// GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 1;//将 GPIO7配置为 EQEP1B
////
// GpioCtrlRegs.GPAPUD.bit.GPIO23 = 1;//禁用 GPIO9上的上拉电阻(EQEP1I)
// GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 0;//将 GPIO9同步到 SYSCLK (EQEP1I)
GpioCtrlRegs.GPAGMUX2.bit.GPIO23 = 1;//将 GPIO9配置为 EQEP1I
// GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 1;//将 GPIO9配置为 EQEP1I
// EDIS;
//
//
//启用所选引脚的内部上拉。

GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0;//启用 GPIO20上拉(EQEP1A)
GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0;//启用 GPIO21上的上拉(EQEP1B)
GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0;//启用 GPIO22上的上拉(EQEP1S)
GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0;//启用 GPIO23上的上拉(EQEP1I)

//输入默认与 SYSCLKOUT 同步。

GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0;//同步到 SYSCLKOUT GPIO20 (EQEP1A)
GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0;//同步到 SYSCLKOUT GPIO21 (EQEP1B)
GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 0;//同步到 SYSCLKOUT GPIO22 (EQEP1S)
GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 0;//同步到 SYSCLKOUT GPIO23 (EQEP1I)

//使用 GPIO 寄存器配置 eQEP-1引脚
GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 1;//将 GPIO20配置为 EQEP1A
GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 1;//将 GPIO21配置为 EQEP1B
GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 1;//将 GPIO22配置为 EQEP1S
GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 1;//将 GPIO23配置为 EQEP1I
// value1 = GpioDataRegs.GPADAT.bit.GPIO20;
// value2= GpioDataRegs.gpadat.bit.gpio21;
// value3 = GpioDataRegs.gpadat.bit.gpio22;
// value4 = GpioDataRegs.gpadat.bit.gpio23;

EDIS;

//

void initEQEP()
{
// CPUSysRegs.PCLKCR4.bit.EQEP1ENCLK = 1;
EQep1Regs.QUPRD = SYS_CLK;// 100Hz 频率的单位计时器周期(任意、根据需要调整)
EQep1Regs.QDECCTL.bit.QSRC = 1;//正交方向计数模式
// EQep1Regs.QDECCTL.bit.QSP = 0;// 1x 分辨率(默认值)
EQep1Regs.QEPCTL.bit.FREE_SOFT = 2;//针对仿真挂起运行
EQep1Regs.QDECCTL.bit.XCR = 0;// 0表示上升沿/下降沿。 1仅对于上升沿、XCR = 1x 分辨率
// EQep1Regs.QDECCTL.bit.swap = 1;// 0表示无变化。 1表示交换 A 和 B。

EQep1Regs.QEPCTL.bit.PCRM = 2;//位置计数器复位0表示索引时复位,1表示最大复位一次,
//第一个索引上的2平均复位,单元时间事件上的3平均复位
EQep1Regs.QEPCTL.bit.QCLM = 1;//锁存单元超时
EQep1Regs.QEPCTL.bit.UTE = 1;
//单位定时器启用
EQep1Regs.QPOSIIT = 0;
EQep1Regs.QPOSMAX = 0xFFFFFFFF;//所需的最大计数
EQep1Regs.QEPCTL.bit.QPEN = 1;// QEP enable

EQep1Regs.QCAPCTL.bit.UPPS = 5;// 1/32表示单元位置
EQep1Regs.QCAPCTL.bit.CCP = 6;// CAP 时钟为1/64
EQep1Regs.QCAPCTL.bit.CEN = 1;// QEP 捕获启用

//void dalcSpeed (float lEncCount)
//{
//
// wr_mech = lEncCount*RAD_PER_COUNT/(10);

外部中断 void cpu_timer0_isr ()
{
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
lNowPos = ReadEncoder();
A+;
SPCNT++;
if (spcn>9)
{B++;
lDifference = lNowPos - lPrevPos;
wr_mech = lDifference *RAD_PER_COUNT*1000;
lPrevPos = lNowPos;
spcnt = 0;

// pulseCount = EQep1Regs.QPOSCNT;//读取脉冲计数
// motorSpeed = pulseCount * 60 * SYS_CLK /(ENCODER_PPR * EQep1Regs.QPOSCNT);//以 RPM 计算电机转速

//必要时清除中断标志
// EQep1Regs.QCLR.bit.UTO = 1;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Swapnil:

    您是否要从我们的 C2000Ware 示例开始? 我们有几个用 RPM 计算速度测量的示例。 这些示例可在我们的 C2000Ware SDK 中找到、位置为 C:\ti\c2000\C2000Ware_x_xx_xx\device_support\f2837xs+示例\cpu1\eQEP_pos_speed\cpu01\eQEP_pos_speed.c

    有关 GPIO 设置、请参阅这些。

    此致!

    马瑞安

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复 Ryan Ma、

    我已经尝试了 eQEP_posspeed 示例、根据我的要求进行了更改程序甚至正在构建、但仍然没有输出、尽管我已删除 EPWM 部分、因为我不需要对信号进行仿真。我已发布了代码您可以看看并获取 返回给我

    //
    #include "F28x_Project.h"
    #include "example_posspeed.h"
    INT 采样时间= 100;
    //

    //
    //全局变量
    //
    POSIPEED QEP_POSTEP=POSIPEED_DEFAULTS;
    UINT16 Interrupt_Count = 0;

    //
    //函数原型
    //
    //void initEpwm();
    中断失效 Timer1_ISR (void);

    //
    //主菜单
    //
    空 main (void)
    {
    //
    //步骤1. 初始化系统控制:
    // PLL、看门狗、启用外设时钟
    //该示例函数位于 F2837xS_SYSCTRL.c 文件中。
    //
    InitSysCtrl();

    //
    //步骤2. 初始化 GPIO:
    //此示例函数可在 F2837xS_GPIO.c 文件中找到,
    //说明了如何将 GPIO 设置为默认状态。
    //
    // InitGpio();//跳过此示例

    //
    //在本例中,仅为 eQEP1和 ePWM1初始化 GPIO
    //此函数位于 F2837xS_eQEP.c 中
    //
    InitEQep1Gpio;
    // InitEPwm1Gpio();
    EALLOW;
    GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;// GPIO4作为输出模拟索引信号
    GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;//通常为低电平
    EDIS;

    //
    //步骤3. 清除所有_interrupts 并初始化 PIE 矢量表:
    //禁用 CPU __interrupts
    //
    Dint;

    //
    //将 PIE 控制寄存器初始化为默认状态。
    //默认状态是禁用所有 PIE _interrupts 并设置标志
    //被清除。
    //此函数位于 F2837xS_PIECTRL.c 文件中。
    //
    InitPieCtrl();

    //
    //禁用 CPU _interrupts 并清除所有 CPU _interrupt 标志:
    //
    IER = 0x0000;
    IFR = 0x0000;

    //
    //使用指向 shell 中断的指针初始化 PIE 矢量表
    //服务例程(ISR)。
    //这将填充整个表,即使__interrupt
    //在本例中未使用。 这对于调试十分有用。
    //在 F2837xS_DefaultIsr.c 中找到 shell ISR 例程。
    //此函数可以在 F2837xS_PieVect.c 中找到。
    //
    InitPieVectTable();

    //
    //此示例中使用的中断被重新映射到
    //此文件中的 ISR 函数。
    //
    EALLOW;//需要执行此操作才能写入 EALLOW 保护的寄存器
    PieVectTable.Timer1_INT =&Timer1_ISR;
    EDIS;//这是禁用对 EALLOW 保护寄存器的写入所必需的
    InitCpuTimers ();
    ConfigCpuTimer (&CpuTimer1200、采样时间);
    CpuTimer1Regs.tcr.all = 0x4000;
    //
    //步骤4. 初始化所有器件外设:
    //
    //initEpwm ();//此函数存在于 Example_EPwmSetup.c 中

    //
    //步骤5. 用户特定代码、启用_interrupts:
    //启用连接到 CPU 计时器的 CPU INT1 0:
    //
    IER |= M_INT3;

    //
    //在 PIE 中启用 TINT0:组3 _interrupt 1
    //
    PieCtrlRegs.PIEIER3.bit.INTx1 = 1;

    //
    //启用全局中断和更高优先级的实时调试事件:
    //
    EINT;//启用全局_interrupt INTM
    ERTM;//启用全局实时__interrupt DBGM

    qep_posspeed.init(&qep_posspeed);

    for (;;)
    {


    void InitEQep1Gpio()
    {


    GpioCtrlRegs.GPAPUD.bit.GPIO20 = 0;//启用 GPIO20上的上拉
    GpioCtrlRegs.GPAPUD.bit.GPIO21 = 0;//启用 GPIO21上的上拉
    GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0;//启用 GPIO22上的上拉
    GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0;//启用 GPIO23上的上拉
    GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0;//同步到 SYSCLKOUT
    GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0;//同步到 SYSCLKOUT
    GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 0;//同步到 SYSCLKOUT
    GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 0;//同步到 SYSCLKOUT
    GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 1;// GPIO20 = EQEP1A
    GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 1;// GPIO21 = EQEP1B
    GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 1;// GPIO22 = EQEP1S
    GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 1;// GPIO23 = EQEP1I
    EDIS;

    //
    // prdTick - EPWM1每4个 QCLK 计数一次(一个周期)
    //
    void POSSPEED_Init (void)
    {
    EQep1Regs.QUPRD = 2000000;// 200 MHz 上100Hz 的单位定时器
    // SYSCLKOUT
    EQep1Regs.QDECCTL.bit.QSRC = 00;// QEP 正交计数模式
    EQep1Regs.QEPCTL.bit.FREE_SOFT = 2;
    EQep1Regs.QEPCTL.bit.PCRM = 00;// PCRM=00 MODE - QPOSCNT 复位开启
    //索引事件
    EQep1Regs.QEPCTL.bit.UTE = 1;//单元超时启用
    EQep1Regs.QEPCTL.bit.QCLM = 1;//锁存单元超时
    EQep1Regs.QPOSMAX = 0xffffffff;
    EQep1Regs.QEPCTL.bit.QPEN = 1;// QEP enable
    EQep1Regs.QCAPCTL.bit.UPPS = 5;// 1/32表示单元位置
    EQep1Regs.QCAPCTL.bit.CCP = 6;// CAP 时钟为1/64
    EQep1Regs.QCAPCTL.bit.CEN = 1;// QEP 捕捉启用

    //
    // POSSPEED_CALC -执行位置计算
    //
    void POSSPEED_CALC (POSSPEED *p)
    {
    长 tmp;
    unsigned int pos16bval;
    _iq Tmp1、newp、oldp;

    //
    //位置计算-机械和电机角度
    //
    p->DirectionQep = EQep1Regs.QEPSTS.bit.QDF;//电机方向:
    // 0=逆时针/反向,1=CW/正向

    pos16bval =(unsigned int) EQep1Regs.QPOSCNT;//捕获一次位置
    //每个 QA/QB 周期
    p->theta_raw = pos16bval+ p->cal_angle;//原始 theta =当前位置。 +
    //变化。 偏离 QA 的偏移量

    //
    //下面的行计算
    // p->theta_mech ~= QPOSCNT/mech_scaler [当前 cnt/(1版本中的总计 cnt)]
    //其中 mech_scaler = 4000 cnts/转
    //
    tmp =(long)((long) p->theta_raw*(long) p->mech_scaler);// Q0*Q26 = Q26
    tmp &= 0x03FFF000;
    p->theta_mech =(int)(tmp>>11);// Q26 -> Q15
    p->theta_mech &= 0x7FFF;

    //
    //下面的行计算 p->elec_mech
    //
    p->theta_elec = p->pole_pairs*p->theta_mech;// Q0*Q15 = Q15
    p->theta_elec &= 0x7FFF;

    //
    //检查出现的索引
    //
    if (EQep1Regs.QFLG.bit.IEL == 1)
    {
    p->index_sync_flag = 0x00F0;
    EQep1Regs.QCLR.bit.IEL = 1;//清除_INTERRUPT 标志

    //
    //使用 QEP 位置计数器进行高速计算
    //
    //检查用于速度计算的单位超时事件:
    //在 INIT 函数中将单位计时器配置为100Hz
    //
    if (EQep1Regs.QFLG.bit.UTO = 1)//如果单位超时(一个100Hz 周期)
    {
    //
    //微分器
    //
    //下面的行计算
    // Position =(x2-x1)/4000 (旋转1周的位置)
    //
    pos16bval =(unsigned int) EQep1Regs.QPOSLAT;//锁存的 POSCNT 值
    tmp =(long)((long) pos16bval*(long) p->mech_scaler);// Q0* Q26 = Q26
    tmp &= 0x03FFF000;
    tmp =(int)(tmp>>11);// Q26 -> Q15
    Tmp &= 0x7FFF;
    newp =_IQ15toIQ (tmp);
    oldp = p->oldpos;

    if (p->DirectionQep=0)// POSCNT 正递减计数
    {
    if (newp>oldp)
    {
    Tmp1 =-(_iq (1)- newp + oldp);// x2-x1应该为负

    否则
    {
    Tmp1 = newp -oldp;


    否则、如果(p->DirectionQep == 1)// POSCNT 正递增计数
    {
    if (newp<oldp)
    {
    Tmp1 =_iq (1)+ newp - oldp;

    否则
    {
    Tmp1 = newp - oldp;// x2-x1应该是正数

    if (Tmp1>_IQ (1))
    {
    p->Speed_fr =_iq (1);

    否则为(Tmp1<_IQ (-1))
    {
    p->Speed_fr =_iq (-1);

    否则
    {
    p->Speed_fr = Tmp1;

    //
    //更新电角
    //
    p->oldpos = newp;

    //
    //将电机转速从 pu 值更改为 rpm 值(Q15 -> Q0)
    // Q0 = Q0* GLOBAL_Q =>_IQXmpy (),X = GLOBAL_Q
    //
    p->SpeedRpm_fr =_IQmpy (p->BaseRpm、p->Speed_fr);

    EQep1Regs.QCLR.bit.UTO=1;//清除_INTERRUPT 标志

    //
    //使用 QEP 捕获计数器进行低速计算
    //
    // if (EQep1Regs.QEPSTS.bit.UPEVNT == 1)//单元位置事件
    //{
    // if (EQep1Regs.QEPSTS.bit.COEF =>= 0)//无捕捉溢出
    //{
    // temp1 =(unsigned long) EQep1Regs.QCPRDLAT;// temp1 = T2-T1
    //}
    // else //捕获溢出,使结果饱和
    //{
    // temp1 = 0xFFFF;
    //}
    //
    ////
    //// p->Speed_pr = p->SpeedScale/temp1
    ////
    // p->Speed_pr =_IQdiv (p->SpeedScaler, temp1);
    // Tmp1 = p->Speed_pr;
    //
    // if (Tmp1>_IQ (1))
    //{
    // p->Speed_pr =_iq (1);
    //}
    //其他
    //{
    // p->Speed_pr = Tmp1;
    //}
    //
    ////
    ////将 p->Speed_pr 转换为 RPM
    ////
    // if (p->DirectionQep == 0)//反向=负
    //{
    ////
    //// Q0 = Q0* GLOBAL_Q =>_IQXmpy (),X = GLOBAL_Q
    ////
    // p->SpeedRPM_pr =-_IQmpy (p->BaseRpm、p->Speed_pr);
    //}
    // else //前进方向=正
    //{
    ////
    //// Q0 = Q0* GLOBAL_Q =>_IQXmpy (),X = GLOBAL_Q
    ////
    // p->SpeedRPM_pr =_IQmpy (p->BaseRpm、p->Speed_pr);
    //}

    EQep1Regs.QEPSTS.all = 0x88;//清除单元位置事件标志
    //清除溢出错误标志

    中断失效 Timer1_ISR (void)
    {PieCtrlRegs.PIEACK.all = PIEACK_Group3;
    UINT16 I;

    //
    //位置和速度测量
    //
    qep_posspeed.calc(&qep_posspeed);

    //
    //用于位置控制和速度控制的控制环路代码
    //
    Interrupt_Count ++;

    //
    //每1000个__interrupts (4000 QCLK 计数或1个版本)
    //
    如果(Interrupt_Count == 1000)
    {
    EALLOW;
    GpioDataRegs.GPASET.bit.GPIO4 = 1;//脉冲索引信号(1个脉冲/修订版本)
    对于(I=0;I<700;I++)
    {

    GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;
    Interrupt_Count = 0;//复位计数
    EDIS;

    //
    //确认此_interrupt 以接收来自组1的更多_interrupts
    //

    // EPwm1Regs.ETCLR.bit.INT=1;

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    该示例是否按您的预期工作?  ePWM 仿真信号是否与 eQEP 一起工作? 如果这起作用、那么进入 GPIO 的输入信号肯定会有一些问题。

    如果可以使用该示例、您是否能够将您的信号连接到相同的 GPIO、而不是将 EPWM 信号传递到 eQEP 输入?

    此致!

    马瑞安