TRAVEL
Click “Yunlong Sect”to follow us
Content
CRC (Cyclic Redundancy Check) is a widely used error detection mechanism for data transmission and storage, especially in automotive embedded systems to ensure the integrity of critical information such as CAN bus and sensor data. Today, we will mainly introduce CRC checks through example programs..

1. Principle of CRC Check

Detailed explanation of CRC8 algorithm (using polynomial 0x07 as an example)
Calculation Steps: 1. Initialize the CRC register to the initial value (usually 0x00) 2. For each byte in the data: a. XOR with the CRC register b. Perform 8 bit shifts on the result: if the highest bit is 1: left shift and XOR with the polynomial if the highest bit is 0: just left shift The final value in the CRC register is the checksum

2. Example Demonstration
Example demonstration: Calculate the CRC8 of “AB”
Data: A(0x41), B(0x42)
Step 1: Process the first byte ‘A’ (0x41)
Initialization: CRC = 0x00 XOR: 0x00 ^ 0x41 = 0x41 Bit Processing: 1. 0x41 (01000001) -> Highest bit 0 -> Left shift: 0x82 2. 0x82 (10000010) -> Highest bit 1 -> Left shift: 0x04 XOR 0x07: 0x04 ^ 0x07 = 0x03 3. 0x03 (00000011) -> Highest bit 0 -> Left shift: 0x06 4. 0x06 (00000110) -> Highest bit 0 -> Left shift: 0x0C 5. 0x0C (00001100) -> Highest bit 0 -> Left shift: 0x18 6. 0x18 (00011000) -> Highest bit 0 -> Left shift: 0x30 7. 0x30 (00110000) -> Highest bit 0 -> Left shift: 0x60 8. 0x60 (01100000) -> Highest bit 0 -> Left shift: 0xC0 After processing 'A': CRC = 0xC0
Step 2: Process the second byte ‘B’ (0x42)
XOR: 0xC0 ^ 0x42 = 0x82 Bit Processing: 1. 0x82 (10000010) -> Highest bit 1 -> Left shift: 0x04 XOR 0x07: 0x04 ^ 0x07 = 0x03 2. 0x03 (00000011) -> Highest bit 0 -> Left shift: 0x06 3. 0x06 (00000110) -> Highest bit 0 -> Left shift: 0x0C 4. 0x0C (00001100) -> Highest bit 0 -> Left shift: 0x18 5. 0x18 (00011000) -> Highest bit 0 -> Left shift: 0x30 6. 0x30 (00110000) -> Highest bit 0 -> Left shift: 0x60 7. 0x60 (01100000) -> Highest bit 0 -> Left shift: 0xC0 8. 0xC0 (11000000) -> Highest bit 1 -> Left shift: 0x80 XOR 0x07: 0x80 ^ 0x07 = 0x87 Final CRC: 0x87
C Language Program
#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <time.h>#include <string.h>// CRC8 polynomial definition (0x07: x^8 + x^2 + x + 1)#define CRC8_POLY 0x07#define CRC8_INIT 0x00// Direct calculation method to implement CRC8uint8_t crc8_direct(const uint8_t *data, size_t len) { uint8_t crc = CRC8_INIT; size_t i = 0; uint8_t bit = 0; for ( i = 0; i < len; i++) { crc ^= data[i]; for ( bit = 0; bit < 8; bit++) { if (crc & 0x80) { crc = (crc << 1) ^ CRC8_POLY; } else { crc <<= 1; } } } return crc;}// Generate CRC8 lookup tablevoid generate_crc8_table(uint8_t *table) {uint16_t i = 0;uint8_t bit = 0; for ( i = 0; i < 256; i++) { uint8_t crc = i; for ( bit = 0; bit < 8; bit++) { if (crc & 0x80) { crc = (crc << 1) ^ CRC8_POLY; } else { crc <<= 1; } } table[i] = crc; }}// Lookup method to implement CRC8uint8_t crc8_table(const uint8_t *data, size_t len) { static uint8_t table[256]; static int initialized = 0; size_t i = 0; if (!initialized) { generate_crc8_table(table); initialized = 1; } uint8_t crc = CRC8_INIT; for ( i = 0; i < len; i++) { crc = table[crc ^ data[i]]; } return crc;}// Print data packetvoid print_packet(const uint8_t *data, size_t len) {size_t i = 0; for ( i = 0; i < len; i++) { printf("%02X ", data[i]); }}// Demonstrate CRC check for CAN framevoid can_frame_demo() { // Simulate CAN frame data (ID: 0x123, Data: 0x11, 0x22, 0x33, 0x44) uint8_t can_frame[] = {0x01, 0x23, 0x11, 0x22, 0x33, 0x44}; size_t len = sizeof(can_frame); // Calculate CRC uint8_t crc = crc8_table(can_frame, len); // Create complete frame (data + CRC) uint8_t full_frame[sizeof(can_frame) + 1]; memcpy(full_frame, can_frame, len); full_frame[len] = crc; printf("\nCAN frame example:\n"); printf("Original frame: "); print_packet(can_frame, len); printf("\nCalculated CRC: 0x%02X\n", crc); printf("Complete frame: "); print_packet(full_frame, len + 1); // Simulate receiving end verification uint8_t received_crc = full_frame[len]; uint8_t calculated_crc = crc8_table(full_frame, len); // Calculate CRC for data part printf("\n\nReceiving end verification:"); if (received_crc == calculated_crc) { printf(" CRC check successful! Data is intact\n"); } else { printf(" CRC check failed! Data is corrupted\n"); } // Simulate transmission error full_frame[2] ^= 0x80; // Flip one bit uint8_t error_crc = crc8_table(full_frame, len); // Recalculate printf("\nSimulated transmission error:"); if (received_crc == error_crc) { printf(" Error not detected!\n"); } else { printf(" CRC detected an error! (Original CRC:0x%02X, Calculated CRC:0x%02X)\n", received_crc, error_crc); }}int main() { srand(time(NULL)); // Initialize random seed printf("================ CRC8 Check Algorithm Demonstration ================\n"); // Demonstration example: Calculate CRC of "AB" const char test_data[] = "AB"; size_t len = strlen(test_data); int i = 0; size_t j = 0; uint8_t crc_direct = crc8_direct((uint8_t*)test_data, len); uint8_t crc_table = crc8_table((uint8_t*)test_data, len); printf("Example data: '%s' (0x41, 0x42)\n", test_data); printf("Direct calculation CRC: 0x%02X\n", crc_direct); printf("Lookup method CRC : 0x%02X\n", crc_table); // Random test data const size_t num_tests = 3; const size_t max_len = 8; printf("\nRandom data tests:"); for ( i = 0; i < num_tests; i++) { size_t len = 3 + rand() % (max_len - 2); // Random length 3-8 bytes uint8_t data[max_len]; // Generate random data for ( j = 0; j < len; j++) { data[j] = rand() & 0xFF; } // Calculate CRC uint8_t crc_d = crc8_direct(data, len); uint8_t crc_t = crc8_table(data, len); // Print results printf("\nTest %d: Data[%zu bytes]: ", i+1, len); print_packet(data, len); printf("\nDirect method: 0x%02X, Lookup method: 0x%02X - ", crc_d, crc_t); if (crc_d == crc_t) { printf("Results match"); } else { printf("Results do not match!"); } } // Empty data test printf("\n\nBoundary test:"); uint8_t empty = crc8_direct(NULL, 0); printf("\nEmpty data CRC: 0x%02X (should be initial value 0x00)", empty); // Single byte test uint8_t single_byte = 0x55; uint8_t crc_single = crc8_direct(&single_byte, 1); printf("\nSingle byte (0x55) CRC: 0x%02X", crc_single); // CAN frame example can_frame_demo(); printf("\n\n================ Demonstration End ================\n"); return 0;}
Program output example

================ CRC8 Check Algorithm Demonstration ================Example data: 'AB' (0x41, 0x42)Direct calculation CRC: 0x87Lookup method CRC : 0x87Random data tests:Test 1: Data[5 bytes]: 7F A3 4C 11 D9 Direct method: 0x2D, Lookup method: 0x2D - Results matchTest 2: Data[4 bytes]: 55 33 F0 2A Direct method: 0xCE, Lookup method: 0xCE - Results matchTest 3: Data[6 bytes]: 01 9B 44 E7 5D 88 Direct method: 0x3B, Lookup method: 0x3B - Results matchBoundary test:Empty data CRC: 0x00 (should be initial value 0x00)Single byte (0x55) CRC: 0x61CAN frame example:Original frame: 01 23 11 22 33 44Calculated CRC: 0x9FComplete frame: 01 23 11 22 33 44 9FReceiving end verification: CRC check successful! Data is intactSimulated transmission error: CRC detected an error! (Original CRC:0x9F, Calculated CRC:0x4F)================ Demonstration End ================

3. CRC Applications in Automotive Embedded Systems
3.1 Typical Use Cases
-
CAN Bus Communication:
-
Each frame of data contains a CRC check field
-
Detect bit flip errors during transmission
-
Example: Key data such as engine speed, brake status, etc.
ECU Firmware Verification:
Verify firmware integrity during software updates
Prevent system failures caused by erroneous code writing
Sensor Data Verification:
Key data such as wheel speed sensors, temperature sensors, etc.
Ensure safety systems receive reliable data
Diagnostic Protocols (UDS/KWP2000):
Integrity check of diagnostic requests and responses
Ensure correct execution of diagnostic commands
3.2 Characteristics and Advantages of CRC Checks
-
Error Detection Capability:
-
Detect all single-bit errors
-
Detect all double-bit errors (if the polynomial is chosen appropriately)
-
Detect any odd number of errors
-
Detect most burst errors
Computational Efficiency:
Lookup method is efficient, suitable for embedded systems
Hardware acceleration support (many MCUs have built-in CRC calculation units)
Flexibility:
Can adapt to different applications through different polynomials
Parameters such as initial value and output XOR value can be adjusted
Space Efficiency:
CRC8 requires only 1 byte of additional space
Suitable for space-constrained embedded environments
In automotive embedded systems, CRC checks are a key technology for ensuring data integrity, especially in safety-critical systems (such as brake control, airbags, etc.). Through this example, we have demonstrated the theoretical basis of CRC, the actual calculation process, and the C language implementation, as well as how to apply this technology in automotive electronic systems.
This content is sourced from the internet for reference and learning purposes. If there are any copyright issues with the content or images, please contact us for processing, and we will delete them within 24 hours. Author | Guo Zhilong Editor | Guo Zhilong Proofreader | Guo Zhilong
Reward, share, like, and follow,Thank you for your support and attention!
Grow together with the sect!There is a path in the mountain of books, diligence is the wayThe sea of learning is boundless, hard work is the boat