C语言常用的工具函数(PIE编码发送函数)

366 阅读5分钟

在国标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();
}