在国标GB29768源代码移植修改的符合ISO18000 - 6C协议的PIE发送编码
例:导引头为:
0-1编码为:
其它详见协议规定。
代码如下:
#define PW 16600 //Tari / 2 = 83us
#define MAX_RESPONSE_BYTES 64
typedef struct
{
uint32_t numBytes; // Nb of full bytes
uint32_t numBits; // Nb of remaining bits
uint8_t data[MAX_RESPONSE_BYTES];
} leadinno_RxTxData_t;
extern leadinno_RxTxData_t leadinnoRxTxData;
#define LEADINNO_CMD_QUERY 0x08 // 占低4位
#define LEADINNO_CMD_READ 0xC2 // 占8位
#define LEADINNO_CMD_WRITE 0xC3 // 占8位
#define SET_PULSE_LOW() GPIOC->BRR = (uint32_t)GPIO_PIN_0
#define SET_PULSE_HIGH() GPIOC->BSRR = (uint32_t)GPIO_PIN_0
static void highLowPulse(uint8_t nbTC);
static void separatorPulse(void);
// 全局定义射频发送和接收的数据缓冲区
leadinno_RxTxData_t leadinnoRxTxData;
uint16_t value_crc16;
/**
* @brief 初始化射频发送和接收的数据缓冲区
*
* @param *RxTxData 存放发送数据的缓冲区
*
* @retval
* @author GB29768
* @date 20220401
* @note
*/
static void leadinnoInitializeCmd(leadinno_RxTxData_t *RxTxData)
{
RxTxData->data[0] = 0x00;
RxTxData->numBytes = 0;
RxTxData->numBits = 0;
}
/**
* @brief 将待发送数据按二进制位添加到射频发送和接收的数据缓冲区.
* @note
* @param *RxTxData 存放发送数据的缓冲区
* @param data 添加的数据字节
* @param bits 添加的数据位数,LSB对齐
*
* @retval
* @author GB29768
* @date 20220401
* @note 不能添加超过一个字节(8位)的数据,不足一个字节的数据,LSB对齐
*/
void leadinnoAddByteToBitStream(leadinno_RxTxData_t *RxTxData, const uint8_t data, const uint8_t bits)
{
if(bits > 0)
{
if(RxTxData->numBits == 8)
{
RxTxData->numBytes++;
RxTxData->data[ RxTxData->numBytes ] = 0x00;
RxTxData->numBits = 0;
}
uint32_t cumulatedBits = RxTxData->numBits + bits;
if (cumulatedBits >= 8)
{
// 111x xxxx | xxxx xxxx gGb29768RxTxData.numBits = 3, bits = 6
// 1110 0000 | xxxx xxxx
RxTxData->data[ RxTxData->numBytes ] |= (uint8_t)(data >> (cumulatedBits-8));
RxTxData->numBytes++;
// 1110 0000 | 0xxx xxxx
RxTxData->data[ RxTxData->numBytes ] = (uint8_t)(data << (16-cumulatedBits));
RxTxData->numBits = cumulatedBits - 8;
}
else
{
RxTxData->data[ RxTxData->numBytes ] |= (uint8_t)(data << (8-cumulatedBits));
RxTxData->numBits = cumulatedBits;
}
}
}
/**
* @brief 将待发送数据按二进制位添加到射频发送和接收的数据缓冲区
*
* @param data 添加的数据半字
* @param bits 添加的数据位数
*
* @retval
* @author GB29768
* @date 20220401
* @note 不能添加超过两个字节(16位)的数据,超过1个字节的数据,高字节对齐;剩下的不足一个字节的数据,LSB对齐
*/
static void leadinnoAddWordToBitStream(leadinno_RxTxData_t *RxTxData, const uint16_t data, const uint8_t bits)
{
if(bits>8) {
leadinnoAddByteToBitStream(RxTxData, (uint8_t)(data>>8), 8);
leadinnoAddByteToBitStream(RxTxData, (uint8_t)(data), bits-8);
}
else {
leadinnoAddByteToBitStream(RxTxData, (uint8_t)(data>>8), bits);
}
}
/**
* @brief 将待CRC16添加到射频发送和接收的数据缓冲区
*
* @param *RxTxData 存放发送数据的缓冲区
*
* @retval
* @author GB29768
* @date 20220401
* @note 如果总的数据位数不是偶数,则在最后添加一个二进制0,然后计算CRC16
*/
static void leadinnoAddCrc(leadinno_RxTxData_t *RxTxData)
{
uint16_t crc;
uint16_t num = RxTxData->numBytes*8 + RxTxData->numBits;
if (num%2 != 0)
{
leadinnoAddByteToBitStream(RxTxData, 0x00,1);
num++;
}
crc = crc16Bitwise(RxTxData->data, num);
leadinnoAddWordToBitStream(RxTxData, crc,16);
}
/**
* @brief 发送射频发送数据缓冲区的数据到刺激器
*
* @param *RxTxData 存放发送数据的缓冲区
*
* @retval
* @author GB29768
* @date 20220401
* @note 包含导引头或帧同步和待发送数据的发送
*/
static void leadinnoFinalizeCmdAndSend(leadinno_RxTxData_t *RxTxData)
{
INIT_DWT();
// Ensure pulse state is HIGH
SET_PULSE_HIGH();
// Lead Code
separatorPulse(); // 12.5us
highLowPulse(1); // 1 High + 1 Low=2 TC (25us @ tc=12.5)
highLowPulse(5); // 5 High + 1 Low=6 TC (75us @ tc=12.5)
//highLowPulse(11); // 11 High + 1 Low=2 TC (150us @ tc=12.5)
// Send all bytes
int16_t i, j;
uint8_t data;
for(i=0 ; i<RxTxData->numBytes ; ++i)
{
data = RxTxData->data[i];
for(j = 7 ; j >= 0; j--)
{
if(((data >> j) & 0x01) == 0)
highLowPulse(1); // 发送字符0 (25us @ tc=12.5)
else
highLowPulse(3); // 发送字符1 (50us @ tc=12.5)
}
}
// Send remaining bits
if (RxTxData->numBits) {
data = RxTxData->data[i]; // Get last byte partial content
for(j = 7 ; j >= (8 - RxTxData->numBits); --j)
{
if(((data >> j) & 0x01) == 0)
highLowPulse(1); // 发送字符0 (25us @ tc=12.5)
else
highLowPulse(3); // 发送字符1 (50us @ tc=12.5)
}
}
// Reinit Rx/Tx data structure before Receive state
leadinnoInitializeCmd(RxTxData);
}
/**
* @brief 能控器发送query指令给刺激器,等待获取UID16
*
* @param *RxTxData 存放发送数据的缓冲区
* @param rn16
* @otherParam 后续去掉,临时用作标定pie时序的形参
*
* @retval uint8_t 命令结果
* @author GB29768
* @date 20220401
* @note 本函数内部需实现PIE编码、CRC计算等功能
*/
uint8_t leadinnoSendCmdQuery(leadinno_RxTxData_t *RxTxData, uint16_t rn16, uint32_t tsp, uint32_t t0, uint32_t trt, uint32_t ttr)
{
leadinnoInitializeCmd(RxTxData);
uint8_t gLastCommand = LEADINNO_CMD_QUERY;
leadinnoAddByteToBitStream(RxTxData, gLastCommand, 4);
leadinnoAddByteToBitStream(RxTxData, (uint8_t)(rn16 >> 8), 8);
leadinnoAddByteToBitStream(RxTxData, (uint8_t)rn16, 8);
leadinnoAddCrc(RxTxData);
INIT_DWT();
// Ensure pulse state is HIGH
SET_PULSE_HIGH();
// Lead Code
SET_PULSE_LOW();
nsdelay(tsp);
SET_PULSE_HIGH();
nsdelay(t0);
SET_PULSE_LOW();
nsdelay(t0);
SET_PULSE_HIGH();
nsdelay(trt);
SET_PULSE_LOW();
nsdelay(t0);
SET_PULSE_HIGH();
nsdelay(ttr);
SET_PULSE_LOW();
nsdelay(t0);
SET_PULSE_HIGH();
// Send all bytes
int16_t i, j;
uint8_t data;
for(i=0 ; i<RxTxData->numBytes ; ++i)
{
data = RxTxData->data[i];
for(j = 7 ; j >= 0; j--)
{
if(((data >> j) & 0x01) == 0)
highLowPulse(1); // 发送字符0 (25us @ tc=12.5)
else
highLowPulse(3); // 发送字符1 (50us @ tc=12.5)
}
}
// Send remaining bits
if (RxTxData->numBits) {
data = RxTxData->data[i]; // Get last byte partial content
for(j = 7 ; j >= (8 - RxTxData->numBits); --j)
{
if(((data >> j) & 0x01) == 0)
highLowPulse(1); // 发送字符0 (25us @ tc=12.5)
else
highLowPulse(3); // 发送字符1 (50us @ tc=12.5)
}
}
// Reinit Rx/Tx data structure before Receive state
leadinnoInitializeCmd(RxTxData);
// uint8_t resp = leadinnoWaitForResponse(RxTxData, CRC16_CHECK_ON);
// return resp;
return 0;
}
/**
* @brief 能控器发送read指令给刺激器,返回读取的结果
*
* @param *RxTxData 存放发送数据的缓冲区
* @param reg 寄存器地址
* @param *data 接收到的数据
* @param rn16
*
* @retval uint8_t 超时时间内收到数据,返回0;失败返回非0
* @author yangFei
* @date 20220401
* @note 本函数内部需实现PIE编码、CRC计算等功能 读取的长度是1 单位是word 16位
*/
uint8_t leadinnoSendCmdRead(leadinno_RxTxData_t *RxTxData, uint8_t reg, uint8_t *data, uint16_t rn16)
{
#define MEM_BANK 0
#define WORD_COUNT 1
leadinnoInitializeCmd(RxTxData);
uint8_t gLastCommand = LEADINNO_CMD_READ;
leadinnoAddByteToBitStream(RxTxData, gLastCommand, 8);
leadinnoAddByteToBitStream(RxTxData, MEM_BANK, 2);
leadinnoAddByteToBitStream(RxTxData, reg, 8);
leadinnoAddByteToBitStream(RxTxData, WORD_COUNT, 8);
leadinnoAddByteToBitStream(RxTxData, (uint8_t)(rn16 >> 8), 8);
leadinnoAddByteToBitStream(RxTxData, (uint8_t)rn16, 8);
leadinnoAddCrc(RxTxData);
leadinnoFinalizeCmdAndSend(RxTxData);
// uint8_t resp = leadinnoWaitForResponse(RxTxData, CRC16_CHECK_ON);
// return resp;
return 0;
}
/**
* @brief 能控器发送read指令给刺激器,返回读取的结果
*
* @param *RxTxData 存放发送数据的缓冲区
* @param reg 寄存器地址
* @param *data 要发送的数据
* @param rn16
*
* @retval uint8_t 超时时间内收到数据,返回0;失败返回非0
* @author yangFei
* @date 20220401
* @note 本函数内部需实现PIE编码、CRC计算等功能 读取的长度是1 单位是word 16位
*/
uint8_t leadinnoSendCmdWrite(leadinno_RxTxData_t *RxTxData, uint8_t reg, uint8_t *data, uint16_t rn16)
{
#define MEM_BANK 0
leadinnoInitializeCmd(RxTxData);
uint8_t gLastCommand = LEADINNO_CMD_WRITE;
leadinnoAddByteToBitStream(RxTxData, gLastCommand, 8);
leadinnoAddByteToBitStream(RxTxData, MEM_BANK, 2);
leadinnoAddByteToBitStream(RxTxData, reg, 8);
leadinnoAddByteToBitStream(RxTxData, data[0], 8);
leadinnoAddByteToBitStream(RxTxData, data[1], 8);
leadinnoAddByteToBitStream(RxTxData, (uint8_t)(rn16 >> 8), 8);
leadinnoAddByteToBitStream(RxTxData, (uint8_t)rn16, 8);
leadinnoAddCrc(RxTxData);
leadinnoFinalizeCmdAndSend(RxTxData);
//uint8_t resp = leadinnoWaitForResponse(RxTxData, CRC16_CHECK_ON);
// return resp;
return 0;
}
static void highLowPulse(uint8_t nbTC)
{
// High pulse
SET_PULSE_HIGH();
nsdelay(nbTC * PW);
// Low Pulse
SET_PULSE_LOW();
nsdelay(PW); // 1 TC
SET_PULSE_HIGH();
}
static void separatorPulse(void)
{
SET_PULSE_LOW();
nsdelay(4 * PW);
SET_PULSE_HIGH();
}