三个字节的汉明码校验程序,linux下编译,存储格式与汉明码有一定区别,前三字节存储数据,第四字节存储校验码。
测试程序,在中间随机改变数据一位,模拟传输位翻转。
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include <time.h>
#define BIT0(x) (x&0x01)
#define BIT1(x) ((x&0x02)>>1)
#define BIT2(x) ((x&0x04)>>2)
#define BIT3(x) ((x&0x08)>>3)
#define BIT4(x) ((x&0x10)>>4)
#define BIT5(x) ((x&0x20)>>5)
#define BIT6(x) ((x&0x40)>>6)
#define BIT7(x) ((x&0x80)>>7)
// |-----------------------|-----------------------|-----------------------|-----------------------|
// |H1|H2|03|H3|05|06|07|H4|09|10|11|12|13|14|15|H5|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|
// |A0 A1 A2 A3 A4 A5 A6 A7|B0 B1 B2 B3 B4 B5 B6 B7|C0 C1 C2 C3 C4 C5 C6 C7|
// H1 = 03+05+07+09+11+13+15+17+19+21+23+25+27+29
// A0+A1+A3+A4+A6+B0+B2+B3+B5+B7+C1+C3+C5+C7
// H2 = 03+06+07+10+11+14+15+18+19+22+23+26+27
// A0+A2+A3+A5+A6+B1+B2+B4+B5+C0+C1+C4+C5
// H3 = 05+06+07+12+13+14+15+20+21+22+23+28+29
// A1+A2+A3+A7+B0+B1+B2+B6+B7+C0+C1+C6+C7
// H4 = 09+10+11+12+13+14+15+24+25+26+27+28+29
// A4+A5+A6+A7+B0+B1+B2+C2+C3+C4+C5+C6+C7
// H5 = 17+18+19+20+21+22+23+24+25+26+27+28+29
// B3+B4+B5+B6+B7+C0+C1+C2+C3+C4+C5+C6+C7
// |A0-------------------A7|B0-------------------B7|C0-------------------C7|H1|H2|H3|H4|H5|XX|XX|XX|
unsigned char *code_han(unsigned char a, unsigned char b, unsigned char c)
{
unsigned char *out = (unsigned char *)malloc(4);
unsigned char h1 = BIT0(a) + BIT1(a) + BIT3(a) + BIT4(a) + BIT6(a) +
BIT0(b) + BIT2(b) + BIT3(b) + BIT5(b) + BIT7(b) +
BIT1(c) + BIT3(c) + BIT5(c) + BIT7(c);
unsigned char h2 = BIT0(a) + BIT2(a) + BIT3(a) + BIT5(a) + BIT6(a) +
BIT1(b) + BIT2(b) + BIT4(b) + BIT5(b) +
BIT0(c) + BIT1(c) + BIT4(c) + BIT5(c);
unsigned char h3 = BIT1(a) + BIT2(a) + BIT3(a) + BIT7(a) +
BIT0(b) + BIT1(b) + BIT2(b) + BIT6(b) + BIT7(b) +
BIT0(c) + BIT1(c) + BIT6(c) + BIT7(c);
unsigned char h4 = BIT4(a) + BIT5(a) + BIT6(a) + BIT7(a) +
BIT0(b) + BIT1(b) + BIT2(b) +
BIT2(c) + BIT3(c) + BIT4(c) + BIT5(c) + BIT6(c) + BIT7(c);
unsigned char h5 = BIT3(b) + BIT4(b) + BIT5(b) + BIT6(b) + BIT7(b) +
BIT0(c) + BIT1(c) + BIT2(c) + BIT3(c) + BIT4(c) + BIT5(c) + BIT6(c) + BIT7(c);
out[0] = a;
out[1] = b;
out[2] = c;
out[3] = (BIT0(h1)<<7) | (BIT0(h2)<<6) | (BIT0(h3)<<5) | (BIT0(h4)<<4) | (BIT0(h5)<<3);
return out;
}
#define HA 0xFF
#define HB 0xFF
#define HC 0xFF
#define H1a 0x5B
#define H1b 0xAD
#define H1c 0xAA
#define H2a 0x6D
#define H2b 0x36
#define H2c 0x33
#define H3a 0x8E
#define H3b 0xC7
#define H3c 0xC3
#define H4a 0xF0
#define H4b 0x07
#define H4c 0xFC
#define H5a 0x00
#define H5b 0xF8
#define H5c 0xFF
#define H1 0x80
#define H2 0x40
#define H3 0x20
#define H4 0x10
#define H5 0x08
unsigned char *code_ming(unsigned char *hm)
{
unsigned char *out = (unsigned char *)malloc(3);
unsigned char *han = code_han(hm[0], hm[1], hm[2]);
unsigned char xy = han[3]^hm[3];
unsigned char corr = 0, fail = 0xFF;
if (xy&H1) fail &= H1a;
else corr |= H1a;
if (xy&H2) fail &= H2a;
else corr |= H2a;
if (xy&H3) fail &= H3a;
else corr |= H3a;
if (xy&H4) fail &= H4a;
else corr |= H4a;
if (xy&H5) fail &= H5a;
else corr |= H5a;
out[0] = (fail&(~corr))^hm[0];
corr = 0; fail = 0xFF;
if (xy&H1) fail &= H1b;
else corr |= H1b;
if (xy&H2) fail &= H2b;
else corr |= H2b;
if (xy&H3) fail &= H3b;
else corr |= H3b;
if (xy&H4) fail &= H4b;
else corr |= H4b;
if (xy&H5) fail &= H5b;
else corr |= H5b;
out[1] = (fail&(~corr))^hm[1];
corr = 0; fail = 0xFF;
if (xy&H1) fail &= H1c;
else corr |= H1c;
if (xy&H2) fail &= H2c;
else corr |= H2c;
if (xy&H3) fail &= H3c;
else corr |= H3c;
if (xy&H4) fail &= H4c;
else corr |= H4c;
if (xy&H5) fail &= H5c;
else corr |= H5c;
out[2] = (fail&(~corr))^hm[2];
return out;
}
#define random_1(a,b) ((rand()%(b-a))+a)
void break_one(unsigned char *hm)
{
srand((int)time(NULL));
int a = random_1(0,3);
int b = random_1(0,8);
printf("Flip data%d bit%d\n", a, b);
hm[a] = hm[a]^(1<<b);
}
int main()
{
printf("|data0|data1|data2|han |\n");
unsigned char *ret = code_han(0x11, 0x22, 0xd3);
printf(" %02X %02X %02X %02X\n", ret[0], ret[1], ret[2], ret[3]);
break_one(ret);
printf(" %02X %02X %02X %02X\n", ret[0], ret[1], ret[2], ret[3]);
unsigned char *rret = code_ming(ret);
printf("After Hamming code is corrected.\n");
printf(" %02X %02X %02X\n", rret[0], rret[1], rret[2]);
return 0;
}
运行结果
|data0|data1|data2|han |
11 22 D3 B0
Flip data2 bit2
11 22 D7 B0
After Hamming code is corrected.
11 22 D3
汉明码还是很局限的,多位翻转就不行了,校验位翻转也不行,所以这个程序就用来参考学习吧。