主题中讨论的其他器件: controlSUITE、 TPS22918、 TIDM-1008
您好,
这是我第一次使用 TMS320F28379D 进行绝对编码器位置解码、 错误1在我的测试中报告1、并且位置值不正确。 代码从开发套件转换为 C:\ti\controlSUITE\development_kits\TMDSIDDK_v2.0\IDDK_PM_Servo_F2837x_v2_00_00_00、主代码如下:endat.c、主函数中的初始化文件和中断中的位置读取函数。 在我们的测试过程中、只能在 EnDat CLK1MHz 下正确获取位置、并注释 CRC 校验代码、并且在伺服电机驱动器的高压直流总线下会加载大型跳点。 遗憾的是、Heidaheen 编码器的连接线无意中损坏、修复后、我们无法获取正确的位置数据、并且按如下方式粘贴了 endat22Data。 理论上、POSITION _hi 应为零、POSITION _lo 也不正确。 我们已经检查了 CLK 和数据信号、它们看起来是正确的。 我们还排除了使用来自 Kollomogen 的伺服驱动器的编码器故障。 硬件电路从 TIDM1008传输。
这是 endat.c 文件。
///-------------------------------------- //文件: endat.c // //说明:包含所有初始化、数据声明和设置 // 用于 EnDat 编码器接口。 此文件服务是 //的模板 使用 PM_endat22库连接并整合所有编码 器// 特定于库的初始化以及其他重要的使用方面。 // //版本: 1.0 // //目标: TMS320F28377D, ////------------------------------------------------------- //版权所有德州仪器2004-2015 年----------------------------------------------- //修订历史记录: //--------------- //日期 |说明/状态 /------------------------------------------------------- //2015年11月4日- PM EnDAT 库使用情况示例项目 /------------------------------------------------------- #include "F28x_Project.h" //器件头文件和示例包括文件 #include "endat.h" uint16_t endat22CRCtable[SIZEOOF_ENDAT_CRCABLE];//声明 EnDat CRC 计算的 CRC 表 ENDAT_DATA_STRUT endat22Data; //PM EnDat22数据结构 uint16_t crc5_result;//计算得出的 CRC 结果检查 uint16_t retval1的变量; //用于函数返回 val 存储并检查 //函数初始化 EnDat 操作 void EnDat_Init (void){ EALLOW; //启用 PWM1/2/3/4的时钟 CpuSysRegs.PCLKCR2.bit.EPWM1 = 1; CpuSysRegs.PCLKCR2.bit.EPWM2 = 1; CpuSysRegs.PCLKCR2.bit.EPWM3 = 1; CpuSysRegs.PCLKCR2.bit.EPWM4= 1; EDIS; //将 EPWM4配置为驱动 GPIO6和 GPIO7上的默认值 EPWM4_Config (); //生成 EnDat 多项式的表,该表已被视为 POLY1 PM_endat22_generateCRCTable (NBITS_POLY1、POLY1、endat22CRCtable); 针对 ENDat 操作的/GPIO 配置 ENDat 设置 GPIO (); //针对 ENDat 操作的 XBAR 配置 endat_config_XBAR(); endat22Data.SPI = SpibRegs (SpibRegs); Pm_endat22_setupPeriph(); EALLOW; //此示例中使用的中断被重新映射到 这个文件中的// ISR 函数。 PieVectTable.SPIB_RX_INT =&spirxFifoIsr; PieCtrlRegs.PIECTRL.bit.ENPIE = 1;//启用 PIE 块 PieCtrlRegs.PIEIER6.bit.INTx3=1; //启用 PIE 组6、INT 9 IER = 0x20; //启用 CPU INT6 EINT; EDIS; //通过 GPIO32为 EnDat 5V 电源加电 // GpioDataRegs.GPBDAT.BIO32 = 1; // delay_US (10000L);//延迟10us // EncCLK 高电平100ms EALLOW; GpioCtrlRegs.GPADIR.bit.GPIO6 = 1;//设置为 GPIO 输出 GpioDataRegs.GPASET.bit.GPIO6 = 1;//一旦 GPIO6被转换为 GPIO、将 GPIO 输出设置为高电平 GpioCtrlRegs.GPAMUX1.bit.GPIO6=0; DELAY_US (100000L); //EncCLK 在~200ns 内处于低电平(>125ns) GpioDataRegs.GPADAT.bit.GPIO6 = 0; // EncCLK 高电平425ms (>381ms) GpioCtrlRegs.GPAMUX1.bit.GPIO6=1; DELAY_US (425000L); //确保 EncData 现在为低电平 if (GpioDataRegs.GPBDAT.bit.GPIO63 = 1){ ESTOP0; } DELAY_US (1000L);//延迟1s PM_endat22_setFreq (ENDAT_INIT_FREQ_DIVIDER); DELAY_US (1000L); //编码器接收复位-命令 ERR retval1 = PM_endat22_setupCommand (编码器_receive_reset、0xAA、0x2222、0);//data1=any; Data2=任何 PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (encoder_receive_reset、0); DELAY_US (1000000L); //延迟1 retval1 = PM_endat22_setupCommand (编码器_receive_reset、0xAA、0x2222、0);//data1=any; Data2=任何 PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (encoder_receive_reset、0); DELAY_US (2000L); //选择存储器区域以读取编码器制造商参数。 //MRS 代码 A1 -选择编码器制造商的参数 // 执行{ retval1 = PM_endat22_setupCommand (selection_of_memory_area、0xA1、0x5555、0);//data1=MRS; Data2=任何 PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} //检查 CRC! retval1 = PM_endat22_receiveData (selection_of_memory_area、0); crc5_result = PM_endat22_getCrcNorm (endat22Data.address、endat22Data.data、endat22CRCtable); //}while (!CheckCRC (crc5_result、endat22Data.data_CRC)); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } * DELAY_US (200L);//DELAY 200us //请求编码器发送移出编码器位置值所需的时钟脉冲数 //读取地址0xD 返回移出位置数据所需的时钟脉冲数 // 执行{ retval1 = PM_endat22_setupCommand (ENCODER_SEND_PARAMETER、0xD、0xAAAA、0);//data1=address; Data2=任何 PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} //检查 CRC! retval1 = PM_endat22_receiveData (ENCODER_SEND_PARAMETER、0); crc5_result = PM_endat22_getCrcNorm (endat22Data.address、endat22Data.data、endat22CRCtable); //} while (!CheckCRC (crc5_result、endat22Data.data_CRC)); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } 在 尝试任何位置数据访问之前、需要设置位置数据的时钟数 endat22Data.Position_Clocks = endat22Data.data & 0xFF; DELAY_US (200L); } void Endat_setup_GPIO (void){ EALLOW; GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 1;//将 GPIO6配置为 EnDat Clk 主器件 GpioCtrlRegs.GPAMUX1.bit.GPIO7=1;//将 GPIO7配置为 SPI 时钟从器件 GpioCtrlRegs.GPBGMUX2.bit.GPIO63 = 3; GpioCtrlRegs.GPCGMUX1.bit.GPIO64 = 3; GpioCtrlRegs.GPCGMUX1.bit.GPIO65=3; GpioCtrlRegs.GPCGMUX1.bit.GPIO66 = 3; GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 3;//将 GPIO24配置为 SPISIMOB GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 3;//将 GPIO25配置为 SPISOMIB GpioCtrlRegs.GPCMUX1.bit.GPIO65=3;//将 GPIO26配置为 SPICLKB GpioCtrlRegs.GPCMUX1.bit.GPIO66=3;//将 GPIO27配置为 SPISTEB GpioCtrlRegs.GPBQSEL2.bit.GPIO63 = 3;//异步输入 GPIO24 (SPISIMOB) GpioCtrlRegs.GPCQSEL1.bit.GPIO64 = 3;//异步输入 GPIO25 (SPISOMIB) GpioCtrlRegs.GPCQSEL1.bit.GPIO65=3;//异步输入 GPIO26 (SPICLKB) GpioCtrlRegs.GPCQSEL1.bit.GPIO66 = 3;//异步输入 GPIO27 (SPISTEB) GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 3;//将 GPIO34配置为 EnDat TxEN // GpioCtrlRegs.GPBDIR.bit.GPIO32 = 1;//将 GPIO32配置为 EnDat Pwr CTL EDIS; } void Endat_config_XBAR (void) { EALLOW; //选择 SPISIMO GPIO 作为 InputXbar Input1 - GPIO24上的 SPISIMO (B) InputXbarRegs.INPUT1SELECT = 63;// GPTRIP XBAR TRIP1 -> GPIO24 EDIS; } //执行延迟补偿的模板 //此函数只应在低频(~200kHz)下运行时调用。 void EnDat_initDelayComp (void){ uint16_t delay1、delay2; //将位置值命令发送到编码器 //在该命令操作期间在内部测量延迟 //执行{ retval1 = PM_endat22_setupCommand (ENCODER_SEND_POSITION、0、0、0); PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (ENCODER_SEND_POSITION、0); crc5_result = PM_endat22_getCrcPos (endat22Data.Position_Clocks、ENDAT21、endat22Data.Position_lo、 endat22Data.position_hi、endat22Data.error1、endat22Data.error2、endat22CRCtable); //}while (!CheckCRC (crc5_result、endat22Data.data_CRC)); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } * DELAY_US (200L);//DELAY 200us //在上述操作期间在内部测量延迟 //读取测量的延迟并存储在变量中- n * 2 * SYSCLK delay1 = PM_endat22_getDelayCompVal (); //重新执行相同的过程 //执行{ retval1 = PM_endat22_setupCommand (ENCODER_SEND_POSITION、0、0、0); PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (ENCODER_SEND_POSITION、0); crc5_result = PM_endat22_getCrcPos (endat22Data.Position_Clocks、ENDAT21、endat22Data.Position_lo、 endat22Data.position_hi、endat22Data.error1、endat22Data.error2、endat22CRCtable); //}while (!CheckCRC (crc5_result、endat22Data.data_CRC)); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } * DELAY_US (200L);//DELAY 200us //在上述操作期间在内部测量延迟 //读取测量的延迟并存储在变量中- n * 2 * SYSCLK delay2 = PM_endat22_getDelayCompVal (); //测得的延迟平均值必须更新到 endat22Data.delay_comp //以使延迟补偿生效 endat22Data.delay_comp =(delay1+delay2)>> 1; } void error (void){ asm (" ESTOP0"); //测试失败!! 停下来! 对于(;;); } 中断 void spiRxFifoIsr (void) { uint16_t i; 对于(i=0;i<=endat22Data.fifo_level;i++){endat22Data.RDATA[i]= endat22Data.SPI->SPIRXBUF;} endat22Data.SPI->SPIFFRX.bit.RXFFOVFCLR=1;//清除溢出标志 endat22Data.SPI->SPIFFRX.bit.RXFFINTCLR=1;//清除中断标志 PieCtrlRegs.PIEACK.All|=0x20; //发出 PIE ACK endat22Data.dataReady=1; } void EPWM4_Config (void){ //将 PWMA 和 B 设置为 ENDAT clk 的默认值。 EALLOW; EPwm4Regs.TZCTL.bit.TZA = 1; EPwm4Regs.TZCTL.bit.TSB = 1; EPwm4Regs.TZFRC.bit.OST = 1; EDIS; } uint16_t CheckCRC (uint16_t expectcrc5、uint16_t receivecrc5){ if (exptcrc5 == receivecrc5){ 返回1; } 否则{ 返回0; } } void endat22_setupAddlData (void) { // EnDat22命令读取位置值并执行存储器区域选择 // 0xA1 MRS 代码以选择编码器制造商参数 //此时启用的附加数据为0 retval1 = PM_endat22_setupCommand (ENCODER_SEND_POSITION 值_AND_SELECTION _of_the _memory_area、0xA1、0、0); PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (ENCODER_SEND_POSITION 值_AND_SELECTION _of_the _memory_area、0); crc5_result = PM_endat22_getCrcPos (endat22Data.Position_Clocks、ENDAT22、endat22Data.Position_lo、 endat22Data.position_hi、endat22Data.error1、endat22Data.error2、endat22CRCtable); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } * DELAY_US (200L);//DELAY 200us // EnDat22命令读取位置值并向编码器发送参数 //发送0xD 参数地址-将选择"否" 时钟脉冲移出位置值// 此时启用的附加数据为0 retval1 = PM_endat22_setupCommand (ENCODER_SEND_POSITION 值和 SEND_PARAMETER、0xD、0、0); PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (ENCODER_SEND_POSITION 值_AND_SEND_PARAMETER、0); crc5_result = PM_endat22_getCrcPos (endat22Data.Position_Clocks、ENDAT22、endat22Data.Position_lo、 endat22Data.position_hi、endat22Data.error1、endat22Data.error2、endat22CRCtable); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } * DELAY_US (200L);//DELAY 200us //启用附加数据1 -读取否 时钟脉冲的数量以移出位置值 // MRS 代码0x45 -确认存储器内容 LSB retval1 = PM_endat22_setupCommand (ENCODER_SEND_POSITION 值_AND_SELECTION _of_the _memory_area、0x45、0、0); PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (ENCODER_SEND_POSITION 值_AND_SELECTION _of_the _memory_area、0); crc5_result = PM_endat22_getCrcPos (endat22Data.Position_Clocks、ENDAT22、endat22Data.Position_lo、 endat22Data.position_hi、endat22Data.error1、endat22Data.error2、endat22CRCtable); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } * DELAY_US (200L);//DELAY 200us //启用附加数据2 -读取运行状态和错误源 // MRS 代码0x59 -附加数据的运行状态2 //在本命令为1之前,在本命令之后启用附加数据2 retval1 = PM_endat22_setupCommand (ENCODER_SEND_POSITION 值_AND_SELECTION _of_the _memory_area、0x59、0、1); PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (encoder_send_position_values_and_selection_of_the _memory_area、1); crc5_result = PM_endat22_getCrcPos (endat22Data.Position_Clocks、ENDAT22、endat22Data.Position_lo、 endat22Data.position_hi、endat22Data.error1、endat22Data.error2、endat22CRCtable); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } * DELAY_US (2000L);//DELAY 200us } void endat22_readPositionWithAddlData (void) { //读取位置值时先前启用了2个附加数据 //此时启用了其他数据,该值为2 retval1 = PM_endat22_setupCommand (ENCODER_SEND_POSITION 值_ITH_additional_data、0、0、2); PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (encoder_send_position_values_with _additional_data、2); // CRC 校验位置数据 crc5_result = PM_endat22_getCrcPos (endat22Data.Position_Clocks、ENDAT22、endat22Data.Position_lo、 endat22Data.position_hi、endat22Data.error1、endat22Data.error2、endat22CRCtable); /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } // CRC 检查附加数据1. crc5_result = PM_endat22_getCrcNorm ((endat22Data.additional_data1 >> 16)、endat22Data.additional_data1、endat22CRCtable); /* if (!CheckCRC (crc5_result、endat22Data.additional_data1_CRC)) { ESTOP0; } // CRC 检查附加数据2. crc5_result = PM_endat22_getCrcNorm ((endat22Data.additional_data2 >> 16)、endat22Data.additional_data2、endat22CRCtable); /* if (!CheckCRC (crc5_result、endat22Data.additional_data2_CRC)) { ESTOP0; } * DELAY_US (200L);//DELAY 200us } void endat21_readPosition (void) { //在 EnDat21模式下读取位置值-无附加数据 retval1 = PM_endat22_setupCommand (ENCODER_SEND_POSITION、0、0、0); PM_endat22_startOperation (); while (endat22Data.dataReady!= 1){} retval1 = PM_endat22_receiveData (ENCODER_SEND_POSITION 值、0); // CRC 校验位置数据 // while (!CheckCRC (crc5_result、endat22Data.data_CRC)){ crc5_result = PM_endat22_getCrcPos (endat22Data.Position_Clocks、ENDAT21、endat22Data.Position_lo、 endat22Data.position_hi、endat22Data.error1、endat22Data.error2、endat22CRCtable); //} /* if (!CheckCRC (crc5_result、endat22Data.data_CRC)) { ESTOP0; } *} //********* //文件结束 //
这是主函数中的初始化文件。
秘书长的报告
// EnDat2.2的参数初始化
秘书长的报告
// Init EnDat22参数
endat1.PolePairs =极点/2;
// endat 操作的初始化例程-在 endat.c 中定义
//配置外设并为所需模块启用时钟
//根据 EnDat 操作的需要配置 GPIO 和 Xbar
//在端数据结构中设置 SPI 外设并启用中断
EnDat_Init();
//打印电缆传播延迟计算。
//对于长电缆长度和更高的 EnDat 时钟频率、需要使用此选项
//在 endat.c 中定义的函数
EnDat_initDelayComp ();
//切换到高频- 8.3MHz (=200/4*ENDAT_RUNTIME_FREQ_DIVIDER)
PM_endat22_setFreq (ENDAT_RUNTIME_FREQ_DIVIDER);
DELAY_US (800L); //延迟800us
endat22Data.dataReady = 1;
这是中断函数中的位置读取文件。
.
//在 EnDat21模式下读取位置数据。 在 endat.c 中定义的函数
if (endat22Data.dataReady = 1)
{
endat21_readPosition ();
}
// endat1.RawTheta =(1.0-((float) endat22Data.position_lo)/33554432.0);//除以2^25:EnDat 编码器25位
endat1.RawTheta = endat22Data.position_lo;
endat1.position=(float)(endat1.RawTheta)*0.00001;
//在对齐过程中,将当前轴位置指定为初始位置
endat1.InitTheta = 1391304;对相位 μ s
endat1.MechTheta = endat1.RawTheta - endat1.InitTheta; /*步进计数中的 MechTheta *
endat1.MechTheta =(endat1.MechTheta)%4800000;
endat1.ElecTheta =(float)(endat1.MechTheta)/4800000;
if (endat1.ElecTheta < 0)
endat1.ElecTheta = endat1.ElecTheta + 1.0;
否则、如果(endat1.ElecTheta > 1.0)
endat1.ElecTheta = endat1.ElecTheta - 1.0;
//计算 Q24中的电角
endat1.ElecTheta =_IQfrac (endat1.PolePairs * endat1.ElecTheta);
//位置感应反转
// endat1.ElecTheta = 1.0 - endat1.ElecTheta;
// endat1.MechTheta = 1.0 - endat1.MechTheta;
