与接收有关的数据有以下几个,可以根据需要修改:
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---------------------