大家好,我是痞子衡,是正經(jīng)搞技術的痞子。今天痞子衡給大家講的是嵌入式里數(shù)據(jù)差錯控制技術 - 重復校驗。
在嵌入式應用里,除了最核心的數(shù)據(jù)處理外,我們還會經(jīng)常和數(shù)據(jù)傳輸打交道。數(shù)據(jù)傳輸需要硬件傳輸接口的支持,串行接口由于占用引腳少的優(yōu)點目前應用比并行接口廣泛,常用的串行接口種類非常多,比如 UART,SPI,I2C,USB 等,在使用這些接口傳輸數(shù)據(jù)時避不可免會遇到一個問題,如果傳輸過程中遇到未知硬件干擾發(fā)生 bit 錯誤怎么辦?
痞子衡今天給大家講的就是數(shù)據(jù)傳輸過程中用于差錯檢測的最簡單的方法,即重復校驗法。
一、重復校驗法基本原理
1.1 校驗依據(jù)
重復校驗法的校驗依據(jù)就是判斷重復傳輸?shù)?q 組 n bits 二進制數(shù)據(jù)是否一致。
1.2 重復校驗位
為了實現(xiàn)重復校驗,就是不斷重復傳輸這組 n bits 原始數(shù)據(jù) q 次即可,一次校驗的 q*n bits 數(shù)據(jù)塊中,僅有 n bits 數(shù)據(jù)是原始有效數(shù)據(jù),校驗位就是那些重復的(q-1)*n bits 數(shù)據(jù)。是不是覺得簡單又粗暴?
1.3 校驗方法
假設原始數(shù)據(jù)塊是 X[n-1:0]共 n bits,重復次數(shù)為 q(q 一般為奇數(shù)),按重復傳輸方式,可分為兩個子類:
按 bit 重復:發(fā)送數(shù)據(jù)序列為,q 個 X0(X0X0...),q 個 X1(X1X1...)...,q 個 Xn-1(Xn-1Xn-1...)
按 block 重復:發(fā)送數(shù)據(jù)序列為,第 1 個 X[n-1:0],第 2 個 X[n-1:0]...,第 q 個 X[n-1:0]。
接受端收到數(shù)據(jù)后,逐次比較 q 個重復位,如完全一致,則認為沒有錯差;如不一致,則存在錯誤 bit。如需糾錯的話,原理也很簡單,判斷 q 個重復位里哪種數(shù)據(jù)位出現(xiàn)的次數(shù)多(這里解釋了 q 為何應是奇數(shù))則為原始正確數(shù)據(jù)位。
1.4 C 代碼實現(xiàn)
實際中按 block 重復校驗法應用比較多,此處示例代碼以此為例:
安裝包:codeblocks-17.12mingw-setup.exe
集成環(huán)境:CodeBlocks 17.12 rev 11256
編譯器:GNU GCC 5.1.0
調(diào)試器:GNU gdb (GDB) 7.9.1
// repetition_code.c
//////////////////////////////////////////////////////////
#include
#include
/*!
* @brief 處理按 block 重復的數(shù)據(jù)塊
*
* @param src, 待處理的數(shù)據(jù)塊 .
* @param dest, 處理完成的原始數(shù)據(jù) .
* @param lenInBytes, 待處理的數(shù)據(jù)塊長度 .
* @param repeatTimes, 數(shù)據(jù)重復次數(shù)(假定為奇數(shù)).
* @retval 0, 數(shù)據(jù)無錯誤位 .
* @retval 1, 數(shù)據(jù)有錯誤位且已糾正 .
*/
uint32_t verify_correct_repetition_block(uint8_t *src,
uint8_t *dest,
uint32_t lenInBytes,
uint32_t repeatTimes)
{
assert(repeatTimes % 2);
assert(!(lenInBytes % repeatTimes));
uint32_t result = 0;
uint32_t blockBytes = lenInBytes / repeatTimes;
// 遍歷一個 block 長度里每個 byte
for (uint32_t i = 0; i < blockBytes; i++)
{
// 遍歷當前 byte 的每個 bit
uint8_t correctByte = 0;
for (uint32_t j = 0; j < 8; j++)
{
// 遍歷當前 byte 的所有重復 byte
uint32_t bit1Count = 0;
for (uint32_t k = 0; k < repeatTimes; k++)
{
// 記錄所有重復 byte 中當前 bit 為 1 的個數(shù)
uint8_t countByte = *(src + i + k * blockBytes);
bit1Count += (countByte & (0x1u << j)) >> j;
}
// 當 bit1 出現(xiàn)半數(shù)則將當前 bit 認定為 1
if (bit1Count > (repeatTimes / 2))
{
correctByte |= 0x1u << j;
}
// 首次發(fā)現(xiàn)錯誤 bit 時,置位 result
if ((!result) && (bit1Count !=0) && bit1Count != repeatTimes)
{
result = 1;
}
}
// 將校驗后的 byte 存入 dest
*(dest + i) = correctByte;
}
return result;
}
// main.c
//////////////////////////////////////////////////////////
#include "repetition_code.h"
#include
#include
int main(void)
{
uint8_t src[3][4] = {{0x32, 0x33, 0x04, 0x08},
{0x32, 0x83, 0x04, 0xd8},
{0x31, 0x33, 0x04, 0xe8}};
uint8_t dest[4];
uint32_t result = verify_correct_repetition_block((uint8_t *)src, dest, sizeof(src), sizeof(src) / sizeof(src[0]));
printf("result = %d/n", result);
for (uint32_t i = 0; i < sizeof(dest); i++)
{
printf("dest[%d] = 0x%x/n", i, dest[i]);
}
return 0;
}
1.5 行業(yè)應用
實際上本文所講的單純的重復校驗法行業(yè)因為效率的原因,行業(yè)里較少應用,其改進版的實現(xiàn) RA Codes 應用在了 FlexRay 協(xié)議里。
二、重復校驗法失效分析
重復校驗實現(xiàn)非常簡單,具有比較理想的檢錯能力,但效率太低,并未得到廣泛使用。即便犧牲了效率,但重復校驗法也存在如下 2 個缺陷,導致其檢錯糾錯并不可靠:
當重復 bit 全部發(fā)生錯誤時,會被誤認為沒有錯誤 bit 發(fā)生。
當錯誤 bit 出現(xiàn)概率大于原始 bit 時,在糾錯時會認定錯誤 bit 是原始 bit。
有沒有其他比重復校驗法更高效的檢錯方法?痞子衡在下篇會繼續(xù)聊。
至此,嵌入式里數(shù)據(jù)差錯控制技術之重復校驗痞子衡便介紹完畢了,掌聲在哪里~~~
審核編輯 黃昊宇
-
控制技術
+關注
關注
3文章
352瀏覽量
33632
發(fā)布評論請先 登錄
高壓放大器在鎖相環(huán)穩(wěn)定重復頻率研究中的應用

常用電器控制電路精選
基于Verilog語言實現(xiàn)CRC校驗

ADS131B04-Q1 SPI通信時,為什么無法得到正常的CRC校驗?
使用stm32來控制并讀取ADS8686S數(shù)據(jù)時出現(xiàn)AIN0-7八個通道數(shù)據(jù)出現(xiàn)交替性重復,為什么?
ADS131采集數(shù)據(jù)重復的原因?
飛凌嵌入式ElfBoard ELF 1板卡-串口通訊編程示例之串口硬件原理
基于GPU器件行為的創(chuàng)新分布式功能安全機制為智能駕駛保駕護航

HDMD-H1型SF6氣體密度繼電器校驗裝置的操作方式說明

LP886-Q1在大屏汽車導航的應用及其EEPROM燒錄校驗方法

AS3933 與SI3933 技術對比資料
重復接地的作用與實施
全自動密度校驗儀操作方法——每日了解電力知識

便攜式互感器校驗裝置的使用方法——每日了解電力知識

評論