首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

串口与线程,事件的效能

2013-11-13 
串口与线程,事件的功能自学BCB也有一段时间了,前段时间领导让我接手一个工程源码,看到串口通信这一块,对线

串口与线程,事件的功能
自学BCB也有一段时间了,前段时间领导让我接手一个工程源码,看到串口通信这一块,对线程和事件的操作流程不太明白
希望大侠能帮我分析下其工作流程。感谢
程序中的注解是我个人理解,也不知道是不是正确。


//---------------------------------------------------------------------------
//串口线程的入口函数
DWORD WINAPI CommProc(LPVOID pParam)//关于此函数的定义有一定的要求。除函数名外,不能随便修改
{
OVERLAPPED os;
DWORD dwMask,dwTrans;
COMSTAT ComStat;
DWORD dwErrorFlags;
COMMCLASS * comm =(COMMCLASS *)pParam;//传入的参数强制转换成类的对象指针

memset(&os, 0, sizeof(OVERLAPPED));
os.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (os.hEvent == NULL)
{
comm->strError="Can't Create event object !";
return (UNIT)-1;
}

SetEvent(comm->m_hPostMsgEvent);//m_hPostMsgEvent事件在打开串口连接的时候创建,用于同步线程操作
while(comm->m_bConnected)//串口未关闭,则进入循环
{
ClearCommError(comm->m_hCom, &dwErrorFlags, &ComStat);
if(ComStat.cbInQue)
{
if(comm->frmMsg != NULL)
::PostMessage(comm->frmMsg-Handle, WM_COMMNOTIFY, 1, 0);

tmpLen = comm->ReadComm(&comm->m_bufRec[comm->m_bufRecLen], min(ComStat.cbInQue, MAXZDLEN-comm->m_bufRecLen-1));
if(tmpLen == 0)
{
continue;
}
comm->m_bufRecLen += tmpLen;
comm->m_bufRec[comm->m_bufRecLen] = NULL;
WaitForSingleObject(comm->m_hPostMsgEvent,INFINITE);

if(comm->frmMsg != NULL)
{
ResetEvent(comm->m_hPostMsgEvent);
::PostMessage(comm_frmMsg->Handle, WM_COMMNOTIFY, 2, (long)comm->m_hPostMsgEvent);
}
else
setEvent(comm->mPostMsgEvent);

continue;
}

dwMask = 0;
if(!WaitCommEvent(comm->m_hCom, &dwMask, &os))
{
if(GetLastError() == ERROR_IO_PENDING)
GetOverlappendResult(comm->m_hCom, &os, &dwTrans, TRUE);
else
{
CloseHandel(os.hEvent);
return (UNIT)-1;
}
}

if((dwMask & EV_DSR) || (dwMask & EV_CTS) || (dwMask & EV_RING) || (dwMask & EV_RLSD))
{
DWORD statttt =0;
if(GetCommModemStatus(comm_m_hCom, &statttt,))
{
if(comm->frmMsg !=NULL)
{
WaitForSingleObject(comm->m_hPostMsgEvent, INFINITE);
ResetEvent(comm->m_hPostMsgEvent);
::PostMessage(comm->frmMsg->Handle, WM_COMMNOTIFY, CM_RECSTS, statttt);
}
else
SetEvent(comm->m_hPostMsgEvent);
}
}
}
CloseHandle(os.hEvent);
return 0;
}

char COMMCLASS::OpenConnection(bool bCrtThread/* = true*/)
{
  m_iLastError = 0;
  DWORD errNo;
  //创建一个消息响应事件
  if(m_hPostMsgEvent == NULL)
    if ((m_hPostMsgEvent = CreateEvent(NULL,TRUE,TRUE,NULL)) ==NULL)
    {
      m_iLastError = 2;
      return 2;
    }
  //异步读事件
  if(m_osRead.hEvent == NULL)
    if((m_osRead.hEvent =CreateEvent(NULL,TRUE,FALSE,NULL))==NULL)
    {
      m_iLastError = 3;
      return 3;
    }
  //异步写事件
  if(m_osWrite.hEvent == NULL)
    if((m_osWrite.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL))==NULL)
    {
      m_iLastError = 4;
      return 4;
    }

  COMMTIMEOUTS TimeOuts;  //在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。
  if(m_bConnected)
  {
    DWORD dwExitCode;
    //线程正在运行
  if ( m_pThread != NULL &&
        GetExitCodeThread( m_pThread, &dwExitCode) &&
    dwExitCode == STILL_ACTIVE)
      return 1;
    m_bConnected =FALSE;
    SetEvent(m_hPostMsgEvent);
    SetCommMask(m_hCom,0);
    CloseHandle(m_pThread);
    m_pThread= NULL;
    CloseHandle(m_hCom);
  }
  //打开串口
  m_hCom = CreateFile(m_sPort.c_str() ,GENERIC_READ|GENERIC_WRITE,0,NULL,
                      OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);
  if(m_hCom==INVALID_HANDLE_VALUE)
  {
    errNo = GetLastError();
    if(errNo == 2)
      m_iLastError = 11;//COMM口可能不存在
    else if(errNo == 5)
      m_iLastError = 12;//COMM口可能已被其它程序占用!


    else
    {
      m_iLastError = 13;//COMM口打开失败
      m_iErrNo = errNo;
    }
    return m_iLastError;
  }

  //初始化一个指定的通信设备的通信参数
  SetupComm( m_hCom,MAXJSLEN,MAXZDLEN);
  //SetCommMask(m_hCom,EV_RXCHAR);//|EV_BREAK|EV_CTS|EV_DSR|EV_ERR|EV_RING|EV_RLSD|EV_RXFLAG); //EV_TXEMPTY
  SetCommMask(m_hCom,EV_RXCHAR|EV_CTS|EV_DSR|EV_ERR|EV_RING|EV_RLSD);//EV_ERR:CE_FRAME,CE_OVERRUN,CE_RXPARITY
  //清空缓冲区
  PurgeComm( m_hCom, PURGE_TXABORT | PURGE_RXABORT |
             PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
  //set RTS,DTR
  EscapeCommFunction(m_hCom,SETRTS|SETDTR);

  //设置超时
  TimeOuts.ReadIntervalTimeout=MAXDWORD;
  TimeOuts.ReadTotalTimeoutMultiplier=0;
  TimeOuts.ReadTotalTimeoutConstant= 0;
  TimeOuts.WriteTotalTimeoutMultiplier =5;
  TimeOuts.WriteTotalTimeoutConstant = 2000;
  SetCommTimeouts(m_hCom,&TimeOuts);

  //配置串口参数
  if(ConfigConnection())
  {
    m_bConnected = TRUE;
    //创建一个挂起线程
    m_pThread  =  CreateThread(NULL,0, CommProc,this,CREATE_SUSPENDED ,&threadID );
    if(m_pThread==NULL)
    {
      CloseHandle(m_hCom);
      m_hCom = INVALID_HANDLE_VALUE;
      m_iLastError = 6;//创建线程失败
      return 6;
    }
    m_bConnected = TRUE;
    if(m_pThread != NULL)
      ResumeThread(m_pThread);  //执行线程
  }
  else
  {
    CloseHandle(m_hCom);
    m_iLastError = 7; //COMM口参数设置失败
    return 7;
  }
  ResetEvent(m_hPostMsgEvent);
  DWORD statttt = 0;
  //串口状态
  if(GetCommModemStatus(m_hCom,&statttt))
  {
    if(frmMsg != NULL)
      ::PostMessage(frmMsg->Handle   ,WM_COMMNOTIFY,1, statttt);
    else
      SetEvent(m_hPostMsgEvent);
  }
  return 1;
}

多线程 串口 事件
[解决办法]
会立即执行到181行

热点排行