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.

[参考译文] TMS320F28P650DK:在 CLB 的 Endat 例程中、31 位 Endat 编码器的位置 CRC 始终不正确、而 25 位 Endat 编码器计算出的位置 CRC 正确。 这是为什么?

Guru**** 2611705 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1561392/tms320f28p650dk-in-the-endat-routine-of-clb-the-position-crc-of-the-31-bit-endat-encoder-is-always-incorrect-while-the-position-crc-calculated-by-the-25-bit-endat-encoder-is-correct-why-is-this

器件型号:TMS320F28P650DK


工具/软件:

您好、工程师:

三个月前我发现了这个问题、但我没有及时收到相应的回复、因此我不得不再次寻求帮助。
在 CLB 的 Endat 例程中、31 位分辨率(多圈+单圈)Endat 编码器的位置 CRC 计算始终不正确、而使用 25 位 Endat 编码器时则正确。 为什么会这样呢? 然而,程序的其余部分考虑了分辨率为 31 位甚至更高的 Endat 编码器。
我们真诚地请求所有工程师的帮助来检查这个问题。

此致、

林浩南

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

    你好 Lin — 很遗憾我没有这方面的答案。 其中一个软件例程似乎必须有一个错误才能获得 31 位分辨率。

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

    你好 Lori ,我非常感谢你的答复。 您能帮助我检查并解决 31 位分辨率的 CRC 计算中的错误吗?  

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

    我不确定其他决议是否会有问题、但支持 31 位分辨率对于我们至关重要。

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

    我会看一下。  给我几天时间。  

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

    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));
    
          }
    
      }
     

     我发现了几个潜在问题:

     

    1. 当 TOTAL_CLOCK 为 31(对于 31 位数据)且未设置 endat22 时、我们得到 TOTAL_CLOCK+1 = 32、这将在 testDataArr[0]=(lowpos_temp)>>(32 -

     (TOTAL_CLOCK+1));AS (32 - 32 = 0)。

    1. 当 TOTAL_CLOCKS = 31 时、表达式 lowpos_temp >>(64 -(TOTAL_COUNT+1)) 存在数学问题、因为移位量为 (64 - 32)= 32、即宽度

     操作数的一个字符。 在 C 语言中、按操作数宽度移位是未定义的行为。

    1. 位屏蔽计算可能会有问题:((1 <<(TOTAL_CLOCK+1)–32)- 1)。 当 Total_Clocks = 31 时、我们得到 1 <<(31+1-32)、等于 1 << 0、等于 1、和

     然后减去 1、得到 0。 这将有效地屏蔽所有位。

     

    • 现在、我将为 31 位数据的 CRC 计算创建一个修复。 根据已确定的问题、我提出了以下解决方案:

     

      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));
                  }
              }
          }
    
     

     我所做的主要更改包括:

     

    1. 在 endat22 和非 endat22 部分中添加了 total_clocks == 31 的特殊情况处理。
    2. 修复了潜在的零除法和未定义的移位行为。
    3. 正确处理了 31 位情况的位屏蔽。
    4. 将 testDataArr 初始化为零、以确保没有随机数据影响计算。
    5. 在表达式 1 <<(total_clocks+1)–32 中添加了括号以确保正确的优先级。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Lori、

    我尝试了这个程序,发现它没有解决问题。 我重新检查了原始程序、发现原始程序的这一部分中的位移和值提取是正确的。 问题不应该出现在这里。

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

    我需要一个星期左右的时间才能看一下。 我会尽快把它拉进来。  

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

    您好 Lin、

    我无法访问 31 位编码器。 为了帮助加快速度、您能给我发送几个示例、说明命令、原始数据、提取的数据和编码器中的黄金 CRC 吗? 拥有一些示例数据将有助于找出问题所在。

    您提到原始数据和提取的数据是正确的吗? 只有计算出的 CRC 不正确、但新的 CRC 函数没有任何帮助。  我是否正确理解?

    谢谢你

    Lori

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

    嗨、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 -感谢您提供的数据 — 让我花几天时间来了解一下。  

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

    感谢 Lori 帮助您查看该计划。

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

    LIN、

    我尝试使用 提供的数据重现此问题。 提取的 DATA_CRC 值不同、这使我认为配置与您的配置不同。  

    例如、位置 1

    计算得出的 CRC 为 3、DATA_CRC 为 17

    我使用了 POSITION_CLOCK = 31

    您使用哪个多项式?

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

    Lori、

    再次感谢您的支持。 我已经检查了程序中的配置、它与您图片中的配置相同。

    关于 CRC 计算结果不符的原因、请允许我在短暂假期后进一步了解。

    但是、根据结果、我们通过 DSP 计算出的 CRC 和编码器返回的 CRC 都不同。

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

    谢谢你林 — 我将在这方面的星期一第六在美国.  

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

    您好 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;
    }
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嗨、Lori、

    非常感谢您的帮助。 我将在明天返回工作岗位时测试该计划。
    我之前还测试了 Heidenhain 提供的 CRC 计算程序、但所需的 CPU 时间过长。该程序单次运行的执行时间预计会很长。

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

    您好 Lin、  

    我担心会出现这种情况(海登海恩实施时间太长)。 我还无法确定查找表实现的修复。 当总长度(DATA + 1 位错误)是 8 位字节的倍数时、似乎会发生。 至少这是 Heidenhain 代码与查找表结果不匹配的情况。 但我认为这应该是最直截了当的情况、所以我在某处遗漏了一些东西。   

    Lori

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

    LIN、

    请尝试此更改 — 我还附加了一个测试用例。

     e2e.ti.com/.../pm_5F00_endat22_5F00_crctest_5F00_main.c

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

    嗨、Lori、

    我已经集成了你提供的代码片段,结果是一个令人愉快的惊喜。 修改后、31 位 CRC 计算现在正确!

    非常感谢您过去几天的技术支持和所有帮助。 我真的很感激。

    此致、

    林浩南