CRC校验代码

一: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; 
}
  1. CRC8_INIT 和 CRC8_TAB:定义了CRC8的初始值和查找表。CRC8_INIT是CRC8计算的初始值,而CRC8_TAB是一个256字节大小的查找表,用于在计算CRC8时快速查找校验值。

  2. Get_CRC8_Check_Sum 函数:用于计算给定数据的CRC8校验值。它接受三个参数:pchMessage(指向数据缓冲区的指针),dwLength(数据长度),ucCRC8(CRC8初始值)。函数通过遍历数据并使用查找表来计算CRC8校验值,最终返回计算得到的CRC8值。

  3. Verify_CRC8_Check_Sum 函数:用于验证数据的CRC8校验值是否正确。它接受两个参数:pchMessage(指向数据缓冲区的指针)和dwLength(数据长度)。函数首先计算数据除去最后一个字节(即CRC8校验值)的CRC8校验值,并将其与数据中的CRC8校验值进行比较,最终返回比较结果(真或假)。

  4. 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
  1. CRC8 和 CRC16 计算函数

    • get_crc8_check_byte(data): 计算给定数据的 CRC8 校验值。
    • get_crc16_check_byte(data): 计算给定数据的 CRC16 校验值。
    • 这两个函数用于计算数据的校验值,以确保数据在传输过程中的完整性。
  2. 初始化串口

    • serial_init(port): 初始化串口通信,返回一个串口对象。
    • 使用 serial.Serial 类初始化串口对象,设置串口号、波特率和超时时间。
  3. 构建帧头

    • get_frame_header(data_length=14): 构建通信帧的帧头部分。
    • 帧头由起始字节(SOF)、数据长度(data_length)、序列号(seq)和CRC8校验值组成。
  4. 发送敌方车辆位置信息

    • send_enemy_location(ser, carID, x, y): 发送敌方车辆位置信息到设备。
    • 构建帧头,添加命令ID、车辆ID和位置坐标(x,y),并计算CRC16校验值后发送。

 

\x450x45 都表示十六进制数值 45,但是在 Python 中,它们的使用上有一些区别:

  1. \x45 是一种特殊的转义字符表示法,用于表示十六进制数值。在字符串中,\x 后面跟着两个十六进制数字,表示一个字节的十六进制值。因此,\x45 表示十六进制数值 45,对应 ASCII 字符集中的字符 E

  2. 0x45 则是直接表示一个十六进制数值,即 45,没有特殊的转义含义。

在 Python 中,两者都可以用于表示十六进制数值,但 \x45 更常用于字符串中,表示字符 'E',而 0x45 则更常用于直接表示数值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/583896.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

张大哥笔记:服务器有挖矿木马程序,该如何处理?

这篇文章发表于2021年&#xff0c;今天借这个平台再发布一下&#xff0c;希望对大家有所帮助&#xff01; 今天收到一个粉丝求助&#xff0c;说收到了阿里云官方短信通知提示有挖矿程序&#xff0c;要求立即整改&#xff0c;否则会关停服务器&#xff0c;以下是我和他的对话内…

机器学习:深入解析SVM的核心概念(问题与解答篇)【二、对偶问题】

对偶问题 **问题一&#xff1a;什么叫做凸二次优化问题&#xff1f;而且为什么符合凸二次优化问题&#xff1f;**为什么约束条件也是凸的半空间&#xff08;Half-Space&#xff09;凸集&#xff08;Convex Set&#xff09;半空间是凸集的例子SVM 约束定义的半空间总结 **问题二…

CTFHub-Web-SSRF

CTFHub-Web-SSRF-WP 一、内网访问 1.题目提示说访问127.0.0.1的flag.php&#xff0c;在URL后面添加路径没想到直接访问成功 二、伪协议读取文件 1.题目提示说访问Web目录下的flag.php&#xff0c;联想到Web目录一般存放于/var/www/html/里&#xff0c;去修改URL尝试进行访问…

【多级缓存】多级缓存OpenResty,Canal,nginx本地缓存

多级缓存 安装OpenRestyOpenResty入门OpenResty获取请求参数OpenResty向tomcat服务器发送请求 在nginx与tomcat端之间添加redis缓存Redis本地缓存缓存同步缓存同步策略基于Canal的异步通知安装Canal Canal客户端 安装OpenResty OpenResty是一个基于 Nginx的高性能 Web 平台&am…

初探 JUC 并发编程:Java 并发包中并发 List 源码剖析

最近在阅读 《Java 并发编程之美》这本书&#xff0c;感觉学到了很多东西&#xff1b;所以我决定将从事书中学到的思想和一些经典的案例整理成博客的形式与大家分享和交流&#xff0c;如果对大家有帮助别忘了留下点赞和关注捏。 第五部分&#xff1a;Java 并发包中并发 List 源…

STM32CubeMX+MDK通过I2S接口进行音频输入输出(全双工读写一个DMA回调)续-音质问题解决总结

一、前言 之前进行了STM32CubeMXMDK通过I2S接口进行音频输入输出&#xff08;全双工读写一个DMA回调&#xff09;的研究总结&#xff1a; https://juejin.cn/post/7339016190612881408#heading-34 后续音质问题解决了&#xff0c;目前测试下来48khz的双声道使用效果很好&…

基于uniapp+微信小程序的智能停车场管理小程序,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

护航智慧交通安全 | 聚铭精彩亮相2024交通科技创新及信创产品推广交流会

4月26日&#xff0c;石家庄希尔顿酒店内&#xff0c;河北省智能交通协会盛大举办2024年度交通科技创新及信创产品推广交流会。聚铭网络受邀参与&#xff0c;携旗下安全产品及解决方案精彩亮相&#xff0c;为智慧交通安全保驾护航。 为深化高速公路创新驱动发展战略&#xff0…

Java网址url工具类

功能描述 无需引入三方依赖文本匹配网址&#xff08;支持多个&#xff09;网址解析&#xff08;包括协议、主机、路径、参数等&#xff09; package com.qiangesoft.image.utils;import org.springframework.util.Assert; import org.springframework.util.CollectionUtils;i…

深度学习基础之《TensorFlow框架(16)—神经网络案例》

一、mnist手写数字识别 1、数据集介绍 mnist数据集是一个经典的数据集&#xff0c;其中包括70000个样本&#xff0c;包括60000个训练样本和10000个测试样本 2、下载地址&#xff1a;http://yann.lecun.com/exdb/mnist/ 3、文件说明 train-images-idx3-ubyte.gz: training s…

C#编程模式之装饰模式

创作背景&#xff1a;朋友们&#xff0c;我们继续C#编程模式的学习&#xff0c;本文我们将一起探讨装饰模式。装饰模式也是一种结构型设计模式&#xff0c;它允许你通过在运行时向对象添加额外的功能&#xff0c;从而动态的修改对象的行为。装饰模式本质上还是继承的一种替换方…

分享三款可以给pdf做批注的软件

PDF文件不像Word一样可以直接编辑更改&#xff0c;想要在PDF文件上进行编辑批注需要用到一些专业的软件&#xff0c;我自己常用的有三款&#xff0c;全都是官方专业正版的软件&#xff0c;功能丰富强大&#xff0c;使用起来非常方便&#xff01; 1.edge浏览器 这个浏览器不仅可…

爬虫实战-房天下(bengbu.zu.fang.com/)数据爬取

详细代码链接https://flowus.cn/hbzx/3c42674d-8e6f-42e3-a3f6-bc1258034676 import requests from lxml import etree #xpath解析库 def 源代码(url): cookies { global_cookie: xeqnmumh38dvpj96uzseftwdr20lvkwkfb9, otherid: b44a1837638234f1a0a15e…

JavaEE 初阶篇-深入了解特殊文件(Properties 属性文件、XML)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Properties 属性文件概述 1.1 Properties 属性文件特性与作用 1.2 使用 Properties 把键值对数据写出到属性文件中 1.3 使用 Properties 读取属性文件里的键值对数…

《动手学深度学习(Pytorch版)》Task03:线性神经网络——4.29打卡

《动手学深度学习&#xff08;Pytorch版&#xff09;》Task03&#xff1a;线性神经网络 线性回归基本元素线性模型损失函数随机梯度下降 正态分布与平方损失 线性回归的从零开始实现读取数据集初始化模型参数定义模型定义损失函数定义优化算法训练 线性回归的简洁实现读取数据集…

c#创建新项目

确保已安装.NET Core SDK。&#xff08;visual studio installer中可安装&#xff09; cmd中先引用到文件夹目录下。 mkdir MyConsoleApp MyConsoleApp是项目文件夹的名字。 mkdir 是一个命令行工具&#xff0c;用于在文件系统中创建新的目录&#xff08;文件夹&#xff09;…

用OpenCV先去除边框线,以提升OCR准确率

在OpenCV的魔力下&#xff0c;我们如魔法师般巧妙地抹去表格的边框线&#xff0c;让文字如诗如画地跃然纸上。 首先&#xff0c;我们挥动魔杖&#xff0c;将五彩斑斓的图像转化为单一的灰度世界&#xff0c;如同将一幅绚丽的油画化为水墨画&#xff0c;通过cv2.cvtColor()函数的…

主机ping不通虚拟机/虚拟机ping不通主机/xhell连接不了虚拟机/win10或win11系统升级导致无法连接到虚拟机

解决方案 重置网卡 找虚拟机ip&#xff0c;第二个inet对应的就是虚拟机ip地址 xshell连接 参考: 主机ping不通虚拟机

认识认识DHCP

文章目录 认识认识DHCP一、什么是DHCP&#xff1f;1.1、为什么要使用DHCP&#xff1f;1.2、DHCP是怎么工作的&#xff1f;1.2.1、客户端首次接入网络的工作原理1.2.2、客户端重用曾经使用过的地址的工作原理1.2.3、客户端更新租期的工作原理 二、配置DHCP Server&#xff0c;为…

电子式汽车机油压力传感器的接线方法及特点

电子式机油压力传感器由厚膜压力传感器芯片、信号处理电路、外壳、固定电路板装置和两根引线&#xff08;信号线和报警线&#xff09;组成。信号处理电路由电源电路、传感器补偿电路、调零电路、电压放大电路、电流放大电路、滤波电路和报警电路组成。 厚膜压力传感器是20世纪…
最新文章