大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家讲的是嵌入式里数据差错控制技术-奇偶校验

  在系列第一篇文章里,痞子衡给大家介绍了最简单的校验法-重复校验,该校验法实现简单,检错纠错能力都还不错,但传输效率实在是不高,在效率至上的大背景下,这种方法是不能容忍的。今天痞子衡继续给大家介绍另一种也非常简单但效率较高的校验法-即奇偶校验法。

一、奇偶校验法基本原理

1.1 校验依据

  奇偶校验法的校验依据就是判断一次传输的一组二进制数据中bit "1"的奇偶性(奇数个还是偶数个)在传输前后是否一致,所以其实奇偶检验法有两个子类:

  • 奇校验:如果以二进制数据中1的个数是奇数为依据,则是奇校验
  • 偶校验:如果以二进制数据中1的个数是偶数为依据,则是偶校验

  一般在同步传输方式中常采用奇校验,而在异步传输方式中常采用偶校验。

1.2 奇偶校验位

  为了实现奇偶校验,通常会在传输的这组二进制数据中插入一个额外的奇偶校验位(bit),用它来确保发送出去的这组二进制数据中“1”的个数为奇数或偶数。

  划重点,奇偶校验位并不是用来标记原始传输数据中1的个数是奇数还是偶数,而是用来确保原始数据加上奇偶校验位后的合成数据中1的个数是奇数或者偶数。

1.3 校验方法

  常用的奇偶校验共有三种:水平奇偶校验,垂直奇偶校验校验和水平垂直奇偶校验。以对32位数据:10100101 10111001 10000100 00011010进行校验为例讲解:

  • 水平奇偶校验:对每一种数据的编码添加校验位,使信息位与校验位处于同一行。
原始数据 水平奇校验位 水平偶校验位
10100101 1 0
10111001 0 1
10000100 1 0
00011010 0 1

  所以加上水平偶校验位后应传输的数据是:101001010 101110011 100001000 000110101

  • 垂直奇偶校验:将数据分为若干组,一组一行,再加上一行校验位,针对每一列采样奇校验或偶校验。
编码分类 垂直奇校验 垂直偶校验
原始数据 10100101 10100101
10111001 10111001
10000100 10000100
00011010 00011010
校验位 01111101 10000010

  所以加上垂直偶校验位后应传输的数据是:10100101 10111001 10000100 0001101010000010

  • 水平垂直奇偶校验:也叫Hamming Code,其是在水平和垂直方向上进行双校验,其不仅可以检测2bit错误的具体位置,还可纠正1bit错误,常用于NAND Flash里。这部分不属于本文要讨论的内容,痞子衡后续会专门介绍Hamming Code。

1.4 C代码实现

  实际中水平校验法应用比较多,此处示例代码以水平奇校验为例:

安装包:codeblocks-17.12mingw-setup.exe

集成环境:CodeBlocks 17.12 rev 11256

编译器:GNU GCC 5.1.0

调试器:GNU gdb (GDB) 7.9.1

// parity_check.c
//////////////////////////////////////////////////////////
#include <stdbool.h>
#include <stdint.h> /*!
* @brief 判断当前byte的极性是否为奇
*
* @param byte, 待计算奇偶性的数据.
* @retval ture, byte极性(含1的个数)为奇数.
* @retval false, byte极性(含1的个数)为偶数.
*/
bool is_byte_odd_parity(uint8_t byte)
{
bool parity = false;
// 普通算法-byte逐位异或(需循环8次)
/*
for (uint8_t i = 0; i < 8; i++)
{
parity ^= byte & 0x01u;
byte >>= 1;
}
*/
// 效率较高算法-计数byte中1的个数(需循环n次,n为byte中1的个数)
while (byte)
{
parity = !parity;
byte &= byte - 1;
}
return parity;
} /*!
* @brief 获取给定data的水平奇校验位
*
* @param src, 待计算奇偶性的数据块.
* @param lenInBytes, 待计算奇偶性的数据块长度.
* @retval 0, data极性(含1的个数)为奇数.
* @retval 1, data极性(含1的个数)为偶数.
*/
uint32_t get_data_parity(uint8_t *src,
uint32_t lenInBytes)
{
uint32_t result = 0;
// 水平校验法
// isDataOddParity用于判断所有data bits的行极性是否为奇
bool isDataOddParity = false;
while (lenInBytes--)
{
isDataOddParity ^= is_byte_odd_parity(*src++);
}
// result为所有data bits的奇校验位
result = !isDataOddParity; return result;
} // main.c
//////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include "parity_check.h" int main(void)
{
uint8_t data[4] = {0x31, 0x33, 0x04, 0x08};
uint32_t parity = get_data_parity(data, sizeof(data)); printf("parity = %d\n", parity);
return 0;
}

1.5 行业应用

  奇偶检验比较典型的应用是在串口UART上,玩过UART的朋友肯定了解串口奇偶检验位的作用,包括下位机MCU UART驱动的编写,上位机串口调试助手的设置都需要注意奇偶校验位。下图是UART传输时序图,奇偶校验位是可选位,仅当使能时才会生效。不过作为嵌入式开发者,倒不必关注奇偶校验的具体实现,因为MCU的UART模块已经在硬件上支持了奇偶检验,我们只需要操作UART对应寄存器的控制位去使能奇偶检验功能即可。

二、奇偶校验法失效分析

  在现实数据传输中,偶尔1位出错的机会最多,2位及以上发生错误的概率比较低,且由于奇偶校验实现简单,具有相对理想的检错能力,因此得到广泛使用。但奇偶校验法有如下2个明显的缺陷:

  • 奇数位误码能检出,偶数位误码不能检出
  • 不能纠错,在发现错误后,只能要求重发。

  前面讲的两种校验法实际上更多是针对byte传输校验,而在实际应用中我们校验的对象往往是数据包packet,有没有其他比奇偶校验法更好且针对packet的检错方法呢?痞子衡在下篇会继续聊。

  至此,嵌入式里数据差错控制技术之奇偶校验痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

文章会同时发布到我的 博客园主页CSDN主页微信公众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:常用的数据差错控制技术(2)- 奇偶校验(Parity Check)的更多相关文章

  1. 痞子衡嵌入式:常用的数据差错控制技术(1)- 重复校验(Repetition Code)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式里数据差错控制技术-重复校验. 在嵌入式应用里,除了最核心的数据处理外,我们还会经常和数据传输打交道.数据传输需要硬件传输接口的支持 ...

  2. 痞子衡嵌入式:常用的数据差错控制技术(3)- 和校验(Checksum)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式里数据差错控制技术-和校验. 在系列前一篇文章里,痞子衡给大家介绍了比较简单的校验法-奇偶校验,该校验法主要是针对byte传输校验而 ...

  3. 痞子衡嵌入式:i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad. 最近碰到一个客户,他们在 i.MX ...

  4. 痞子衡随笔:常用的数据传输差错检测技术(1)- 奇偶校验(Parity Check)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式数据传输里的差错检测技术-奇偶校验. 在嵌入式应用里,除了最核心的数据处理外,我们还会经常和数据传输打交道.数据传输需要硬件传输接口 ...

  5. 痞子衡嵌入式:超级好用的可视化PyQt GUI构建工具(Qt Designer)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是PyQt GUI构建工具Qt Designer. 痞子衡开博客至今已有好几年,一直以嵌入式开发相关主题的文章为主线,偶尔穿插一些其他技术 ...

  6. 痞子衡嵌入式:极易上手的可视化wxPython GUI构建工具(wxFormBuilder)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是wxPython GUI构建工具wxFormBuilder. 一.手工代码布局GUI界面的烦恼 如果你曾经设计过上位机软件GUI界面,初 ...

  7. 痞子衡嵌入式:恩智浦MCU安全加密启动一站式工具NXP-MCUBootUtility用户指南

    NXP MCU Boot Utility English | 中文 1 软件概览 1.1 介绍 NXP-MCUBootUtility是一个专为NXP MCU安全加密启动而设计的工具,其特性与NXP M ...

  8. 痞子衡嵌入式:PCM编码与Waveform音频文件(.wav)格式详解

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是PCM编码及Waveform音频文件格式. 嵌入式里有时候也会和音频打交道,比如最近特别火的智能音箱产品,离不开前端的音频信号采集.降噪 ...

  9. 痞子衡嵌入式:飞思卡尔i.MX RT系列MCU特性介绍(2)- RT1052DVL6性能实测

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RT系列MCU的性能. 在前面的文章 i.MXRT微控制器概览 里,痞子衡给大家简介过恩智浦半导体在2017年推出的新 ...

随机推荐

  1. 201771010118 马昕璐《面向对象程序设计java》第十二周学习总结

    第一部分:理论知识学习部分 用户界面:用户与计算机系统(各种程序)交互的接口 图形用户界面:以图形方式呈现的用户界面 AET:Java 的抽象窗口工具箱包含在java.awt包中,它提供了许多用来设计 ...

  2. 1.SSM整合_单表的增删改查

    目标:增删改查 环境:Maven+Eclipse+Tomcat7+JDK7 思维导图: 表结构 目录结构 依赖 <dependencies> <dependency> < ...

  3. Multi-Get API

    multiGet API并行地在单个http请求中执行多个get请求. Multi-Get Request MultiGetRequest构造函数为空,需要你添加`MultiGetRequest.It ...

  4. mysql根据字符截取字符串(总结)

    mysql根据字符截取字符串(总结) 1.1 前言   为结合自己平常查资料的习惯,我会先给出例子,然后再对相关知识进行详解.该案例使用到的函数为:SUBSTRING_INDEX 1.2 需要实现的实 ...

  5. Dora.Interception,为.NET Core度身打造的AOP框架 [3]:多样化拦截器应用方式

    在<以约定的方式定义拦截器>中,我们通过对拦截器的介绍了Dora.Interception的两种拦截机制,即针对接口的“实例拦截”针对虚方法的“类型拦截”.我们介绍了拦截器的本质以及基于约 ...

  6. AIO系列文档(1)----图解ByteBuffer

    因何而写 网上关于bytebuffer的文章真的很多,为何在此还要写一篇呢?主要是基于以下几点考虑 很多人在使用t-io时,还不会bytebuffer,只会照着t-io提供的例子照猫画虎,不利于灵活运 ...

  7. JavaScript中如何理解如何理解Array.apply(null, {length:5})

    先来看一个问题: 如何理解Array.apply(null, {length:5})的{length:5}? 我测试过Array.apply(null, {length:5}) //返回[undefi ...

  8. Node.js(day6)

    初始化准备工作 初始化目录 nmp init -y 安装基本的第三方插件 express npm install express --save art-template npm install art ...

  9. iOS学习——(转)多线程

    转载自:iOS多线程全套:线程生命周期,多线程的四种解决方案,线程安全问题,GCD的使用,NSOperation的使用 一.多线程的基本概念 进程:可以理解成一个运行中的应用程序,是系统进行资源分配和 ...

  10. php内核一些常识

    整个PHP环境和Zend环境会涉及多个全局变量,下面是几个比较重要的: php_core_globals core_globals(main/php_globals.h) ==> PG PHP调 ...