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.
工具/软件:Code Composer Studio
您好!
我的软件示例有问题:
eQEP_pos_speed_CPU1 (V210、但尝试使用不同版本)
我尝试使用该示例来使用 TI 2-MTR-DYNO 封装的编码器。 eQEP1A 和 eQEP1B 已正确注册、但是在任何情况下、QEP1I 都不会注册。 我尝试了:
-将 GPIO 引脚4连接到 EQEP1I 引脚以仿真索引脉冲
-将编码器直接连接到引脚接头
-将3.3V 电压直接连接到 EQEP1I 引脚以强制进行索引检测
这些似乎都不起作用、因此一旦 theta_raw 溢出、它就会产生一个错误的 theta_mech 生成、从而使编码器无用。
有关我的设置的信息:
- Code Composer 10.0
-编译器 TI v20.2.1.LTS
提前感谢您的帮助!
您好、Rick、
您是否将 GPIO4用作 EQEP1I? 如果您查看数据表、GPIO4没有连接到 eQEP Index 引脚。
您可以将 GPIO13与多路复用器选项5结合使用。
此致、
Nirav
Nirav、您好!
我不使用 GPIO4作为 EqepI、而是从外部将其连接到 eqep1引脚接头的 eqep1I 引脚。 (示例中也建议这样)由于我尝试了不同的方法来创建索引脉冲(并使用示波器进行测量以验证是否生成了 DE 脉冲)、我假设该脉冲是由 DE 控制器记录的 NOG、但我不知道导致此情况的原因是什么。
如果我列出负责处理中断的代码:
//检查索引出现 // if (EQep1Regs.QDLG.bit.IEL =1) { p->index_SYNC_FLAG = 0x00F0; EQep1Regs.QCLR.bit.IEL = 1;//清除__interrupt 标志 }
当我在这个代码内放置一个断点时、即使一个外部索引脉冲被应用于 GPIO23、它也不会达到。 (也在 e2e.ti.com/.../634607 中讨论)
更新:
设置:
我已经对 C2000Ware 示例进行了同样的尝试、它仍然无法检测到索引脉冲。 我已经使用示波器进行检查、EQEPI 引脚确实会接收到一个索引脉冲。 还有什么可以检查的吗?
此致、
Rick
您好!
当前工作范围 I 的实现方式是将 QPOSMAX 设置为4000、这与编码器的分辨率相同、但是、这不是一个合适的解决方案、因为它不使用索引信号来缓解任何计数错误。 我仍在尝试解决索引脉冲未注册的问题。 有关 GPIO 和 EqepRegs 设置的一些额外信息:(与更改最大 QPOSCNT 的示例相同)
文件:F2837xD_eQEP.c (系统文件) void InitEQep1Gpio (void) { EALLOW; // //禁用所选输出引脚的内部上拉 //以降低功耗 //用户可以启用或禁用上拉。 //注释掉其他不需要的行。 GpioCtrlRegs.GPAPUD.bit.GPIO20 = 1;//禁用 GPIO20上的上拉电阻(EQEP1A) GpioCtrlRegs.GPAPUD.bit.GPIO21 = 1;//禁用 GPIO21上的上拉电阻(EQEP1B) GpioCtrlRegs.GPAPUD.bit.GPIO22 = 1;//禁用 GPIO22上的上拉电阻(EQEP1S) GpioCtrlRegs.GPAPUD.bit.GPIO23 = 1;//禁用 GPIO23上的上拉电阻(EQEP1I) // //将输入同步到 SYSCLK //同步可由用户启用或禁用。 //注释掉其他不需要的行。 // GpioCtrlRegs.GPAQSEL2.bit.GPIO20 = 0;//将 GPIO20与 SYSCLK 同步(EQEP1A) GpioCtrlRegs.GPAQSEL2.bit.GPIO21 = 0;//将 GPIO21同步到 SYSCLK (EQEP1B) GpioCtrlRegs.GPAQSEL2.bit.GPIO22 = 0;//将 GPIO22同步到 SYSCLK (EQEP1S) GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 0;//将 GPIO23同步到 SYSCLK (EQEP1I) // //使用 GPIO 寄存器配置 eQEP-1引脚 //这指定哪些可能的 GPIO 引脚将是 EQEP1功能 //引脚。 //注释掉其他不需要的行。 // 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; } 文件:posspeed_example (示例 c2000Ware) // // POSISPEED_Init -初始化 EQEP1配置 // void Encoder_Init (void) { EQep1Regs.QUPRD = 2000000; //频率为200MHz 时频率为100Hz 的单位定时器 // SYSCLKOUT EQep1Regs.QDECCTL.bit.QSRC = 00; // QEP 正交计数模式 EQep1Regs.QEPCTL.bit.free_soft = 2; EQep1Regs.QEPCTL.bit.PCRM = 00; // PCRM=00模式- QPOSCNT 复位打开 //索引事件 EQep1Regs.QEPCTL.bit.UTE = 1; //设备超时启用 EQep1Regs.QEPCTL.bit.QCLM = 1; //锁存装置超时 EQep1Regs.QPOSMAX = 0xFA0; EQep1Regs.QEPCTL.bit.QPEN = 1; // QEP 使能 EQep1Regs.QCAPCTL.bit.UPP=5; // 1/32表示单元位置 EQep1Regs.QCAPCTL.bit.CCPS = 6; 对于 CAP 时钟、为//1/64 EQep1Regs.QCAPCTL.bit.CEN = 1; // QEP 捕捉使能 } // POSISPEED_CALC -执行位置计算 // void Encoder_Update (EncoderState *p) { 长温度; unsigned int pos16bval、temp1; _iq Tmp1、newp、oldp; // //位置计算-机械和电动机角度 // P->DirectionQep = EQep1Regs.QEPSTS.bit.QDF;//电机方向: // 0 = CCV/反向,1 = CW/正向 pos16bval =(unsigned int) EQep1Regs.QPOSCNT;//捕捉位置一次 //每个 QA/QB 周期 p->theta_raw = pos16bval+ p->cal_angle; //原始 θ=当前位置。 + //对。 来自 QA 的偏移 if (p->theta_raw > 4000){ p->theta_ray=p->theta_ray-4000; } 否则为(p->theta_raw <-4000){ p->theta_ray=p->theta_ray+4000; } // //下面的行计算 // p->theta_mech ~= QPOSCNT/mech_scaler [当前 cnt/(1修订版中的总 cnt)] //其中 mech_scaler = 4000 cnts/Revolution // tmp =(long)(((long) p->theta_ray*(long) p->mech_scaler);// q0*Q26 = Q26 tmp &= 0x03FFF000; p->theta_mech =(int)(Tmp>>11); //Q26 -> Q15 p->theta_mech &= 0x7FFF; p->th_rad =2*M_pi-((double) p->theta_mech/32765)*2*M_pi; p->th_deg =360-(((double) p->theta_mech/32765)*360; if (p->th_deg<0){ p->th_deg=p->th_deg; } // //以下行计算 p->elec_mech // p->theta_elec = p->pole _pairs*p->theta_mech; // q0*q15 = q15 p->theta_elec &= 0x7FFF; // //检查索引出现情况 // if (EQep1Regs.QDL.bit.IEL = 1) { P->index_SYNC_FLAG = 0x00F0; EQep1Regs.QCLR.bit.IEL = 1;//清除__interrupt 标志 } // //使用 QEP 位置计数器进行高速计算 // //检查单位时间超时事件以计算速度: //初始化函数中的单位计时器配置为100Hz // if (EQep1Regs.QFLG.bit.UTO = 1)//如果单元超时(一个100Hz 周期) { // //微分器 // //下面的行计算 //位置=(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->oldp; if (p->DirectionQep=0) // POSCNT 正在递减计数 { if (newp>oldp) { Tmp1 =-(_IQ (1)- newp + oldp);// x2-x1应该为负 } 其他 { Tmp1 = newp -oldp; } } 否则,如果(p->DirectionQep=1) // POSCNT 正在递增计数 { if (newp _iq (1)) { P->Speed_fr =_IQ(1); } 否则、IF (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 =(无符号长整型) EQep1Regs.QCPRDLAT;// temp1 = T2-T1 } 否则//捕获溢出,使结果饱和 { TEMP1 = 0xFFFF; } // // p->Speed_pr = p->SpeedScaler/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); } 其他 //正向=正 { // // q0 = q0*global_Q =>_IQXmpy(),X = global_Q // P->SpeedRPM_pr =_IQmpy (p->BaseRpm、p->Speed_pr); } EQep1Regs.QEPSTS.ALL = 0x88;//清除单元位置事件标志 //清除溢出错误标志 } }
此致、
Rick
您好、Rick、
对延迟回复表示歉意。 您的所有配置看起来都很好、因此我尝试弄清您为什么看不到索引脉冲。 最后、我想我可能已经发现了问题。
由于您使用的是 Launchpad、因此必须将 QEP 信号连接到接头 J14 (eQEP1A、eQEP1B 和 eQEP1I)。 如果您浏览 Launchpad 的原理图、您会发现 eQEP1A 和 eQEP1B 分别连接到 GPIO20和 GPIO21、但 eQEP1I 连接到 GPIO99 (而非 GPIO23)。 因此、在您的代码中、您需要使用多路复用器选项5设置 GPIO99。
请尝试一下、如果您仍遇到任何问题、请告诉我。
此致、
Nirav
Nirav、您好!
这确实解决了问题! 谢谢! 下次我一定要仔细检查 Launchpad 的原理图!
此致、
Rick