Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

CRC là gì

CRC là 1 thuật toán để kiểm tra lỗi dữ liệu trên đường truyền.

Khoá học lập trình STM32 nâng cao Ngọc Tuấn


Tại sao lại phải dùng CRC?
Giả sử, ta cần truyền 1 byte 0x16 qua giao thức UART

0001 0110 0101 0110


Bên truyền Bên nhận

Ta thấy trường hợp đường truyền bị nhiễu sẽ đẫn đến bên nhận nhận không đúng dữ
liệu từ bên phát. Như vậy nếu ta lấy kết quả này đem đi xử lí thì sẽ rất nguy hiểm.
Như vậy ta cần phải có cơ chế kiểm tra dữ liệu trên đường truyền để có thể đưa ra
phương án như là yêu cẩu gửi lại hoặc bỏ qua dữ liệu nhận được.

Câu hỏi: Các bạn hãy liệt kê các phương pháp check dữ liệu mà các bạn biết?
Khoá học lập trình STM32 nâng cao Ngọc Tuấn
Phương pháp chung để kiểm tra lỗi
Giả sử ta cần gửi 1 mảng có dữ liệu như sau:

uint8_t arr[] = { 0x01, 0x44, 0x40, 0x67, 0x78 };

0x01 0x44 0x40 0x67 0x78 0x01 0x44 0x45 0x67 0x78

Bên truyền Bên nhận

Câu hỏi: Liệu bên nhận có biết mình nhận sai dữ liệu?
Khoá học lập trình STM32 nâng cao Ngọc Tuấn
Phương pháp chung để kiểm tra lỗi
• Như vậy để biết được dữ liệu có đúng hay không người ta sẽ gửi kèm n byte check
(thông thường từ 1 → 4 byte) kèm với data. Vậy byte check này có giá trị bao nhiêu?
Tuỳ thuộc vào thuật toán check lỗi sẽ ra giá trị và độ dài số byte check khác.

• Công thức chung:

Thuật toán CRC, checksome … Dữ liệu


Dữ liệu cần gửi
kiểm tra

• Khi gửi đi ta sẽ gửi kèm các byte check

N byte data N byte check N byte data N byte check


Dữ liệu Dữ liệu
Dữ liệu cần gửi Dữ liệu nhận được
kiểm tra kiểm tra
Khoá học lập trình STM32 nâng cao Ngọc Tuấn
Phương pháp chung để kiểm tra lỗi
• Trường hợp nhận đúng dữ liệu

0x01 0x44 0x40 0x67 0x78 0x56 0x67 0x01 0x44 0x40 0x67 0x78 0x56 0x67

• Trường hợp nhận sai dữ liệu

0x01 0x44 0x40 0x67 0x78 0x56 0x67 0x01 0x44 0x40 0x67 0x78 0x56 0x67

Khoá học lập trình STM32 nâng cao Ngọc Tuấn


Sơ đồ khối kiểm tra lỗi
Dữ liệu cần Nhận được dữ
truyền liệu

Lấy số byte nhận


Đưa vào bộ tạo mã được – n byte check (
check lỗi gọi là x byte)

Đưa x byte vào bộ


tạo mã
Tạo ra n byte check

Tạo ra n byte check

Truyền data + n
byte check lỗi So sánh n byte
check với n
byte cuối ở dữ
liệu nhận đươc
Khoá học lập trình STM32 nâng cao Ngọc Tuấn
Sơ đồ khối kiểm tra lỗi Byte lỗi

Dữ liệu cần Ví dụ truyền 3 byte : Nhận được dữ Giả sử bên nhận sẽ nhận được
truyền A = { 0x01, 0x44, 0x40}; liệu A= { 0x01, 0x35, 0x40, 0x78};

Lấy số byte nhận Lấy 4 - 1 byte check


Đưa vào bộ tạo mã Đưa 3 byte vào bộ tạo mã check được – n byte check ( B= { 0x01, 0x35, 0x40};
check lỗi A = { 0x01, 0x44, 0x40}; gọi là x byte) // không có byte cuối 0x78

Đưa x byte vào bộ Đưa 3 byte vào bộ tạo mã


tạo mã B= { 0x01, 0x35, 0x40};
Tạo thêm 1 byte check
Tạo ra n byte check B = 0x78 Tạo ra 1 byte check
C = 0x65 (vì cùng 1 thuật toán
Tạo ra n byte check
tạo mã, nếu như dữ liệu đầu vào
giống nhau thì giá trị byte check
Truyền data + n sẽ như nhau, ở đây dữ liệu khác
Truyền bộ đệm C =A + B
byte check lỗi So sánh n byte với khi truyền sang nên giá trị
C= { 0x01, 0x44, 0x40, 0x78};
check với n byte check sẽ khác )
byte cuối ở dữ
liệu nhận đươc
So sánh byte check C: 0x65 với 0x78 bên kia
Khoá học lập trình STM32 nâng
Ta thấy caonhau, nên data nhận được không đúng với data truyền sang
khác Ngọc Tuấn
Thuật toán CRC
“ Giá trị CRC chính là số dư của dữ liệu với đa thức sinh ”

Đa thức sinh tổng quát của bộ tính CRC-n như sau:

Trong đó:
❖ 𝑎𝑛 là 1 hoặc 0.

❖ Chuỗi bit của đa thức sinh có các cách biểu diễn sau:

• Cách biểu diễn thông thường (Trong 1 đa thức sinh 𝑎𝑛 luôn bằng 1, bit cao nhất sẽ bị loại bỏ
các giá trị sắp xếp bình thường 𝑎𝑛−1 . . 𝑎0 )

• Cách biểu diễn đảo ngược (Trong 1 đa thức sinh 𝑎𝑛 luôn bằng 1, bit cao nhất sẽ bị loại bỏ
các giá trị sắp xếp theo chiều người lại tử 𝑎0 . . 𝑎𝑛−1 )

Khoá học lập trình STM32 nâng cao Ngọc Tuấn


Thuật toán CRC
Ví dụ: Ta có đa thức sinh sau

 Chuỗi bit đa thức sinh sẽ là:


- Cách biểu diễn thông thường: 11010101.
- Cách biểu diễn đảo ngược : 10101011.

Một số đa thức sinh phổ biến

Xem thêm đa thức sinh tại: https://vi.wikipedia.org/wiki/Cyclic_Redundancy_Check


Khoá học lập trình STM32 nâng cao Ngọc Tuấn
Thuật toán CRC

Đa thức sinh
Dữ liệu cần truyền

• Tiến hành phép chia lây dư Message


cho Generator Polynomial phần dư
thu được chính là giá trị CRC Giá trị CRC thu được
Khoá học lập trình STM32 nâng cao Ngọc Tuấn
Chương trình CRC-8
#define POLYNOMIAL 0xD8

uint8_t crc8(uint8_t const message)


{
uint8_t remainder = 0;
remainder = message;
for (uint8_t bit = 8; bit > 0; --bit)
{
if (remainder & 0x80)
{
remainder ^= POLYNOMIAL;
}
remainder = (remainder << 1);
}
return remainder;
}

Link tham khảo: https://barrgroup.com/embedded-systems/how-to/crc-calculation-c-code


Khoá học lập trình STM32 nâng cao Ngọc Tuấn
Chương trình CRC tổng quát
typedef uint8_t crc; // typedef uint16_t crc; typedef uint32_t crc;
#define WIDTH (8 * sizeof(crc))
#define TOPBIT (1 << (WIDTH - 1))
#define POLYNOMIAL 0xD8

crc crc_cal(uint8_t const message[], int nBytes)


{
crc remainder = 0;
for (int byte = 0; byte < nBytes; ++byte)
{
remainder ^= (message[byte] << (WIDTH - 8));
for (uint8_t bit = 8; bit > 0; --bit)
{
if (remainder & TOPBIT){
remainder = (remainder << 1) ^ POLYNOMIAL;
}
else {
remainder = (remainder << 1);
}
}
}
return (remainder);
}
Khoá học lập trình STM32 nâng cao Ngọc Tuấn

You might also like