www.pudn.com > GPSComEVC3.0.rar > Serial.cpp
// Serial.cpp: implementation of the CSerial class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Serial.h" #include "GpsNavDoc.h" #include "MainFrm.h" #include#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif TCHAR* GetUnicodeString(const char *s); ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSerial::CSerial() { m_strReceived=""; m_index=0; } CSerial::~CSerial() { if(hPort != INVALID_HANDLE_VALUE) ClosePort(hPort); } BOOL CSerial::OpenPort(CWnd* pPortOwner,UINT portnr,UINT baud,char parity,UINT databits,UINT stopbits,DWORD dwCommEvents,UINT buffersize) { if(!(portnr > 0 && portnr < 5&&pPortOwner != NULL)) return FALSE; DWORD dwError,dwThreadID; CString str=""; TCHAR *szPort = new TCHAR[50]; if(hPort!= NULL) { CloseHandle(hPort); hPort = NULL; } str.Format( _T("COM%d:"), portnr); lstrcpy(szPort,(LPCTSTR)str); //打开串口 hPort = CreateFile (szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); //如果打开端口出错, 返回FALSE if ( hPort == INVALID_HANDLE_VALUE ) { //不能打开端口 CString strError; strError.Format(_T("Unable to open com%d, Error No.=%d"),portnr, GetLastError()); MessageBox (NULL, strError, TEXT("Error!"), MB_OK); delete [] szPort; //delete [] szBaud; return FALSE; } //指定端口监测的事件集 SetCommMask (hPort, dwCommEvents); //分配设备缓冲区 SetupComm(hPort,buffersize,buffersize); //初始化缓冲区中的信息 PurgeComm(hPort,PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //配置串行端口 if(!InitDCB(baud)) return FALSE; //设置端口超时值 if(!InitCommTimeouts()) return FALSE; //设置端口上指定信号的状态 // SETDTR: 发送DTR (data-terminal-ready)信号 // SETRTS: 发送RTS (request-to-send)信号 EscapeCommFunction (hPort, SETDTR); EscapeCommFunction (hPort, SETRTS); //创建一个从串口读取数据的线程 if (hReadThread = CreateThread (NULL, 0, ReadPortThread, this, 0,&dwThreadID)) { } else { //不能创建线程 MessageBox (NULL, TEXT("Unable to create the read thread"),TEXT("Error!"), MB_OK); dwError = GetLastError (); return FALSE; } m_bConnected=TRUE; m_pOwner=pPortOwner; return TRUE; } DWORD CSerial::WritePort(TCHAR *buf,DWORD dwCharToWrite) { BOOL fWriteState; DWORD dwBytesWritten; //写入数据 fWriteState=WriteFile(hPort,buf,dwCharToWrite*sizeof(TCHAR),&dwBytesWritten,NULL); if(!fWriteState) { //不能写数据 MessageBox(NULL,TEXT("Can't Write String to Comm"),TEXT("Error!"),MB_OK); dwBytesWritten=0; } return dwBytesWritten; } BOOL CSerial::ClosePort(HANDLE hCommPort) { if (hCommPort != INVALID_HANDLE_VALUE) { //设置连接属性为FALSE m_bConnected=FALSE; //结束线程中WaitCommEvent的等待 SetCommMask(hPort,0); //阻塞至线程停止 if(hReadThread) { TerminateThread(hReadThread,0); CloseHandle(hReadThread); } //清除端口上指定信号的状态 EscapeCommFunction(hPort,CLRDTR); EscapeCommFunction(hPort,CLRRTS); //清除驱动程序内部的发送和接收队列 PurgeComm(hPort,PURGE_TXCLEAR|PURGE_RXCLEAR); //关闭串口 CloseHandle (hCommPort); hCommPort = INVALID_HANDLE_VALUE; return TRUE; } else { return TRUE; } } BOOL CSerial::InitDCB(UINT baud) { DCB PortDCB; DWORD dwError; PortDCB.DCBlength = sizeof (DCB); //得到端口的默认设置信息 GetCommState (hPort, &PortDCB); //改变DCB结构设置 PortDCB.BaudRate = baud; //波特率 PortDCB.fBinary = TRUE; //Win32不支持非二进制串行传输模式,必须为TRUE PortDCB.fParity = TRUE; //启用奇偶校验 PortDCB.fOutxCtsFlow = TRUE; //串行端口的输出由CTS线控制 PortDCB.fOutxDsrFlow = FALSE; //关闭串行端口的DSR流控制 PortDCB.fDtrControl = DTR_CONTROL_ENABLE; //启用DTR线 PortDCB.fDsrSensitivity = FALSE; //如果设为TRUE将忽略任何输入的字节,除非DSR线被启用 //PortDCB.fTXContinueOnXoff = TRUE; //当为TRUE时,如果接收缓冲区已满且驱动程序已传送XOFF字符,将使驱动程序停止传输字符 PortDCB.fTXContinueOnXoff = FALSE; PortDCB.fOutX = FALSE; //设为TRUE指定XON/XOFF控制被用于控制串行输出 PortDCB.fInX = FALSE; //设为TRUE指定XON/XOFF控制被用于控制串行输入 PortDCB.fErrorChar = FALSE; //WINCE串行驱动程序的默认执行将忽略这个字段 PortDCB.fNull = FALSE; //设为TRUE将使串行驱动程序忽略收到的空字节 PortDCB.fRtsControl = RTS_CONTROL_ENABLE; //启用RTS线 PortDCB.fAbortOnError = FALSE; //WINCE串行驱动程序的默认执行将忽略这个字段 PortDCB.ByteSize = 8; //每字节的位数 PortDCB.Parity = NOPARITY; //无奇偶校验 PortDCB.StopBits = ONESTOPBIT; //每字节一位停止位 //根据DCB结构配置端口 if (!SetCommState (hPort, &PortDCB)) { //不能配置串行端口 MessageBox (NULL, TEXT("Unable to configure the serial port"),TEXT("Error!"), MB_OK); dwError = GetLastError (); return FALSE; } return TRUE; } BOOL CSerial::InitCommTimeouts() { COMMTIMEOUTS CommTimeouts; DWORD dwError; //得到超时参数 GetCommTimeouts (hPort, &CommTimeouts); //改变COMMTIMEOUTS结构设置 CommTimeouts.ReadIntervalTimeout =MAXDWORD;//1000; CommTimeouts.ReadTotalTimeoutMultiplier = 0;//1000; CommTimeouts.ReadTotalTimeoutConstant = 0;//1000; CommTimeouts.WriteTotalTimeoutMultiplier = 0; CommTimeouts.WriteTotalTimeoutConstant = 5000;//5000; //设置端口超时值 if (!SetCommTimeouts (hPort, &CommTimeouts)) { //不能设置超时值 MessageBox (NULL, TEXT("Unable to set the time-out parameters"), TEXT("Error"), MB_OK); dwError = GetLastError (); return FALSE; } return TRUE; } DWORD WINAPI ReadPortThread(LPVOID pParam) { POSITION po=AfxGetApp()->GetFirstDocTemplatePosition(); CDocTemplate *pDocTem=AfxGetApp()->GetNextDocTemplate(po); po=pDocTem->GetFirstDocPosition(); CGpsNavDoc *pDoc=(CGpsNavDoc *)pDocTem->GetNextDoc(po); CSerial *port = (CSerial*)pParam; BOOL fReadState; DWORD dwCommModemStatus; DWORD dwLength,dwreadedLength; dwreadedLength=0; COMSTAT ComStat; DWORD dwErrorFlags; unsigned char RXBuff; /*char* buf=new char[256];*/ int nTemp=0; BOOL bResult; int i=0; unsigned long r_len = 0; OVERLAPPED _ro; // 重叠I/O _ro.Offset = 0; _ro.OffsetHigh = 0; // create events DWORD CommEvent = 0; _ro.hEvent = NULL; if (_ro.hEvent != NULL) ResetEvent(_ro.hEvent); _ro.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd(); PurgeComm(port->hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); while (port->hPort != INVALID_HANDLE_VALUE) { //等待串口的事件发生 //PurgeComm(port->hPort,PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //PurgeComm(port->hPort,PURGE_RXCLEAR); // 指定监视的端口事件 //SetCommMask (port->hPort, EV_RXCHAR | EV_CTS /*| EV_DSR | EV_RLSD | EV_RING */); bResult =WaitCommEvent (port->hPort, &dwCommModemStatus, &_ro);//(NULL); if(!bResult) continue; ClearCommError(port->hPort,&dwErrorFlags,&ComStat); if (ComStat.cbInQue == 0) continue; //SetCommMask (port->hPort, EV_RXCHAR | EV_CTS /*| EV_DSR | EV_RING */);//// if ((dwCommModemStatus & EV_RXCHAR) == EV_RXCHAR) {//有数据信号 pDoc->UpdateAllViews(NULL); ClearCommError(port->hPort,&dwErrorFlags,&ComStat); //cbInQue返回在串行驱动程序输入队列中的字符数 dwLength=ComStat.cbInQue; if(dwLength>0) { //从串口读取数据 fReadState=ReadFile(port->hPort, /*buf,*/&RXBuff, /*dwLength,*/1, &dwreadedLength, &_ro); //NULL); if(!fReadState) { //不能从串口读取数据 MessageBox(NULL,TEXT("Error in read from serial port"),TEXT("Read Error"),MB_OK); } else { char ch=(char)RXBuff; if (ch == 10 && port->m_strReceived[port->m_index-1] == 13) { port->m_strReceived+=ch; port->m_index++; i=port->m_strReceived.Find(_T("$GPGGA")); if(i==-1) { return 0; } port->m_strReceived=port->m_strReceived.Mid(i); pMain->m_strReceived=port->m_strReceived; ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM)0, (LPARAM) port->m_nPortNr); port->m_index=0; port->m_strReceived=""; } else if (port->m_index<1000) { port->m_strReceived+= ch; port->m_index++; } else { port->m_index=0; } } //delete[] buf; } } GetCommModemStatus (port->hPort, &dwCommModemStatus); nTemp=1;///////// } CloseHandle(_ro.hEvent); pMain->m_wndStatusBar.SetPaneText(0,_T("Thread End...."),TRUE); return 0; } // Restart the comm thread // BOOL CSerial::RestartMonitoring() { ResumeThread(hPort); return TRUE; } // // Suspend the comm thread // BOOL CSerial::StopMonitoring() { SuspendThread(hPort); return TRUE; }