Chinaunix首页 | 论坛 | 博客
  • 博客访问: 522338
  • 博文数量: 252
  • 博客积分: 6057
  • 博客等级: 准将
  • 技术积分: 1635
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-21 10:17
文章分类

全部博文(252)

文章存档

2013年(1)

2012年(1)

2011年(32)

2010年(212)

2009年(6)

分类: 系统运维

2010-11-19 08:36:48

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.

一个请求帧的最后一个字节是校验字节(图3/2/1-32),使一奇校验
对属于前款的框架字节对应位设置。
代表一个逻辑非异或功能以上的各个位(如图。3/2/1-32)
前帧的字节。


main.cpp

//---------------------------------------------------------------------------
#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 = "";
}
//---------------------------------------------------------------------------



main.h

//---------------------------------------------------------------------------
#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "sysdyn.h"

typedef unsigned char uint8_t;
//---------------------------------------------------------------------------
int CharToHex(char chHex);
uint8_t StrToHex(AnsiString strHex);
uint8_t CalcFCS(TByteDynArray ldata, int nstart, int nend);
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TLabel *Label1;
        TMemo *Memo1;
        TLabel *Label2;
        TEdit *Edit1;
        TButton *Button1;
        TButton *Button2;
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall Button2Click(TObject *Sender);
private:    // User declarations
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif




关于出错校验的一些参考资料如下:
(1)差错控制


(2)第六章 差错控制


(3)差错控制编码 线性分组码
http://emfang.blog.hexun.com/32361127_d.html

(4)浅谈差错控制编码技术


(5)校验码 



阅读(1005) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~