Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2342420
  • 博文数量: 816
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-17 17:57
文章分类

全部博文(816)

文章存档

2011年(1)

2008年(815)

分类:

2008-12-17 18:00:27

与接收有关的数据有以下几个,可以根据需要修改:

YbCommDevice1->PackageSize = 4096;    //你接收数据的最大长度,可以适当大一些,当然也可以正好合适
YbCommDevice1->PackageInterval = 50;  //识别超时的时间间隔
YbCommDevice1->PackageType = cptFrameTimeout; //用判断超时的方法接收数据包
YbCommDevice1->UsePackage  = true;    //启动数据包协议

其中识别超时的时间间隔很重要,
1.发送数据方在发送数据时可能处理数据,或处理中断等,可能在一帧数据内产生延时,时间定义过短会拆开数据
2.如果你的超时时间定义过大,会把两帧数据当一帧处理
所以超时时间一定要比一帧数据内部两个字节的最大间距大,并且比两帧数据的最小间隔小

例如:t1 为两个字节之间的最大间距, t2 为两帧数据之间的最小间隔

00   11  22 33  44 .. .. .. 12 34 45 67 99 .. .. .. .. .. .. 34 12 45
 |___|           |___________|
  t1                 t2

成功的间隔必需满足: t1 < 超时时间间隔 < t2

启动了这个协议需要用 ReadPackage 来接收数据
实际收到的字节数 = YbCommDevice1->ReadPackage(接收缓存, 缓存容量);

--------------------next---------------------
API函数和我见到过的串口控件,包括 mscomm 和 spcomm 等,产生读串口事件,或者收到串口数据的条件:
当然是收到数据就尽可能快的产生事件,所以没等数据收完就产生事件,并且可以读到数据了。
如果你的程序不是很忙,一般情况收到大约8个字节就会产生事件,
如果你的一帧数据有二十几个字节,可能会三次才能收全数据

大多数情况都会用编程判断时间间隔来解决这个问题,
就是超过一帧数据内部两个字节的最大间隔还没收到数据,就认为是一帧数据结束
但延时事件不宜过长,因为你延时的事件超过两帧数据的最小间隔,就会把两帧数据连成一个

如果你用API或别的控件编程,以上这些都需要自己处理,比较麻烦。
就是因为这个,所以在新版本的串口控件加上这个功能,方便识别数据。

--------------------next---------------------
但是效果十分的不好,首先设置超时100ms,这是规约规定的数据帧间隔最长时间
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  YbCD->Active = true;
  send("90 c0 0d 03 44 00 02 00 00 e3 44");
}
//---------------------------------------------------------------------------
unsigned char TForm1::CRC8(unsigned char *puchMsg, unsigned short usDataLen)
{
static unsigned char CRCBZ[]={
    0x00,0x07,0x0E,0x09,0x1C,0x1B,0x12,0x15,
    0x38,0x3F,0x36,0x31,0x24,0x23,0x2A,0x2D,
    0x70,0x77,0x7E,0x79,0x6C,0x6B,0x62,0x65,
    0x48,0x4F,0x46,0x41,0x54,0x53,0x5A,0x5D,
    0xE0,0xE7,0xEE,0xE9,0xFC,0xFB,0xF2,0xF5,
    0xD8,0xDF,0xD6,0xD1,0xC4,0xC3,0xCA,0xCD,
    0x90,0x97,0x9E,0x99,0x8C,0x8B,0x82,0x85,
    0xA8,0xAF,0xA6,0xA1,0xB4,0xB3,0xBA,0xBD,
    0xC7,0xC0,0xC9,0xCE,0xDB,0xDC,0xD5,0xD2,
    0xFF,0xF8,0xF1,0xF6,0xE3,0xE4,0xED,0xEA,
    0xB7,0xB0,0xB9,0xBE,0xAB,0xAC,0xA5,0xA2,
    0x8F,0x88,0x81,0x86,0x93,0x94,0x9D,0x9A,
    0x27,0x20,0x29,0x2E,0x3B,0x3C,0x35,0x32,
    0x1F,0x18,0x11,0x16,0x03,0x04,0x0D,0x0A,
    0x57,0x50,0x59,0x5E,0x4B,0x4C,0x45,0x42,
    0x6F,0x68,0x61,0x66,0x73,0x74,0x7D,0x7A,
    0x89,0x8E,0x87,0x80,0x95,0x92,0x9B,0x9C,
    0xB1,0xB6,0xBF,0xB8,0xAD,0xAA,0xA3,0xA4,
    0xF9,0xFE,0xF7,0xF0,0xE5,0xE2,0xEB,0xEC,
    0xC1,0xC6,0xCF,0xC8,0xDD,0xDA,0xD3,0xD4,
    0x69,0x6E,0x67,0x60,0x75,0x72,0x7B,0x7C,
    0x51,0x56,0x5F,0x58,0x4D,0x4A,0x43,0x44,
    0x19,0x1E,0x17,0x10,0x05,0x02,0x0B,0x0C,
    0x21,0x26,0x2F,0x28,0x3D,0x3A,0x33,0x34,
    0x4E,0x49,0x40,0x47,0x52,0x55,0x5C,0x5B,
    0x76,0x71,0x78,0x7F,0x6A,0x6D,0x64,0x63,
    0x3E,0x39,0x30,0x37,0x22,0x25,0x2C,0x2B,
    0x06,0x01,0x08,0x0F,0x1A,0x1D,0x14,0x13,
    0xAE,0xA9,0xA0,0xA7,0xB2,0xB5,0xBC,0xBB,
    0x96,0x91,0x98,0x9F,0x8A,0x8D,0x84,0x83,
    0xDE,0xD9,0xD0,0xD7,0xC2,0xC5,0xCC,0xCB,
    0xE6,0xE1,0xE8,0xEF,0xFA,0xFD,0xF4,0xF3 };

unsigned char uchCRC=0xff; //陪集码
unsigned uIndex;

uIndex=*puchMsg;
puchMsg++;
while(usDataLen--)//循环校验
{
    uchCRC=CRCBZ[uIndex]; //正表
    uIndex=uchCRC^*puchMsg++;
}
return (~uchCRC); //求反结果
}
//---------------------------------------------------------------------------

void __fastcall TForm1::send(AnsiString sends)
{
  int nBytes = 0;
  char Buffer[1000], *EndPtr;
  AnsiString t,s = sends.Trim();
  while(s.Length()>0)
  {
    int p = s.Pos(' '); //空格
    if(p>0)
    {
      t = s.SubString(1,p-1);
      s = s.SubString(p+1,s.Length()).Trim();
      Buffer[nBytes++] = strtol(t.c_str(), &EndPtr, 16); //十六进制字符串转成字节
    }
    else //还剩下最后一个字节
    {
      t = s;
      s = "";
      Buffer[nBytes++] = strtol(t.c_str(), &EndPtr, 16); //十六进制字符串转成字节
    }
  }
  Buffer[nBytes++]=CRC8(Buffer,nBytes);
  YbCD->Write(Buffer,nBytes);
}
//---------------------------------------------------------------------------


void __fastcall TForm1::YbCDPackage(TObject *Sender,
      int NotifyType)
{
  unsigned char Buf[8192]; //收到的字节数不会超过串口缓存的容量, 所以分配一个缓存容量相同的Buf
  int n = YbCD->Read(Buf,8192); //收到 n 个字节
  AnsiString s;
  for(int i=0; i    s += IntToHex(Buf[i],2).SubString(IntToHex(Buf[i],2).Length()-1,2) + " ";
  s = s.Trim();
  Memo1->Lines->Add(s);
}
上边是源码,但是经常性的收不到数据,而且有时候即使是有数据也是不完整的,更难受的是接收后并不及时显示在Memo中要再点击Button才会显示,所以我使用了这个控件却选择了定时器收数的方式


--------------------next---------------------

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