串口接收数据及时返回问题(电能表测试的上位机应用程序)

来源:互联网 发布:淘宝海报制作软件 编辑:程序博客网 时间:2024/05/16 05:14

毕业来到电表公司只有半年,初出茅庐,才刚刚接触上位机应用程序,串口接收返回问题一开始就成为了本人程序开发的第一只拦路虎。经过不懈的努力,终于找到解决的方法,在此与同行分享一下鄙人陋见,欢迎大家批评指教!

 

开发条件

1、1G 金丝顿内存,AMD Athlon 64位3500+处理器;

2、Microsoft VC6.0开发平台;

3、232转485电路模块;

4、符合97版645电能表通讯规约的三相复费率电能表(RS485通讯)。

 

目前流行的串口操作方法有两种:文件操作法和MSComm控件法。前者主要利用VC提供的API文件操作函数对串口设备进行操作,后者利用MSComm类对串口设备进行操作。与文件操作法相比,MSComm控件法有着快速可靠处理的事件响应方法,再加上运用简单的优点,本方法选用MSComm法。

 

先简单介绍一下电能表通讯的数据帧。根据97版645电能表通讯规约的规定,电能表的通讯帧由以下部分组成:1字节长度的开始字节(0x68)+6字节长度地址域+1字节长度数据开始字节(0x68)+1字节长度的控制域+1字节长度的数据长度指示字节+指示长度的数据+1字节长度的校验字节+1字节长度的结束字节(0x16)。从以上分析可知,如果得到数据域长度字节,便可得知整个数据帧的长度。

 

程序编写。在设置好串口通讯参数后,并成功打开串口设备。将MSComm控件的RThreshold属性设置为1(SetRTreshold(1)语句),也就是说,只要串口输入缓冲区里有一个字节便响应OnCommEvent事件,然后在事件响应函数OnCommMScomm1()函数里执行读串口操作,当读到除去前导字节0xfe后有10个字节时(1字节长度的开始字节(0x68)+6字节长度地址域+1字节长度数据开始字节(0x68)+1字节长度的控制域+1字节长度的数据长度指示字节),解析数据域长度字节,因数据域后只有两个字节长度(校验和+结束字节),这时便可得到数据帧的总长度。当一次读到数据达到总长度时,可把数据调出来给有相关功能的类或函数来处理来得到要求的数据,此功能可以设置在接收串口数据函数里,代码参考如下。

 

int totallen=0;//全局变量,帧的总长度
char *tmp4=new char[100];//全局指针,用于暂存串口数据
int tmp4len=0;//全局变量,用于暂存tmp4指针读到的数据的长度
int countFE=0;//全局变量,用于数0xfe的个数
void CMy11Dlg::OnButtonR() //接收串数据的函数
{
 
 VARIANT vReceive;
 COleVariant temp;
 CByteArray temp1;
 CString temp2="";
 CString show="";
 char*temp3=NULL;
 int k=0;
 CString tmp="";
 k=m_com.GetInBufferCount();
 if(k>0){
  vReceive=m_com.GetInput();
  temp3=(char*)(unsigned char*) vReceive.parray->pvData;
  for(int i=0;i<k;i++)
  {
//   tmp4len=i;
   *(tmp4+tmp4len)=temp3[i];
   temp2.Format("%hx ",*(temp3+i));
   show+=temp2;
   tmp4len++;
  }
//  tmp.Format("%d ",tmp4[9]);
//  AfxMessageBox(tmp);}//读完缓充区里的数据后,k=0,需要等到Oncomm事件发生k才会再次为非零值
 }
 for(int i=0;i<4;i++)//数FE的个数
 {
  if((0xfe-256)==temp3[i])
   countFE++;
 }
 if(tmp4len>(10+countFE))
  totallen=(int)tmp4[(9+countFE)]+12+countFE;
 if(tmp4len==totallen){           //整串数据已经读取出来后,进行清零处理,准备处理下一帧数据
  SHOWHX(tmp4,totallen);
  totallen=0;
  tmp4len=0;
  countFE=0;
//  m_com.SetPortOpen(false);
 }
 m_edit1+=show;
 UpdateData(false);
 p->LineScroll(p->GetLineCount());//自动滚动至最底行的控制语句必须放置在更新控件语句后面,自动滚动才会有效
// AfxMessageBox("123");
}

 

好了,用于电能表测试的上位机应用程序中,关于串口接收函数及时准确返回的问题的一点点个人见解讲述完毕,因技术水平有限,欢迎大家批评指教,还有本人的书面表达问题,大家也可指数哈~

祝大家即将来临的2010年农历年里合家安康~

原创粉丝点击