ZHDA067 March   2026 TMS320F280039C

 

  1.   1
  2.   摘要
  3.   商标
  4. 1简介
  5. 2系统说明
    1. 2.1 SPI 实现方案
    2. 2.2 CLB 实现方案
    3. 2.3 软件更改
  6. 3验证
  7. 4总结
  8. 5参考资料

软件更改

T-Format 解决方案中的大多数软件都可以在 A-Format 接口中重复使用。根据上述 SPI 和 CLB 实现,软件也有变化。

第一个是 tformat_configureCLBLen() API。此函数用于为 CLB 计数器配置适当数量的传输和接收时钟,这些时钟可能因命令而异。在 A-Format CLB 实现(用于 CRC 计算)中,CRC 掩码取决于编码器响应的时钟数,因此向该 API 添加了两个额外的配置。两行配置的 COUNTER_1_MATCH_1 和 COUNTER_1_MATCH_2 可以正确触发 FSM_2 并在编码器响应中标记 CRC。有关配置影响的详细信息,请参阅图 2-5

static inline void
tformat_configureCLBLen(uint16_t transmitClocks, uint16_t receiveClocks)
{
    CLB_writeInterface(PM_TFORMAT_CLB_BASE,
                        CLB_ADDR_COUNTER_1_MATCH1, transmitClocks);
    CLB_writeInterface(PM_TFORMAT_CLB_BASE,
                        CLB_ADDR_COUNTER_1_MATCH2, transmitClocks);
    CLB_writeInterface(PM_TFORMAT_CLB_BASE,
                        CLB_ADDR_HLC_R0, receiveClocks);


    // Below are the changes
    CLB_writeInterface(PM_TFORMAT_RX_CRC_BASE,
                       CLB_ADDR_COUNTER_1_MATCH1, receiveClocks - 9);
    CLB_writeInterface(PM_TFORMAT_RX_CRC_BASE,
                       CLB_ADDR_COUNTER_1_MATCH2, receiveClocks - 1);

    return;
}

传递到 PM_tformat_setupCommand() 函数的参数的第二个更改。

PM_tformat_setupCommandReadoutOrReset(uint16_t commandID0_1_2_3_7_8_C,
                              uint16_t tformatRXClocks,
                              uint16_t tformatRXFields,
                              uint16_t tformatTXClocks,
                              uint16_t tformatFIFOLevel)

这些参数包括帧数据、传输及接收数据的字段/时钟数以及 FIFO LEVEL。这些参数与接口协议本身相关,并受 SPI 实现一节中提到的 FIFO 分离的影响。下面示出了如何正确计算这些参数的示例。此示例基于 A-Format CDF0。

    #define AFORMAT_FRAME_LEN 9
    #define AFORMAT_TX_FRAMES 1
    #define AFORMAT_CFID0RES_RX_FIELDS 4

    uint16_t aformatTXClocks = (AFORMAT_TX_FRAMES*AFORMAT_FRAME_LEN);
    uint16_t aformatRXClocks = (2u*AFORMAT_CFID0RES_FIELDS*AFORMAT_FRAME_LEN);
    uint16_t aformatRXFields = (2u*AFORMAT_CFID0RES_FIELDS);
    uint16_t aformatFIFOLevel = (2u+2u*AFORMAT_CFID0RES_FIELDS);

由于 A-Format 中的 18 位字段被拆分为两个 9 位半字段,因此在填充 FIFO 时,最高有效半部分将首先填充,然后是最低有效半部分。与 T-Format 解决方案相同,TX FIFO 的其余部分会填充 0xFFFF,以便在接收期间将 TX 线路保持在高电平。下面是 FIFO 填充的示例。

    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = cdf_msh;  // Change
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = cdf_lsh;  // Change

    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;

    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;
    HWREGH(PM_TFORMAT_SPI + SPI_O_TXBUF) = 0xFFFF;

最后,必须更改解码函数 PM_tformat_receiveDataID0_1_7_8_C()。此函数根据接口协议读取 SPI 缓冲器并且将原始数据解码为综合的数据结构。下文提供了 A-Format 中 CDF0 的解码响应示例。请注意,RX FIFO 也是拆分的。

void aformat_decode(){
    // for now, limited to the response of CF0
    uint16_t fullData[4] = {0};

    // full data: get rid of start bit 0 and end bit 1
    fullData[0] = (tformatRxData[3]<<7)|(tformatRxData[4]>>2);
    fullData[1] = (tformatRxData[5]<<7)|(tformatRxData[6]>>2);
    fullData[2] = (tformatRxData[7]<<7)|(tformatRxData[8]>>2);
    fullData[3] = (tformatRxData[9]<<7)|(tformatRxData[10]>>2);
    aformatData.fullData = ((uint64_t)fullData[0]<<48)|
                           ((uint64_t)fullData[1]<<32)|
                           ((uint64_t)fullData[2]<<16)|
                           ((uint64_t)fullData[3]);

    // crc data
    aformatData.crcIncludedData = aformatData.fullData>>8; //for cmd ID 0 only!!

    // crc recived from encoder
    aformatData.crcRecv = (aformatData.fullData & 0x00000000000000ff);

    // crc by CLB
    aformatData.crcByCLB = aformat_getRxCRCbyCLB();
    aformatData.crcBothRecvAndCLB = ((aformatData.crcRecv&0xff)<<8) | (aformatData.crcRecv&0xff);

    // single turn data fullData[16:34] = ST[0:18] (19bit)
    aformatData.stData = (aformatData.fullData & 0x0000ffffd0000000)>>29;
    aformatData.stData = (__flip32(aformatData.stData)>>13)&0x7FFFF;

    // multi turn data fullData[35:51] (17bit)
    aformatData.mtData = (aformatData.fullData & 0x000000001ffff000)>>12;
    aformatData.mtData = (__flip32(aformatData.mtData)>>15)&0x1FFFF;

    // err code
    aformatData.errCode = (aformatData.fullData & 0x000f000000000000)>>48;

    // command ID
    aformatData.cmdID =  (aformatData.fullData & 0x03e0000000000000)>>53;

    // encoder address
    aformatData.encoderAddress = (aformatData.fullData & 0x1c00000000000000)>>58;

    encoderStatus.position = (float)aformatData.stData/524288.0*360;
    encoderStatus.turns = aformatData.mtData;
}