痞子衡随笔:常用的数据传输差错检测技术(1)- 奇偶校验(Parity Check)
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家讲的是嵌入式里数据差错控制技术-重复校验。
在嵌入式应用里,除了最核心的数据处理外,我们还会经常和数据传输打交道。数据传输需要硬件传输接口的支持,串行接口由于占用引脚少的优点目前应用比并行接口广泛,常用的串行接口种类非常多,比如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 <stdint.h>
#include <assert.h>
/*!
* @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)) >> 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 <stdio.h>
#include <stdlib.h>
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。
有没有其他比重复校验法更高效的检错方法?痞子衡在下篇会继续聊。
至此,嵌入式里数据差错控制技术之重复校验痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。
痞子衡随笔:常用的数据传输差错检测技术(1)- 奇偶校验(Parity Check)的更多相关文章
- 痞子衡嵌入式:常用的数据差错控制技术(2)- 奇偶校验(Parity Check)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式里数据差错控制技术-奇偶校验. 在系列第一篇文章里,痞子衡给大家介绍了最简单的校验法-重复校验,该校验法实现简单,检错纠错能力都还不 ...
- 痞子衡嵌入式:走进二维码(QR Code)的世界(1)- 引言
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是走进二维码(QR Code)的世界专题的引言. 如今二维码可以说是深入走进大家的生活了,推送名片.扫码支付都离不开它,大家几乎每天都会和 ...
- 痞子衡嵌入式:我的博文总量终于追平了jicheng0622
自打2016年10月选定清爽又复古的博客园平台作为痞子衡的个人博客主战场之后,痞子衡就一直坚持在博客园首发原创技术文章,然后再同步到其他平台(CSDN,知乎,微信公众号...),在坚持更文近四年半(2 ...
- 痞子衡嵌入式:常用的数据差错控制技术(1)- 重复校验(Repetition Code)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式里数据差错控制技术-重复校验. 在嵌入式应用里,除了最核心的数据处理外,我们还会经常和数据传输打交道.数据传输需要硬件传输接口的支持 ...
- 痞子衡嵌入式:常用的数据差错控制技术(3)- 和校验(Checksum)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式里数据差错控制技术-和校验. 在系列前一篇文章里,痞子衡给大家介绍了比较简单的校验法-奇偶校验,该校验法主要是针对byte传输校验而 ...
- 痞子衡嵌入式:i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad. 最近碰到一个客户,他们在 i.MX ...
- 痞子衡嵌入式:串口调试工具Jays-PyCOM诞生记(3)- 串口功能实现(pySerial)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是串口调试工具Jays-PyCOM诞生之串口功能实现. 串口调试助手是最核心的当然是串口数据收发与显示的功能,Jays-PyCOM借助的是 ...
- 痞子衡嵌入式:从头开始认识i.MXRT启动头FDCB里的lookupTable
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT启动头FDCB里的lookupTable. 一个MCU内部通常有很多外设模块,这些外设模块是各MCU厂商做差异化产品的本质, ...
- 痞子衡嵌入式:嵌入式里串口(UART)自动波特率识别程序设计与实现
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是嵌入式里串口(UART)自动波特率识别程序设计与实现. 串口(UART)是嵌入式里最基础最常用也最简单的一种通讯(数据传输)方式,可以说 ...
随机推荐
- UE4 小笔记
1,设置postprocess材质时使用Add or Update Blendable 用Make PostprocessSetting会报警告,因为C++代码中没有设置为BlueprintReadW ...
- Oracle实战笔记(第七天)之PL/SQL进阶
一.控制结构 控制结构包括:判断语句(条件分支语句).循环语句.顺序控制语句三种. 1.条件分支语句 if--then:简单条件判断 --编写一个过程,可以输入一个雇员名,如果该雇员名的工资低于200 ...
- 洛谷P1233 [木棍加工]
主要思路: 这道题一眼看过去就可以贪心.. 首先可以按L排序.. 显然排序之后我们就可以抛开L不管了.. 然后就可以愉快的贪心了.. 细节: 这道题可以看成用 最少的合法序列(详见原题) 装下所有木棍 ...
- python_计算1+……+100中偶数和
如何计算1+--+100中偶数和? 1. 把奇数去掉,通过if,判断累加数除以2的余数,是否为1,判断是否是奇数 2. 通过continue 跳过对奇数的累加 #!/usr/bin/python3 d ...
- common-logging--源码之SimpleLog
common-logging源码Log接口 在common-logging的源码中,将log核心类抽象成了一个Log接口. 这里贴出Log接口的源码: /* * Licensed to the Apa ...
- junit源码解析--初始化阶段
OK,我们接着上篇整理.上篇博客中已经列出的junit的几个核心的类,这里我们开始整理junit完整的生命周期. JUnit 的完整生命周期分为 3 个阶段:初始化阶段.运行阶段和结果捕捉阶段. 这篇 ...
- Linux指令--性能监控和优化命令相关指令
原文出处:http://www.cnblogs.com/peida/archive/2012/12/05/2803591.html.感谢作者无私分享 性能监控和优化命令相关指令有:top,free,v ...
- Inner Join and Left Join 与条件的结合
在使用关系数据库时,表连接和对结果集的筛选是必不可少的查询技能,对于他们的用法你都搞清楚了么?请让我们一起来过一遍. 表创建与初始化: Inner Join 结果集: 对于Inner Join, 条件 ...
- Linux常用命令(二)--文件目录命令
1. 列表目录命令: 格式: ls [参数] 用于显示文件或目录信息 选项: -l 每行显示一个文件和目录信息(长格式),简写:ll等同于ls -l 注意:当参数是文件时,显示此文件全部信息 当参数是 ...
- Android4.0新控件
谷歌在推出Android4.0的同时推出了一些新控件,Android4.0中最常用的新控件有下面5种. 1. Switch的使用 Switch顾名思义,就是开关的意思,有开和关两种状态. 当Swit ...