奇偶校验

以前有一个魔术,是这样的:

魔术师蒙蔽眼耳,不得与助手和观众有任何交流,助手则从现场随机找一名观众,给他若干枚类似硬币的棋子,每枚棋子正反面分别为黑色和白色,然后让观众任意排列这些棋子,助手用自己手上的一枚棋子补位,然后再让观众自己选择翻转或不反转这些棋子,最后由魔术师观察这些棋子,判断观众是否翻转了棋子。

似曾相识?

对,这就是奇偶校验。

奇偶校验是数据通信和数据存储中用来检测错误的一种简单的方法,其基本思想在于通过引入一个额外的校验位,使得数据位的总数为奇数或偶数。这个校验位的奇偶性与数据位中1的个数相关,以此校验通信或存储过程是否出现错误。奇偶校验基于数据位中1的个数,通过在数据传输中引入一个校验位,使得数据位和校验位中的1的总数为奇数或偶数。这样在接收端,通过检测校验位中的奇偶性,就可以判断数据是否在传输过程中发生了错误。

奇校验

  • 奇校验的原理: 在奇校验中,校验位被设置为确保数据位和校验位中1的总数为奇数。如果数据中的1的个数已经是奇数,校验位设置为0,使得总数为偶数;如果数据中的1的个数是偶数,校验位设置为1,使得总数为奇数。

  • 实现方式: 在串口通信中,发送端计算数据位中1的个数,然后设置校验位,使得总的位数为奇数。接收端同样计算接收到的数据位和校验位中1的个数,检测奇偶性,从而发现是否存在传输错误。

偶校验

  • 偶校验的原理: 在偶校验中,校验位被设置为确保数据位和校验位中1的总数为偶数。如果数据中的1的个数已经是奇数,校验位设置为1,使得总数为偶数;如果数据中的1的个数是偶数,校验位设置为0,使得总数为奇数。

  • 实现方式: 类似于奇校验,发送端计算数据位中1的个数,然后设置校验位,使得总的位数为偶数。接收端同样计算接收到的数据位和校验位中1的个数,检测奇偶性,从而发现是否存在传输错误。

应用场景

奇偶校验在串口通信中广泛应用,特别是在RS-232等标准中。在传输数据时,通过设置奇偶校验位,可以有效地检测并纠正单比特错误,提高通信的可靠性。

实例代码

以下是简单的Python代码演示如何在串口通信中使用奇偶校验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import random

def generate_parity(data, parity_type='odd'):
count_ones = sum([int(bit) for bit in data])
if parity_type == 'odd':
return '1' if count_ones % 2 == 0 else '0'
elif parity_type == 'even':
return '1' if count_ones % 2 == 1 else '0'

def simulate_communication(data_bits, parity_type='odd'):
# 发送端生成奇偶校验位
parity_bit = generate_parity(data_bits, parity_type)

# 随机决定是否翻转一个随机的位
flip_bit_index = random.randint(0, len(data_bits) - 1)
flip_bit = random.choice(['0', '1']) # 随机选择是翻转为0还是1

transmitted_data = data_bits[:flip_bit_index] + flip_bit + data_bits[flip_bit_index + 1:] + parity_bit

# 接收端接收数据
received_data = transmitted_data[:-1]
received_parity = transmitted_data[-1]

# 接收端进行奇偶校验的检测
received_parity_check = generate_parity(received_data, parity_type)

# 检查是否存在错误
error_detected = received_parity != received_parity_check

return transmitted_data, received_data, received_parity, error_detected

# 示例
data_bits = '1101101'
parity_type = 'odd'

transmitted_data, received_data, received_parity, error_detected = simulate_communication(data_bits, parity_type)

print(f"Original Data: {data_bits}")
print(f"Transmitted Data: {transmitted_data}")
print(f"Received Data: {received_data}")
print(f"Received Parity: {received_parity}")
print(f"Error Detected: {error_detected}")

结论

奇偶校验作为串口通信中的一项基本技术,通过引入校验位,有效地帮助检测传输过程中的错误。选择奇校验还是偶校验取决于具体的通信标准和应用需求。

尽管奇偶校验在一些情况下可以有效地检测和纠正传输中的错误,但也存在一些不足之处:

  1. 仅能检测单比特错误: 奇偶校验只能检测到数据中的单比特错误,即数据中的一位发生了变化。对于多位错误或其他类型的错误,奇偶校验无法提供有效的保护。

  2. 无法纠正错误: 奇偶校验虽然可以检测错误,但不能提供纠正错误的能力。一旦检测到错误,通信系统通常需要采取其他手段(例如重新传输)来纠正错误。

  3. 传输效率较低: 引入奇偶校验位会增加传输的数据量,降低了传输效率。对于一些对传输速率要求较高的应用场景,可能会选择更高级的错误检测和纠正机制。

  4. 无法应对脉冲噪声: 在实际通信中,可能会受到一些脉冲噪声的影响,奇偶校验对于这类噪声的容忍性较差,容易产生误报。

  5. 不适用于高速通信: 在高速通信的情境下,奇偶校验的性能可能受到限制,因为它对于数据的快速变化和复杂模式的适应性较弱。

  6. 不支持多点通信: 在某些多点通信的情况下,奇偶校验可能不如其他更先进的错误检测和纠正机制适用。

在实际应用中,特别是对于对通信质量要求较高、对传输速率要求较大的场景,人们常常会选择更为复杂和强大的错误检测和纠正技术,例如循环冗余校验(CRC)或海明码,以提高通信系统的可靠性。

但是这些不足并不影响奇偶校验在数据校验中的基础性地位,很多算法都是在此基础上发展起来的。我们要学习理解这些设计思想,通过巧妙设计去解决问题。