Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1073731
  • 博文数量: 132
  • 博客积分: 612
  • 博客等级: 中士
  • 技术积分: 1389
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-14 16:06
文章分类

全部博文(132)

文章存档

2015年(2)

2014年(55)

2013年(53)

2012年(2)

2011年(20)

分类: C/C++

2011-05-13 15:09:28

由于项目需要,本次通讯使用了modbus协议,用的c++builder的Tcomm串口控件。使用modbus协议时需要添加2个事:
(1)每次发送数据包时需要在包尾部添加CRC16校验码;
(2)处理好每帧数据的帧间隔时间。
附件: testcom.rar   

上面的(1)很好处理,找个CRC16的接口将算完的校验码附在包尾就行了。主要是(2)的处理,遇到的具体问题和现象是:有时一个完整的数据包需要用多次接收完,而我在接收端一直认为每读一次串口就接收了一个完整的数据包,所以这样肯定会出现问题,表现为接收到了无法识别的数据包。解决这个问题的办法是判断任意两次接收到的数据包的帧间隔时间,如果这个时间小于一个给定值,那么就认为这两个数据包其实是一个协议包的内容,如果帧间隔时间大于这个给定值,就认为接收到的是两个独立的数据协议包。这样处理后就解决了问题。具体的实现见下面:
  1. //---------------------------------------------------------------------------
  2. DWORD dwStart_dwStart=0;
  3. int global_len=0;
  4. unsigned char global_buff[37];
  5. int times=0;
  6. void __fastcall TForm1::Comm1ReceiveData(TObject *Sender)
  7. {
  8.         int len;
  9.         int i;
  10.         int j;
  11.         unsigned short int crc;
  12.         unsigned short int crc_pkt;
  13.         unsigned char tmp[37];

  14.         if(GetTickCount()-dwStart_dwStart>50)
  15.         {
  16.                 //已经是完全的一个新帧了
  17.         //用Next表示这是个新包
  18.                 Label3->Caption="Next";
  19.                 inbuff=Comm1->ReadInputByte();
  20.                 len=inbuff.Length;
  21.                 global_len=inbuff.Length;
  22.                 for(i=0;i<len;i++)
  23.                 {
  24.                         global_buff[i]=inbuff[i];
  25.                 }
  26.                 dwStart_dwStart=GetTickCount();

  27.         }
  28.         else
  29.         {
  30.                 //还是接着上次的那个帧数据
  31.         //用this表示这是个连续的数据包
  32.                 Label3->Caption="This";
  33.                 //读出本次接收到的数据
  34.                 inbuff=Comm1->ReadInputByte();
  35.                 //读出本次接收的数据长度
  36.                 len=inbuff.Length;
  37.                 //将本次接收到的数据追加到上次的数组中去
  38.                 //此时,如果数据仍然没有发送完,就是说还会有
  39.                 //下一帧数据发过来,那么就会重复本部操作,不停的
  40.                 //向上次的数据追加数据,而如果本次追加完没有下一次了
  41.                 //那么需要本次继续向下面运行,怎么才能实现呢
  42.                 for(i=global_len,j=0;j<len;i++,j++)
  43.                 {
  44.                         global_buff[i]=inbuff[j];
  45.                 }
  46.                 global_len=global_len+len;
  47.                 Timer1->Enabled=false;
  48.                 times = times+1;
  49.         //记录这个数据包被拆分成了几份
  50.                 Label4->Caption=times;
  51.         }

  52.         Timer1->Enabled=true;
  53.          

  54. }
  1. }
  2. void __fastcall TForm1::Timer1Timer(TObject *Sender)
  3. {
  4.         Timer1->Enabled=false;
  5.         int i;


  6.         for(i=0;i<global_len;i++)
  7.         {
  8.                 Memo1->Text = Memo1->Text + " "+IntToHex(global_buff[i],2);
  9.         }
  10.         global_len=0;
  11.         times=0;

  12.           Memo1->Text = Memo1->Text + '\x0d'+'\x0a';
  13. }
  14. //---------------------------------------------------------------------------

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