一:CRC8校验操作
//crc8 generator polynomial:G(x)=x8+x5+x4+1
const unsigned char CRC8_INIT = 0xff;
const unsigned char CRC8_TAB[256] =
{
0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc, 0x23,
0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62, 0xbe, 0xe0,
0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff, 0x46, 0x18, 0xfa,
0xa4, 0x27, 0x79, 0x9b, 0xc5, 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07, 0xdb, 0x85, 0x67,
0x39, 0xba, 0xe4, 0x06, 0x58, 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a, 0x65, 0x3b, 0xd9, 0x87,
0x04, 0x5a, 0xb8, 0xe6, 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24, 0xf8, 0xa6, 0x44, 0x1a, 0x99,
0xc7, 0x25, 0x7b, 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,
0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd, 0x11,
0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, 0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50, 0xaf, 0xf1,
0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c, 0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee, 0x32, 0x6c, 0x8e,
0xd0, 0x53, 0x0d, 0xef, 0xb1, 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73, 0xca, 0x94, 0x76, 0x28,
0xab, 0xf5, 0x17, 0x49, 0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b, 0x57, 0x09, 0xeb, 0xb5,
0x36, 0x68, 0x8a, 0xd4, 0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16, 0xe9, 0xb7, 0x55, 0x0b, 0x88,
0xd6, 0x34, 0x6a, 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, 0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35,
};
unsigned char Get_CRC8_Check_Sum(unsigned char *pchMessage,unsigned int
dwLength,unsigned char ucCRC8)
{
unsigned char ucIndex;
while (dwLength--)
{
ucIndex = ucCRC8^(*pchMessage++);
ucCRC8 = CRC8_TAB[ucIndex];
}
return(ucCRC8);
}
/*
** Descriptions: CRC8 Verify function
** Input: Data to Verify,Stream length = Data + checksum
** Output: True or False (CRC Verify Result)
*/
unsigned int Verify_CRC8_Check_Sum(unsigned char *pchMessage, unsigned int dwLength)
{
unsigned char ucExpected = 0;
if ((pchMessage == 0) || (dwLength <= 2)) return 0;
ucExpected = Get_CRC8_Check_Sum (pchMessage, dwLength-1, CRC8_INIT);
return ( ucExpected == pchMessage[dwLength-1] );
© 2024 大疆 版权所有 37
}
/*
** Descriptions: append CRC8 to the end of data
** Input: Data to CRC and append,Stream length = Data + checksum
** Output: True or False (CRC Verify Result)
*/
void Append_CRC8_Check_Sum(unsigned char *pchMessage, unsigned int dwLength)
{
unsigned char ucCRC = 0;
if ((pchMessage == 0) || (dwLength <= 2)) return;
ucCRC = Get_CRC8_Check_Sum ( (unsigned char *)pchMessage, dwLength-1, CRC8_INIT);
pchMessage[dwLength-1] = ucCRC;
}
-
CRC8_INIT 和 CRC8_TAB:定义了CRC8的初始值和查找表。CRC8_INIT是CRC8计算的初始值,而CRC8_TAB是一个256字节大小的查找表,用于在计算CRC8时快速查找校验值。
-
Get_CRC8_Check_Sum 函数:用于计算给定数据的CRC8校验值。它接受三个参数:pchMessage(指向数据缓冲区的指针),dwLength(数据长度),ucCRC8(CRC8初始值)。函数通过遍历数据并使用查找表来计算CRC8校验值,最终返回计算得到的CRC8值。
-
Verify_CRC8_Check_Sum 函数:用于验证数据的CRC8校验值是否正确。它接受两个参数:pchMessage(指向数据缓冲区的指针)和dwLength(数据长度)。函数首先计算数据除去最后一个字节(即CRC8校验值)的CRC8校验值,并将其与数据中的CRC8校验值进行比较,最终返回比较结果(真或假)。
-
Append_CRC8_Check_Sum 函数:用于在数据末尾附加CRC8校验值。它接受两个参数:pchMessage(指向数据缓冲区的指针)和dwLength(数据长度)。函数首先计算数据的CRC8校验值,并将其附加在数据末尾,以完成数据的CRC8校验
二:CRC16校验操作
-
uint16_t CRC_INIT = 0xffff; const uint16_t wCRC_Table[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 38 © 2024 大疆 版权所有 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; /* ** Descriptions: CRC16 checksum function ** Input: Data to check,Stream length, initialized checksum ** Output: CRC checksum */ uint16_t Get_CRC16_Check_Sum(uint8_t *pchMessage,uint32_t dwLength,uint16_t wCRC) { Uint8_t chData; if (pchMessage == NULL) { return 0xFFFF; } while(dwLength--) { chData = *pchMessage++; (wCRC) = ((uint16_t)(wCRC) >> 8) ^ wCRC_Table[((uint16_t)(wCRC) ^ (uint16_t)(chData)) & 0x00ff]; } return wCRC; } /* ** Descriptions: CRC16 Verify function ** Input: Data to Verify,Stream length = Data + checksum ** Output: True or False (CRC Verify Result) */ uint32_t Verify_CRC16_Check_Sum(uint8_t *pchMessage, uint32_t dwLength) { uint16_t wExpected = 0; if ((pchMessage == NULL) || (dwLength <= 2)) { return __FALSE; } © 2024 大疆 版权所有 39 40 © 2024 大疆 版权所有 wExpected = Get_CRC16_Check_Sum ( pchMessage, dwLength - 2, CRC_INIT); return ((wExpected & 0xff) == pchMessage[dwLength - 2] && ((wExpected >> 8) & 0xff) == pchMessage[dwLength - 1]); } /* ** Descriptions: append CRC16 to the end of data ** Input: Data to CRC and append,Stream length = Data + checksum ** Output: True or False (CRC Verify Result) */ void Append_CRC16_Check_Sum(uint8_t * pchMessage,uint32_t dwLength) { uint16_t wCRC = 0; if ((pchMessage == NULL) || (dwLength <= 2)) { return; } wCRC = Get_CRC16_Check_Sum ( (U8 *)pchMessage, dwLength-2, CRC_INIT ); pchMessage[dwLength-2] = (U8)(wCRC & 0x00ff); pchMessage[dwLength-1] = (U8)((wCRC >> 8)& 0x00ff)
这段代码实现了CRC16校验的计算、验证和附加功能。下面是逐步解释:
-
CRC_INIT 和 wCRC_Table:定义了CRC16校验的初始值和查找表。CRC_INIT是CRC16的初始值,而wCRC_Table是一个256字节大小的查找表,其中包含了预先计算好的CRC16校验值。
-
Get_CRC16_Check_Sum 函数:用于计算给定数据的CRC16校验值。它接受三个参数:pchMessage(指向数据缓冲区的指针)、dwLength(数据长度)、wCRC(CRC16初始值)。函数通过遍历数据并使用查找表来计算CRC16校验值,最终返回计算得到的CRC16值。
-
Verify_CRC16_Check_Sum 函数:用于验证数据的CRC16校验值是否正确。它接受两个参数:pchMessage(指向数据缓冲区的指针)和dwLength(数据长度)。函数首先计算数据除去最后两个字节(即CRC16校验值)的CRC16校验值,然后将其与数据中的CRC16校验值进行比较,最终返回比较结果(真或假)。
-
Append_CRC16_Check_Sum 函数:用于在数据末尾附加CRC16校验值。它接受两个参数:pchMessage(指向数据缓冲区的指针)和dwLength(数据长度)。函数首先计算数据的CRC16校验值,并将低8位和高8位分别附加在数据末尾,以完成数据的CRC16校验。
在CRC校验中,附加校验值到数据末尾的常见做法是为了方便数据传输和校验的实现。具体来说,附加CRC校验值的目的是在数据传输结束后,接收方可以利用这个校验值来验证接收到的数据是否在传输过程中发生了错误或损坏。
通常情况下,CRC校验值的长度是16位(对于CRC16),而数据通常以字节为单位传输。为了将16位的校验值附加到数据末尾,需要将这16位拆分成两个字节,其中高8位和低8位分别存储在数据的最后两个字节中。
在验证数据时,接收方会首先计算接收到的数据除去最后两个字节(即CRC校验值)的CRC校验值,并将其与接收到的CRC校验值进行比较。如果两者相等,则说明数据在传输过程中没有发生错误;否则,就说明数据存在错误或者损坏。
通过在数据末尾附加CRC校验值的方式,可以实现简单有效的数据完整性校验,并且不需要额外的协议字段来标识校验值的位置。
import serial
import serial.tools.list_ports
import struct
CRC8_TABLE = [
0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc,
0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,
0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff,
0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5, 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07,
0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58, 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,
0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24,
0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b, 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,
0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,
0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, 0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50,
0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c, 0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee,
0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1, 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,
0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49, 0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b,
0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4, 0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16,
0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a, 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, 0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35,
]
CRC16_TABLE = [
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
]
def get_crc16_check_byte(data):
crc = 0xffff
for byte in data:
crc = ((crc >> 8) ^ CRC16_TABLE[(crc ^ byte & 0xff) & 0xff])
return crc
def get_crc8_check_byte(data):
crc = 0xff
for byte in data:
crc_index = crc ^ byte
crc = CRC8_TABLE[crc_index]
return crc
alarm_layer = 5
car2client = {1: b'\x01\x01',
2: b'\x02\x01',
3: b'\x03\x01',
4: b'\x04\x01',
5: b'\x05\x01',
101: b'\x65\x01',
102: b'\x66\x01',
103: b'\x67\x01',
104: b'\x68\x01',
105: b'\x69\x01'
}
def serial_init(port):
port_list = list(serial.tools.list_ports.comports())
if len(port_list) == 0:
print('无可用串口')
else:
for i in range(0, len(port_list)):
print(port_list[i])
bps = 115200
timex = 0.5
ser = serial.Serial(port, bps, timeout=timex)
return ser
# 构建帧头
def get_frame_header(data_length=14):
# frame header
# +--------+--------------+--------+--------+
# | SOF | data_length | seq | CRC8 |
# +--------+--------------+--------+--------+
# | 1-byte | 2-byte | 1-byte | 1-byte |
# +--------+--------------+--------+--------+
#
# SOF: start of frame, a fixed byte at the beginnig of frame header
# the value is 0xA5 in v1.4 protocol
# 单字节,接收的数据应为 A5
#
# data_length: 不包含 cmd_id 和 frame_tail
# (construct of a frame:
# [ frame_head | cmd_id | data | frame_tail ]
# 5-byte 2-byte n-byte 2-byte
# )
# 双字节,以data_length=14(10)为例,接收时表现为 0E 00,低字节在前
#
# seq: packet sequence number
# not used now?
#
# struct.py
# https://docs.python.org/3.8/library/struct.html#struct-format-strings
# format: struct member type -> size
# 'H': unsigned short -> 2 bytes
# 'h': short -> 2 bytes
# 'B': unsigned char -> 1 byte
# 'f': float -> 4 bytes
# 'fff' or '3f' means continuous 3 float values
# 'I': unsigned int -> 4 bytes
# global SOF, seq
SOF = b'\xA5'
seq = 0 # 目前均为单包数据,且无重发机制?
_data_length = struct.pack('H', data_length)
_seq = struct.pack('B', seq)
_frame_header = SOF + \
_data_length + \
_seq
frame_header = _frame_header + struct.pack('B', get_crc8_check_byte(_frame_header))
return frame_header
def send_enemy_location(ser, carID, x, y):
tx_buff = get_frame_header(10)
tx_buff += b'\x05\x03'
tx_buff += struct.pack('H', carID) + struct.pack('ff', x, y)
CRC16 = get_crc16_check_byte(tx_buff)
frame_tail = bytes([CRC16 & 0x00ff, (CRC16 & 0xff00) >> 8])
tx_buff += frame_tail
ser.write(tx_buff)
return tx_buff
-
CRC8 和 CRC16 计算函数:
get_crc8_check_byte(data)
: 计算给定数据的 CRC8 校验值。get_crc16_check_byte(data)
: 计算给定数据的 CRC16 校验值。- 这两个函数用于计算数据的校验值,以确保数据在传输过程中的完整性。
-
初始化串口:
serial_init(port)
: 初始化串口通信,返回一个串口对象。- 使用
serial.Serial
类初始化串口对象,设置串口号、波特率和超时时间。
-
构建帧头:
get_frame_header(data_length=14)
: 构建通信帧的帧头部分。- 帧头由起始字节(SOF)、数据长度(data_length)、序列号(seq)和CRC8校验值组成。
-
发送敌方车辆位置信息:
send_enemy_location(ser, carID, x, y)
: 发送敌方车辆位置信息到设备。- 构建帧头,添加命令ID、车辆ID和位置坐标(x,y),并计算CRC16校验值后发送。
\x45
和 0x45
都表示十六进制数值 45
,但是在 Python 中,它们的使用上有一些区别:
-
\x45
是一种特殊的转义字符表示法,用于表示十六进制数值。在字符串中,\x
后面跟着两个十六进制数字,表示一个字节的十六进制值。因此,\x45
表示十六进制数值45
,对应 ASCII 字符集中的字符E
。 -
0x45
则是直接表示一个十六进制数值,即45
,没有特殊的转义含义。
在 Python 中,两者都可以用于表示十六进制数值,但 \x45
更常用于字符串中,表示字符 'E'
,而 0x45
则更常用于直接表示数值。