工具/软件:
您好、工程师:
三个月前我发现了这个问题、但我没有及时收到相应的回复、因此我不得不再次寻求帮助。
在 CLB 的 Endat 例程中、31 位分辨率(多圈+单圈)Endat 编码器的位置 CRC 计算始终不正确、而使用 25 位 Endat 编码器时则正确。 为什么会这样呢? 然而,程序的其余部分考虑了分辨率为 31 位甚至更高的 Endat 编码器。
我们真诚地请求所有工程师的帮助来检查这个问题。
此致、
林浩南
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.
工具/软件:
您好、工程师:
三个月前我发现了这个问题、但我没有及时收到相应的回复、因此我不得不再次寻求帮助。
在 CLB 的 Endat 例程中、31 位分辨率(多圈+单圈)Endat 编码器的位置 CRC 计算始终不正确、而使用 25 位 Endat 编码器时则正确。 为什么会这样呢? 然而,程序的其余部分考虑了分辨率为 31 位甚至更高的 Endat 编码器。
我们真诚地请求所有工程师的帮助来检查这个问题。
此致、
林浩南
LIN、
我请 Claude Code 分析该函数、以及为什么它不适用于 31 位函数。 以下是分析和建议的修复方法。 请记住、这是 AI 产生的、但我希望它会有所帮助。
该问题专门针对 31 位数据发生、但适用于 25 位数据。 让我们重点看一下 PM_endat22_getCrcPos 函数的相关部分:
if(endat22)
{
lowpos_temp = __flip32(lowpos);
if (total_clocks+2 > 32)
{
highpos_temp = ((__flip32(highpos)) >> (64 - (total_clocks+2))) & (( 1 << (total_clocks+2) -32) - 1);
testDataArr[1] = lowpos_temp >> (64 - (total_clocks+2));
testDataArr[0] = (lowpos_temp << (((total_clocks+2)-32))) | highpos_temp;
}
else
{
testDataArr[0] = (lowpos_temp) >> (32 - (total_clocks+2));
}
}
else
{
lowpos_temp = __flip32(lowpos);
if (total_clocks+1 > 32)
{
highpos_temp = ((__flip32(highpos)) >> (64 - (total_clocks+1))) & (( 1 << (total_clocks+1) -32) - 1);
testDataArr[1] = lowpos_temp >> (64 - (total_clocks+1));
testDataArr[0] = lowpos_temp << ((total_clocks+1)-32) | highpos_temp;
}
else
{
testDataArr[0] = (lowpos_temp) >> (32 - (total_clocks+1));
}
}
我发现了几个潜在问题:
(TOTAL_CLOCK+1));AS (32 - 32 = 0)。
操作数的一个字符。 在 C 语言中、按操作数宽度移位是未定义的行为。
然后减去 1、得到 0。 这将有效地屏蔽所有位。
uint32_t PM_endat22_getCrcPos(uint32_t total_clocks, uint32_t endat22, uint32_t lowpos, uint32_t highpos, uint32_t error1, uint32_t error2, uint16_t *crc_table)
{
uint16_t accumulator, nBytes;
uint32_t testDataArr[2] = {0}; // Initialize array to zero
uint32_t lowpos_temp, highpos_temp;
lowpos_temp = lowpos;
if(endat22)
{
lowpos = (lowpos << 2) | (error2 << 1) | error1;
highpos = (highpos << 2) | (lowpos_temp >> 30);
}
else
{
lowpos = (lowpos << 1) | error1;
highpos = (highpos << 1) | (lowpos_temp >> 31);
}
if(endat22)
{
lowpos_temp = __flip32(lowpos);
if (total_clocks+2 > 32)
{
// Handle the special case for 31-bit data (resulting in 33-bit with endat22)
if (total_clocks == 31) {
highpos_temp = __flip32(highpos) & 0x1; // Only get the lowest bit
testDataArr[1] = lowpos_temp >> 31; // Right shift by 31 bits to get the upper bit
testDataArr[0] = lowpos_temp << 1 | highpos_temp; // Left shift by 1 and OR with highpos
} else {
highpos_temp = ((__flip32(highpos)) >> (64 - (total_clocks+2))) & (( 1 << ((total_clocks+2) -32)) - 1);
testDataArr[1] = lowpos_temp >> (64 - (total_clocks+2));
testDataArr[0] = (lowpos_temp << ((total_clocks+2)-32)) | highpos_temp;
}
}
else
{
testDataArr[0] = (lowpos_temp) >> (32 - (total_clocks+2));
}
}
else
{
lowpos_temp = __flip32(lowpos);
if (total_clocks+1 > 32)
{
// Handle the special case for 31-bit data
if (total_clocks == 31) {
testDataArr[0] = lowpos_temp; // Use the full lowpos value
testDataArr[1] = 0; // highpos will not be used
} else {
highpos_temp = ((__flip32(highpos)) >> (64 - (total_clocks+1))) & (( 1 << ((total_clocks+1) -32)) - 1);
testDataArr[1] = lowpos_temp >> (64 - (total_clocks+1));
testDataArr[0] = lowpos_temp << ((total_clocks+1)-32) | highpos_temp;
}
}
else
{
// Add special case for exactly 31-bit data (total_clocks == 31)
if (total_clocks == 31) {
testDataArr[0] = lowpos_temp >> 1; // Shift right by 1 bit
} else {
testDataArr[0] = (lowpos_temp) >> (32 - (total_clocks+1));
}
}
}
我所做的主要更改包括:
嗨、Lori、
你是对的。 正是这种情况。
我尝试滤除 CRC 错误、手动旋转 31 位分辨率的 Endat 编码器五圈、并使用我们的上部计算机工具检查旋转过程中程序计算出的位置变化和匝数。 它们匹配、表明 DSP 程序在提取原始数据时没有问题。

目前、我只使用了与 EEPROM 相关的命令和 ENCODER_SEND_POSITION_VALUES 命令。 下面是我随机获取的几组数据。 我希望他们可以帮助。请原谅我忘记捕获原始编码器返回的数据。
Selection_of_memory_area
PM_endat22_setupCommand (Selection_of_memory_area、0x00B9、0x5555、0);
//data1=MRS 代码;data2=任意
RDATA[0]= 32768 (0x8000)
RDATA[1]= 0
RDATA[2]= 11861 (0x2E55)
RDATA[3]= 21833 (0x5549)
RDATA[4]= 26116 (0x6636)
(编码器)data_crc : 4.
(DSP) crc_result:4.
ENCODER_SEND_PARAMETER
PM_endat22_setupCommand (ENCODER_SEND_PARAMETER、0x00、0xAAAA、0);
//data1=地址;data2=任意
RDATA[0]= 32768 (0x8000)
RDATA[1]= 0
RDATA[2]= 0
RDATA[3]= 49 (0x0031)
(编码器)DATA_CRC:24 (0x18)
(DSP) CRC_RESULT:24 (0x18)
ENCODER_SEND_POSITION_VALUES 1
PM_endat22_setupCommand (ENCODER_SEND_POSITION_VALUES、0、0、0);
RDATA[0]= 32766 (0x801C)
RDATA[1]= 18990 (0x4A2E)
RDATA[2]= 11719 (0x2DC7)
RDATA[3]= 21 (0x15)
(编码器)DATA_CRC:3 (0x03)
(DSP) CRC_RESULT:21 (0x15)
ENCODER_SEND_POSITION_VALUES 2.
PM_endat22_setupCommand (ENCODER_SEND_POSITION_VALUES、0、0、0);
RDATA[0]= 32788 (0x8014)
RDATA[1]= 49998 (0xC34E)
RDATA[2]= 52729 (0xCDF9)
RDATA[3]= 21 (0x15)
(编码器)DATA_CRC:28 (0x1C)
(DSP) CRC_RESULT:10 (0x0A)
ENCODER_SEND_POSITION_VALUES 3.
PM_endat22_setupCommand (ENCODER_SEND_POSITION_VALUES、0、0、0);
RDATA[0]= 32771 (0x8003)
RDATA[1]= 45260 (0xB0CC)
RDATA[2]= 19927 (0x4DD7)
RDATA[3]= 21 (0x15)
(编码器)DATA_CRC:11 (0x0B)
(DSP) CRC_RESULT:29 (0x1D)
ENCODER_SEND_POSITION_VALUES 4.
PM_endat22_setupCommand (ENCODER_SEND_POSITION_VALUES、0、0、0);
RDATA[0]= 32780 (0x800C)
RDATA[1]= 9593 (0x2579)
RDATA[2]= 36289 (0x8DC1)
RDATA[3]= 21 (0x15)
(编码器)data_crc : 0
(DSP) CRC_RESULT:22 (0x16)
ENCODER_SEND_POSITION_VALUES 5.
PM_endat22_setupCommand (ENCODER_SEND_POSITION_VALUES、0、0、0);
RDATA[0]= 32780 (0x800C)
RDATA[1]= 37344 (0x91E0)
RDATA[2]= 36307 (0x8DD3)
RDATA[3]= 21 (0x15)
(编码器)DATA_CRC:9 (0x09)
(dsp) crc_result:31 (0x1F)
您好 Lin、
Heidenhain 的 EnDat2.2 文档具有以下 CRC 实现。 用于测试的注意事项 I coded endat22 = 0。
我已将其与 TI 查找表方法进行比较、并且只要数据长度(包括 error1 位)等于字节边界、就会发现不匹配。 例如、时钟总数= 31。 这导致我认为 CRC 中的“if (dangling bits!= 0)“在这种情况下需要有一个“else",“,但、但我还无法解决它。
同时、您能否查看此计算是否有效以及是否满足您的处理要求? 我将继续研究更优的解决方案。
unsigned int endat22_spec_crc(){ unsigned int endat22 = 0; unsigned int ff[5]; // State of the 5 flip-flops unsigned int code[66]; // Data-bit array unsigned int ex; // Auxiliary variable unsigned int crc = 0; // Determined CRC code signed int i; // Controlled variable for looping for(i = 0; i < 5; i++) // Set all flip-flops to 1 ff[i] = 1; if (endat22) // Transfer alarm bits into code array { code[0] = endat22Data.error1; code[1] = endat22Data.error2; } else code[1] = endat22Data.error1; unsigned long position_lo = endat22Data.position_lo; for(i = 2; i < 34; i++) // Transfer lowpos bits into code array { code[i] = (position_lo & 0x00000001L) ? 1 : 0; position_lo >>= 1; } unsigned long position_hi = endat22Data.position_hi; for(i = 34; i < 66; i++) // Transfer highpos bits into code array { code[i] = (position_hi & 0x00000001L) ? 1 : 0; position_hi >>= 1; } for(i = (endat22 ? 0 : 1); i <= (endat22Data.position_clocks+1); i++) { // Calculate the CRC analog to the ex = ff[4] ^ code[i]; // described generator hardware ff[4] = ff[3]; ff[3] = ff[2] ^ ex; ff[2] = ff[1]; ff[1] = ff[0] ^ ex; ff[0] = ex; } for(i = 4; i >= 0; i--) // Store CRC in variable { ff[i] = ff[i] ? 0 : 1; // Invert bits crc <<= 1; crc |= ff[i]; } return crc;}LIN、
请尝试此更改 — 我还附加了一个测试用例。
