大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家讲的是嵌入式里数据差错控制技术 - 重复校验。
在嵌入式应用里,除了最核心的数据处理外,我们还会经常和数据传输打交道。数据传输需要硬件传输接口的支持,串行接口由于占用引脚少的优点目前应用比并行接口广泛,常用的串行接口种类非常多,比如 uart,spi,i2c,usb 等,在使用这些接口传输数据时避不可免会遇到一个问题,如果传输过程中遇到未知硬件干扰发生 bit 错误怎么办?
痞子衡今天给大家讲的就是数据传输过程中用于差错检测的最简单的方法,即重复校验法。
一、重复校验法基本原理
1.1 校验依据
重复校验法的校验依据就是判断重复传输的 q 组 n bits 二进制数据是否一致。
1.2 重复校验位
为了实现重复校验,就是不断重复传输这组 n bits 原始数据 q 次即可,一次校验的 q*n bits 数据块中,仅有 n bits 数据是原始有效数据,校验位就是那些重复的(q-1)*n bits 数据。是不是觉得简单又粗暴?
1.3 校验方法
假设原始数据块是 x[n-1:0]共 n bits,重复次数为 q(q 一般为奇数),按重复传输方式,可分为两个子类:
按 bit 重复:发送数据序列为,q 个 x0(x0x0...),q 个 x1(x1x1...)...,q 个 xn-1(xn-1xn-1...)
按 block 重复:发送数据序列为,第 1 个 x[n-1:0],第 2 个 x[n-1:0]...,第 q 个 x[n-1:0]。
接受端收到数据后,逐次比较 q 个重复位,如完全一致,则认为没有错差;如不一致,则存在错误 bit。如需纠错的话,原理也很简单,判断 q 个重复位里哪种数据位出现的次数多(这里解释了 q 为何应是奇数)则为原始正确数据位。
1.4 c 代码实现
实际中按 block 重复校验法应用比较多,此处示例代码以此为例:
安装包:codeblocks-17.12mingw-setup.exe
集成环境:codeblocks 17.12 rev 11256
编译器:gnu gcc 5.1.0
调试器:gnu gdb (gdb) 7.9.1
// repetition_code.c
//////////////////////////////////////////////////////////
#include
#include
/*!
* @brief 处理按 block 重复的数据块
*
* @param src, 待处理的数据块 .
* @param dest, 处理完成的原始数据 .
* @param leninbytes, 待处理的数据块长度 .
* @param repeattimes, 数据重复次数(假定为奇数).
* @retval 0, 数据无错误位 .
* @retval 1, 数据有错误位且已纠正 .
*/
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 的个数
uint8_t countbyte = *(src + i + k * blockbytes);
bit1count += (countbyte & (0x1u j;
}
// 当 bit1 出现半数则将当前 bit 认定为 1
if (bit1count > (repeattimes / 2))
{
correctbyte |= 0x1u << j;
}
// 首次发现错误 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 行业应用
实际上本文所讲的单纯的重复校验法行业因为效率的原因,行业里较少应用,其改进版的实现 ra codes 应用在了 flexray 协议里。
二、重复校验法失效分析
重复校验实现非常简单,具有比较理想的检错能力,但效率太低,并未得到广泛使用。即便牺牲了效率,但重复校验法也存在如下 2 个缺陷,导致其检错纠错并不可靠:
当重复 bit 全部发生错误时,会被误认为没有错误 bit 发生。
当错误 bit 出现概率大于原始 bit 时,在纠错时会认定错误 bit 是原始 bit。
有没有其他比重复校验法更高效的检错方法?痞子衡在下篇会继续聊。
至此,嵌入式里数据差错控制技术之重复校验痞子衡便介绍完毕了,掌声在哪里~~~
腾讯行人重识别算法突破成世界第一
RealNetworks,“5G+超高清视频”领跑2019世界5G大会
POS与POW的中心化问题探讨
这条消息米粉会激动,小米6或将与小米平板3齐发
专家表示8K市场还需要很长时间才能够爆发
常用的数据差错控制技术(1)-重复校验
如何区分SMA、3.5mm、2.92mm、2.4mm、1.85mm这五种常见射频接头
恒温恒湿机、恒温恒湿试验箱、恒湿恒湿箱、恒温恒湿又名环境试验
个性定制需求的冰箱产品将会成为冰箱产品的另一个发展方向
2023年扫地机器人销量下滑,同比下降了11.4%
胆机单管放大输出与推挽放大输出
充分利用16 GT/s PCIe第4代带宽
电阻综合知识
eSPI接口通道功能解析
食品接触材料迁移池的主要参数及技术特征
东航与GE签署全面数字化解决分析服务协议
七天物联网智能家居实战学习笔记(五)
户外LED显示屏的生产过程
智能ai音响哪个牌子好_最新十大智能音箱排行榜
美国密苏里大学开发出一种能捕获超过90%光能量的柔软太阳能薄片