ZHDA067 March 2026 TMS320F280039C
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;
}