VC MFC 串口通信(多线程)

来源:互联网 发布:java实现迭代器 编辑:程序博客网 时间:2024/06/05 22:48

VC  MFC  串口通信(多线程)

现在一般用VC写串口通信,大多数人会采取下面的三种方式:
一.直接利用VC 里面的MSComm类进行编程。
二.网上也有一个比较好的类,大多数人也喜欢采用SerialPort(此类其实也比较好用)
三.应用API函数进行串口编程。
        以上三种方式编程,我都用过的。。。(当然都不是很深入)。其实前两种用起来比较简单一点。就是对串口初始化,在调用MSComm(SerialPort)的函数就可以了。我只是简单的看过上面两个类的定义,其中也有线程的使用。但是在我使用的时候,我是通过串口接收一副图像,但有时候界面会出现卡死的情况,到此论坛上求助,有人告诉我要创建一个线程,,,这里我到现在都不是很了解,因为我觉得本来就是一个线程吧! 为什么还要创建了。。)于是就学应用API函数进行编程了。
API 函数:API(Application Programming Interface,应用编程接口)其实就是操作系统留给应用程序的一个调用接口,应用程序通过调用操作系统的 API 而使操作系统去执行应用程序的命令(只要是在windows环境下编程都可以调用API函数)
利用API函数进行串口编程的步骤:
(1)打开串口:CreatFile()函数             
m_hcom=CreateFile("COM1",//COM1口GENERIC_READ|GENERIC_WRITE, //允许读和写0, //独占方式NULL,OPEN_EXISTING, //打开FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式NULL             );
            创建一个关于串口的句柄
(2)创建串口通信事件:CreatEvent()函数
这里涉及到了一个重要的结构体OVERLAPPED:OVERLAPPED是一个包含了用于异步输入输出的信息的结构体,在这个结构体中最重要的一个成员为hEvent,线程利用CreatEvent函数为hEvent创建一个手工重置事,hEvent将作为线程的同步对象使用,初始化的hEvent为有信号的,当读写事件完成操作之后,hEvent会变为有信号。对这一结构,请看这里http://blog.csdn.net/pofenglangguayunfan/article/month/2013/10。
(3)串口的初始化,设置串口参数
/********************输入缓冲区和输出缓冲区的大小***********/    SetupComm(m_hcom,1024,1024);/*********************超时结构(读一次缓冲区就返回)****************************/    COMMTIMEOUTS TimeOuts;TimeOuts.ReadIntervalTimeout=MAXDWORD;//两个字节之间的间隔时间TimeOuts.ReadTotalTimeoutMultiplier=0;//读时间系数TimeOuts.ReadTotalTimeoutConstant=0;//读时间常数TimeOuts.WriteTotalTimeoutMultiplier=100;//设定写超时TimeOuts.WriteTotalTimeoutConstant=500;SetCommTimeouts(m_hcom,&TimeOuts);   /******************串口参数的配置*******************/DCB dcb;GetCommState(m_hcom,&dcb);//获得参数dcb.BaudRate=4800;dcb.ByteSize=8;//每个字节8位dcb.Parity=NOPARITY;//无奇偶检验dcb.StopBits=ONESTOPBIT;//两个停止位    SetCommState(m_hcom,&dcb);
(4)建立读数据的线程:
一般写数据我们是可以控制的,但读数据的时候,我们不知道数据什么时候会到,所以要建立一个专门的线程,其中用到的函数有:WaitCommEvent,ClearCommError,WaitForSingleObject,ReadFile
OVERLAPPED os;//异状态步输入/输出的    COMSTAT comStat;//通信设备控制块os.hEvent=NULL;os.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);os.Offset=0;os.OffsetHigh=0;m_osRead.hEvent=CreateEvent(NULL, TRUE, FALSE, NULL);    char czReceiveBuffer[100];DWORD dErrInformation;memset(czReceiveBuffer,0,sizeof(czReceiveBuffer));SetCommMask(m_hcom, EV_RXCHAR);///*if(os.hEvent=NULL){AfxMessageBox("无法创建事件对象!");return (UINT)-1;}*//****************** 在通信之前清除掉错误信息**************/if(m_hcom!=NULL){ClearCommError(m_hcom,&dErrInformation,&comStat);}while(TRUE){     DWORD wEven; INT bResult=WaitCommEvent(m_hcom,&wEven,&os); //DWORD BytesRead;if(!bResult) {     switch(GetLastError()) { case ERROR_IO_PENDING:  break; case 87:  break;  default:  break; } } else  { ClearCommError(m_hcom,&dErrInformation,&comStat); if(comStat.cbInQue==0) { continue; } } INT nEvent=WaitForSingleObject(os.hEvent,INFINITE);         if(nEvent==WAIT_OBJECT_0) {            DWORD CommEvent=0;GetCommMask(m_hcom,&CommEvent);if(CommEvent&EV_RXCHAR==EV_RXCHAR)//输入缓冲区接收到新字符{              BOOL bread=TRUE;  BOOL bresult=TRUE;  DWORD deError=0;  DWORD BytesRead=0;  /////////////////////  COMSTAT comstat;  for(;;)  {  DWORD dRBufferSize=100; INT bResult=ClearCommError(m_hcom,&deError,&comstat);//成功返回值非0      if(comstat.cbInQue==0)  {  break;  }  if(bread)                  {  strRec="";  bresult=ReadFile(m_hcom,czReceiveBuffer,100,&dRBufferSize,&m_osRead);  if(!bresult)  {                        switch(deError=GetLastError()){case ERROR_IO_PENDING:{bread=FALSE;break;}default:{break;}}  }  else  {  bread=TRUE;  }  }              if(!bread)  {                    bread=TRUE;bresult=GetOverlappedResult(m_hcom,&os,    &BytesRead,                        TRUE);                    if(!bresult){}  }                 PurgeComm(m_hcom, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); for(DWORD k=0;k<dRBufferSize;k++) { strRec+=czReceiveBuffer[k]; } ::PostMessage(m_hVieWnd,WM_RECEDATA,(unsigned int)czReceiveBuffer,dRBufferSize);  }} }if(nEvent!=WAIT_OBJECT_0){GetLastError();}}return TRUE;
(5)写数据:用WriteFile()函数
    OVERLAPPED m_osWriter;memset(&m_osWriter,0,sizeof(OVERLAPPED));m_osWriter.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);UpdateData(true);//m_strSend += "/n";COMSTAT ComStat;DWORD dwErrorFlags;BOOL  bWriterStat;DWORD dwBytesWrite=0;ClearCommError(m_hcom,&dwErrorFlags,&ComStat);bWriterStat = WriteFile(m_hcom,m_strSend,m_strSend.GetLength(),&dwBytesWrite,&m_osWriter);if(!bWriterStat){       if(GetLastError()==ERROR_IO_PENDING)   {   WaitForSingleObject(m_osWriter.hEvent,1000);   }}
(6)
终止线程CloseHandle();

        
原创粉丝点击