laitimes

The validation algorithm _CRC C instance

author:DS Xiaolongge

1. Introduction to CRC

Cyclic Redundancy Check (CRC) is a commonly used error detection technique to verify whether an error has occurred during transmission or storage. It generates a check value by performing a series of calculations and comparisons on the data and attaches it to the data. The receiver can use the same algorithm to validate the received data and then compare it with the received check value to determine if there are any errors in the data.

CRC checks are typically used in the following areas:

(1) Reliability of data transmission: When data is transmitted through media or networks, noise, interference, or other transmission errors may occur. By adding a CRC checksum to the data, the receiver can detect if an error has occurred during transmission and take appropriate action, such as requesting that the data be retransmitted.

(2) Integrity detection of storage media: When reading or writing data on storage media, errors such as bit flip and media failure may occur. By using CRC validation at data storage, these errors can be detected when the data is read and the integrity of the data is guaranteed.

(3) Network communication protocols: Many network communication protocols (such as Ethernet, WiFi, USB, etc.) use CRC verification as part of the data frame to ensure that the transmitted data is accurate. After receiving the data frame, the receiver uses a CRC check to verify the integrity of the data.

In the project, CRC calibration is widely used in various communication systems, storage systems, and data transmission systems. By using CRC validation, you can improve the reliability of your data and reduce errors during transmission or storage. It can detect errors at the data bit level and provide a degree of data integrity assurance. CRC verification plays an important role in ensuring data reliability and integrity, especially in application scenarios with high requirements for data integrity.

2. Sample code

The following C code shows how to get the CRC check value of a piece of data:

#include <stdio.h>
#include <stdint.h>

// CRC校验函数
uint16_t crc16(uint8_t *data, int length)
{
    uint16_t crc = 0xFFFF;
    
    for (int i = 0; i < length; i++)
    {
        crc ^= data[i];
        
        for (int j = 0; j < 8; j++)
        {
            if (crc & 1)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    
    return crc;
}

// 封装的CRC校验函数调用
uint16_t calculateCRC(uint8_t *data, int length)
{
    return crc16(data, length);
}

int main()
{
    uint8_t message[] = {0x01, 0x02, 0x03, 0x04, 0x05};
    int length = sizeof(message) / sizeof(message[0]);
    
    uint16_t crc = calculateCRC(message, length);
    printf("CRC: 0x%04X\n", crc);
    
    return 0;
}           

In the above code, the crc16 function implements the calculation logic of the CRC check. The commonly used CRC-16 algorithm (0xA001 polynomial) is used. The calculateCRC function is an encapsulation of crc16 and is used to call the CRC function and return the check result.

In the main function, the CRC check value for a given data is calculated by calling the calculateCRC function and the result is printed.

The CRC checksum function and encapsulation function in the code are calculated based on the data type of unsigned 8-bit byte and unsigned 16-bit integer.

3. Case: Data verification

Scenario: In microcontroller communication, the microcontroller needs to send a piece of data to the host computer. For example, stored in char buff[1024]; in this array. Two functions need to be encapsulated, the single-chip microcomputer side calls the function to perform CRC verification on this data, encapsulate the check value, and then the host computer verifies the CRC after receiving the data, and verifies whether the data is transmitted correctly.

3.1 Sender (Encapsulation Checksum)

#include <stdio.h>
#include <stdint.h>

// CRC校验函数
uint16_t crc16(uint8_t *data, int length)
{
    uint16_t crc = 0xFFFF;
    
    for (int i = 0; i < length; i++)
    {
        crc ^= data[i];
        
        for (int j = 0; j < 8; j++)
        {
            if (crc & 1)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    
    return crc;
}

// 封装CRC校验值到数据中
void appendCRC(uint8_t *data, int length)
{
    uint16_t crc = crc16(data, length);
    data[length] = crc & 0xFF; // 将低8位放入数据末尾
    data[length + 1] = crc >> 8; // 将高8位放入数据末尾的下一个位置
}

int main()
{
    uint8_t buff[1024] = {0x01, 0x02, 0x03, 0x04, 0x05}; // 原始数据
    int length = 5; // 数据长度
    
    // 在原始数据后追加CRC校验值
    appendCRC(buff, length);
    
    // 输出发送的数据(包括CRC校验值)
    printf("发送的数据:");
    for (int i = 0; i < length + 2; i++)
    {
        printf("%02X ", buff[i]);
    }
    printf("\n");
    
    return 0;
}           

In the sender's code, use the appendCRC function to append the CRC checksum to the end of the original data.

3.2 Receiver (Validation Data)

#include <stdio.h>
#include <stdint.h>

// CRC校验函数
uint16_t crc16(uint8_t *data, int length)
{
    uint16_t crc = 0xFFFF;
    
    for (int i = 0; i < length; i++)
    {
        crc ^= data[i];
        
        for (int j = 0; j < 8; j++)
        {
            if (crc & 1)
            {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else
            {
                crc >>= 1;
            }
        }
    }
    
    return crc;
}

// 验证CRC校验值是否正确
int verifyCRC(uint8_t *data, int length)
{
    uint16_t crc = crc16(data, length - 2); // 去除数据末尾的CRC校验值
    
    // 获取接收到的CRC校验值
    uint16_t receivedCRC = (data[length - 1] << 8) | data[length - 2];
    
    // 比较计算得到的CRC校验值与接收到的CRC校验值
    if (crc == receivedCRC)
    {
        return 1; // 校验通过
    }
    else
    {
        return 0; // 校验失败
    }
}

int main()
{
    uint8_t receivedData[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0xC2, 0x45}; // 收到的数据(包括CRC校验值)
    int length = sizeof(receivedData) / sizeof(receivedData[0]);
    
    // 验证CRC校验值是否正确
    int crcResult = verifyCRC(receivedData, length);
    
    if (crcResult)
    {
        printf("CRC校验通过\n");
        // TODO: 进一步处理正确的数据
    }
    else
    {
        printf("CRC校验失败\n");
        // TODO: 处理校验失败的情况
    }
    
    return 0;
}           

In the receiver's code, use the verifyCRC function to verify that the received data has the correct CRC check value. If the verification passes, further data processing operations can be performed; If the verification fails, you can handle the exception.

The CRC check function in the example is calculated based on the data type of unsigned 8-bit byte and unsigned 16-bit integer. It can be appropriately modified according to actual needs to adapt to different data types and CRC algorithms.