//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{ }
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
BYTE byte_eibOctetData;
AnsiString str_eibOctetData;
TByteDynArray tbyte_eibArray;
AnsiString strEibData;
int n_strStart;
int i;
uint8_t u_eibCheckOctet;
strEibData = Memo1->Text;
strEibData = strEibData.UpperCase();
tbyte_eibArray.set_length(2048);
try
{
for(i=0,n_strStart=1; n_strStart<=strEibData.Length(); n_strStart+=3)
{
str_eibOctetData = "";
str_eibOctetData = str_eibOctetData+strEibData[n_strStart]+strEibData[n_strStart+1];
byte_eibOctetData = (BYTE)StrToHex(str_eibOctetData);
tbyte_eibArray.operator [](i) = byte_eibOctetData;
i++;
}//end for(n_strStart=1; n_strStart<=strEibData.Length(); n_startStart++)
tbyte_eibArray.set_length(i);
}
catch(...)
{
MessageBox(NULL,"输入数据格式不正确请输新输入!",NULL,NULL);
}//end try
u_eibCheckOctet = CalcFCS(tbyte_eibArray,tbyte_eibArray.Low,tbyte_eibArray.High);
AnsiString str_eibFCSOctet = "";
str_eibFCSOctet.sprintf("%02X",u_eibCheckOctet);
Edit1->Text = str_eibFCSOctet;
}
//---------------------------------------------------------------------------
/*
创建日期:2009/06/25
创建者: 楚来
作者: 同上
作者联系方式:Email--chulia20002001@yahoo.com.cn
说明: 计算eib LPDU的效验码。
ldata --- 存放LPDU数据的数组单元。
nstart --- 要计算的数据从ldata[nstart]字节开始。
nend --- 直到ldata[nend]字节结束计算。但是ldata[nend]字节
不参与计算。
修改日期:2010/11/19 说明: 修正了Eib校验算法,在Eib帧数据的校验中采用垂直奇校验。 对垂直奇校验做个说明: 奇校验是指在一组的数据码元后面附加一个冗余位,使得该组 连冗余位在内的码字中“1”的个数为偶数的叫(偶校验)或1 的个数为奇数的就叫(奇校验)。 垂直奇校验如下图所表示: ________________ 位元|8|7|6|5|4|3|2|1| ----------------- 字节 B0--|1|0|1|1|0|0|0|0| ----------------- 字节 00--|0|0|0|0|0|0|0|0| ----------------- 字节 32--|0|0|1|1|0|0|1|0| ----------------- 字节 08--|0|0|0|0|1|0|0|0| ----------------- 效验字节 75--|0|1|1|1|0|1|0|1| ----------------- 对图示进行解说一下:该图第一行表示位元组位元编号。从高位到 低位排列. 然后下面是个各8位位元组的位元内容与上面的位元编号 对应。 我们先看位元组的第8位,在图表中的第一列中1个数为奇数 所以这一列的最低下填了一个0(前面我们有说过,因为采用的是 奇校验,奇校验就是指这一组1的个数始终保持奇数。),我们看第 二列中1的个数为零,零即不是奇数也不是偶数,但是奇校验是这一 组1的个数为奇数,所以我们在第二列的最低下填了一个1,第三列中 1的个数为偶数,所以我们在第三列的最低下址了一个1。其他几列依 次类推分类为10101。
垂直奇校验的数学算法是: 第一种表达式: ~(byte1 xor byte n-2 xor byte n-1 xor byte n)
= check byte; 第二种表达式: (byte1 xor byte n-2 xor byte n-1 xor byte n) xor 0xFF
= check byte; 也就是说将所有的字节进行异或运算,然后取反,便可得到该组字节 的奇校验码。该算法在德国又被称为(模加计算),什么叫模加计算 了,可以观察上表,我们将表中的任一列位进行累加计算可以得到一 个结果,然后将这个结果取反就可以得到校验码了。其中每列位的累 加运算在整个字节组上又可以看成的一个 异或Xor 运算。 最后就是 需要一个取反,或者再 xor一个0xFF。 就可以计算出校验码了。应为 再xor 一个0xFF 就相当于取后的功能,两个运算是等价的。
下面给出Eib协议英文第三版 中的(第三卷:系统说明 第1章:Eib 双绞 线的实例)这一章中的Page 3/2/1-33页中给出的校验字符如何计算的说 明:
2.2.2.4 Check Octet The last octet of a request frame is the check octet (Fig. 3/2/1-32) which makes an odd parity over the set of corresponding bits belonging to the preceding octets of the frame. This represents a logical NOT XOR function (F in Fig. 3/2/1-32) over the individual bits of the preceding octets of the frame.
下面是google机器翻译的译文: 2.2.2.4 校验字符 一个请求帧的最后一个字节是校验字节(图3/2/1-32),使一奇校验 对属于前款的框架字节对应位设置。这 代表一个逻辑非异或功能以上的各个位(如图。3/2/1-32) 前帧的字节。
*/
uint8_t CalcFCS(TByteDynArray ldata, int nstart, int nend)
{
uint8_t EibCheckChar = 0xFF;
uint8_t OctetByte = 0x00;
//以下是 20090625版的算法
//for(; nstart<=nend; nstart++)
//{ EibCheckChar = ~(EibCheckChar^(OctetByte=ldata[nstart])); }
//以下是 20101119版的算法
OctetByte = ldata[nstart];
for(int nCount=nstart+1; nCount<=nend; nCount++)
{ OctetByte =OctetByte^ldata[nCount]; }
EibCheckChar = ~OctetByte;
return EibCheckChar;
}
//---------------------------------------------------------------------------
int CharToHex(char chHex)
{
if(chHex>='0' && chHex<='9') return chHex-0x30;
else if(chHex>='A' && chHex<='F') return chHex-55;
return -1;
}
//----------------------------------------------------------------------------
uint8_t StrToHex(AnsiString strHex)
{
if(strHex.Length()==0 || strHex.Length()>=3)return -1;
if(strHex.Length() == 2)
{
int nHHex = CharToHex(strHex[1]);
if(nHHex == -1) return -1;
int nLHex = CharToHex(strHex[2]);
if(nLHex == -1) return -1;
return nHHex*16+nLHex;
}
else return CharToHex(strHex[1]);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Memo1->Text = "";
Edit1->Text = "";
}
//---------------------------------------------------------------------------
|