VC在win95下编写用于串行通讯的程序既然有这么多人问这个文体,贝贝就给个Visual C++ 4.2写的 Window 95串口通讯函数集合(只适用于32位) 需要说明的是:这是我程序的一部分,因此有一些与具体应用无关的部分。 但我觉得关键是原理,而不是程序本身.后面有些使用介绍,帮助理解这长的程序。 头文件(.H) #include "StdAfx.h" #define GWL_PGPSINFO 0 #define GPSEXTRABYTES sizeof( LONG ) #define MAXPORTS 4 #define CN_SEND WM_USER+100 #define RXQUEUE 4096 #define TXQUEUE 4096 // cursor states #define CS_HIDE 0x00 #define CS_SHOW 0x01 // Flow control flags #define FC_DTRDSR 0x01 #define FC_RTSCTS 0x02 #define FC_XONXOFF 0x04 // ascii definitions #define ASCII_BEL 0x07 #define ASCII_BS 0x08 #define ASCII_LF 0x0A #define ASCII_CR 0x0D #define ASCII_XON 0x11 #define ASCII_XOFF 0x13 // data structures typedef struct tagGPSINFO { HANDLE idComDev; BYTE bPort; BOOL fConnected; BYTE bByteSize,bParity,bStopBits; DWORD dwBaudRate; HANDLE hPostEvent,hWatchThread,hWatchEvent; HWND hTermWnd; DWORD dwThreadID; OVERLAPPED osWrite,osRead; } GPSINFO, *PGPSINFO ; #define COMDEV( x ) (x -> idComDev) #define PORT( x ) (x -> bPort) #define CONNECTED( x ) (x -> fConnected) #define BYTESIZE( x ) (x -> bByteSize) #define PARITY( x ) (x -> bParity) #define STOPBITS( x ) (x -> bStopBits) #define BAUDRATE( x ) (x -> dwBaudRate) #define POSTEVENT( x ) (x -> hPostEvent) #define HTHREAD( x ) (x -> hWatchThread) #define THREADID( x ) (x -> dwThreadID) #define WRITE_OS( x ) (x -> osWrite) #define READ_OS( x ) (x -> osRead) // function prototypes (private) LRESULT NEAR CreateGPSInfo(HWND,BYTE nPort=1); BOOL NEAR DestroyGPSInfo(); int NEAR ReadCommBlock(LPSTR,int); BOOL NEAR WriteCommBlock(LPSTR,DWORD); BOOL NEAR OpenConnection(); BOOL NEAR SetupConnection(); BOOL NEAR CloseConnection(); // function prototypes (public) DWORD FAR PASCAL CommWatchProc(LPSTR); 具体实现请看下文(为了这文章,我都段线2次了) CPP实现部分: #include "StdAfx.h" #include "Com.h" HWND hGPSWnd=NULL; PGPSINFO npGPSInfo=NULL; LRESULT NEAR CreateGPSInfo(HWND hWnd,BYTE nPort) { if (NULL==(npGPSInfo=(PGPSINFO)LocalAlloc(LPTR,sizeof(GPSINFO)))) return ((LRESULT)-1) ; hGPSWnd=hWnd; COMDEV(npGPSInfo)=0; CONNECTED(npGPSInfo)=FALSE; PORT(npGPSInfo)=nPort; BAUDRATE(npGPSInfo)=CBR_9600; BYTESIZE(npGPSInfo)=8; PARITY(npGPSInfo)=NOPARITY; STOPBITS(npGPSInfo)=ONESTOPBIT; WRITE_OS(npGPSInfo).Offset=0; WRITE_OS(npGPSInfo).OffsetHigh=0; READ_OS(npGPSInfo).Offset=0; READ_OS(npGPSInfo).OffsetHigh=0; // create I/O event used for overlapped reads / writes READ_OS(npGPSInfo).hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); if (READ_OS(npGPSInfo).hEvent==NULL) { LocalFree( npGPSInfo ) ; return ( -1 ) ; } WRITE_OS(npGPSInfo).hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); if (NULL==WRITE_OS(npGPSInfo).hEvent) { CloseHandle(READ_OS(npGPSInfo).hEvent); LocalFree(npGPSInfo) ; return (-1) ; } return ( (LRESULT) TRUE ) ; } BOOL NEAR DestroyGPSInfo() { if (!npGPSInfo) return (FALSE); if (CONNECTED(npGPSInfo)) CloseConnection(); CloseHandle(READ_OS(npGPSInfo).hEvent); CloseHandle(WRITE_OS(npGPSInfo).hEvent); CloseHandle(POSTEVENT(npGPSInfo)); LocalFree(npGPSInfo); return (TRUE); } BOOL NEAR OpenConnection() { char szPort[15]; BOOL fRetVal; HCURSOR hOldCursor,hWaitCursor; HANDLE hCommWatchThread; DWORD dwThreadID; COMMTIMEOUTS CommTimeOuts; if (!npGPSInfo) return (FALSE); hWaitCursor=LoadCursor(NULL,IDC_WAIT) ; hOldCursor=SetCursor(hWaitCursor) ; wsprintf(szPort,"COM%d",PORT(npGPSInfo)); if((COMDEV(npGPSInfo)=CreateFile(szPort,GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL))==(HANDLE)-1) return ( FALSE ) ; else { SetCommMask(COMDEV(npGPSInfo),EV_RXCHAR); SetupComm(COMDEV(npGPSInfo),4096,4096); PurgeComm(COMDEV(npGPSInfo),PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); CommTimeOuts.ReadIntervalTimeout=0xFFFFFFFF; CommTimeOuts.ReadTotalTimeoutMultiplier=0; CommTimeOuts.ReadTotalTimeoutConstant=1000; CommTimeOuts.WriteTotalTimeoutMultiplier=0; CommTimeOuts.WriteTotalTimeoutConstant=1000; SetCommTimeouts(COMDEV(npGPSInfo),&CommTimeOuts); } fRetVal=SetupConnection(); if (fRetVal) { CONNECTED(npGPSInfo)=TRUE; if(NULL==(hCommWatchThread=CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,(LPTHREAD_START_ROUTINE)CommWatchProc, (LPVOID)NULL,0,&dwThreadID))) { CONNECTED(npGPSInfo)=FALSE; CloseHandle(COMDEV(npGPSInfo)); fRetVal=FALSE; } else { THREADID(npGPSInfo)=dwThreadID; HTHREAD(npGPSInfo)=hCommWatchThread; EscapeCommFunction(COMDEV(npGPSInfo),SETDTR); } } else { CONNECTED(npGPSInfo)=FALSE; CloseHandle(COMDEV(npGPSInfo)); } SetCursor(hOldCursor); return (fRetVal); } BOOL NEAR SetupConnection() { BOOL fRetVal; DCB dcb; if (!npGPSInfo) return(FALSE); dcb.DCBlength=sizeof(DCB); GetCommState(COMDEV(npGPSInfo),&dcb); dcb.BaudRate=BAUDRATE(npGPSInfo); dcb.ByteSize=BYTESIZE(npGPSInfo); dcb.Parity=PARITY(npGPSInfo); dcb.StopBits=STOPBITS(npGPSInfo); dcb.fOutxDsrFlow=FALSE; dcb.fDtrControl=DTR_CONTROL_ENABLE; dcb.fOutxCtsFlow=FALSE; dcb.fRtsControl=RTS_CONTROL_ENABLE; dcb.fInX=dcb.fOutX=FALSE; dcb.fBinary=TRUE; dcb.fParity=TRUE; fRetVal=SetCommState(COMDEV(npGPSInfo),&dcb); return (fRetVal); } BOOL NEAR CloseConnection() { if (!npGPSInfo) return(FALSE); CONNECTED(npGPSInfo)=FALSE; SetCommMask(COMDEV(npGPSInfo),0); while(THREADID(npGPSInfo)!=0); EscapeCommFunction(COMDEV(npGPSInfo),CLRDTR); PurgeComm(COMDEV(npGPSInfo),PURGE_TXABORT|PURGE_RXABORT| PURGE_TXCLEAR|PURGE_RXCLEAR); CloseHandle(COMDEV(npGPSInfo)); return (TRUE); } int NEAR ReadCommBlock(LPSTR lpszBlock,int nMaxLength) { BOOL fReadStat ; COMSTAT ComStat ; DWORD dwErrorFlags; DWORD dwLength; DWORD dwError; if (!npGPSInfo) return(FALSE); ClearCommError(COMDEV(npGPSInfo),&dwErrorFlags,&ComStat); dwLength=min((DWORD)nMaxLength,ComStat.cbInQue); if (dwLength>0) { fReadStat=ReadFile(COMDEV(npGPSInfo),lpszBlock, dwLength,&dwLength,&READ_OS(npGPSInfo)); if (!fReadStat) { if (GetLastError()==ERROR_IO_PENDING) { OutputDebugString("/n/rIO Pending"); while(!GetOverlappedResult(COMDEV(npGPSInfo),&READ_OS(npGPSInfo),&dwLength,TRUE)) { dwError=GetLastError(); if(dwError == ERROR_IO_INCOMPLETE)continue; } } else { dwLength=0; ClearCommError(COMDEV(npGPSInfo),&dwErrorFlags,&ComStat); } } } return ( dwLength ) ; } BOOL NEAR WriteCommBlock(LPSTR lpByte,DWORD dwBytesToWrite) { BOOL fWriteStat; DWORD dwBytesWritten; DWORD dwErrorFlags; DWORD dwError; COMSTAT ComStat; if (!npGPSInfo) return(FALSE); fWriteStat=WriteFile(COMDEV(npGPSInfo),lpByte,dwBytesToWrite, &dwBytesWritten,&WRITE_OS(npGPSInfo)); if (!fWriteStat) { if(GetLastError()==ERROR_IO_PENDING) { while(!GetOverlappedResult(COMDEV(npGPSInfo), &WRITE_OS(npGPSInfo),&dwBytesWritten,TRUE)) { dwError=GetLastError(); if(dwError == ERROR_IO_INCOMPLETE)continue; else { ClearCommError(COMDEV(npGPSInfo),&dwErrorFlags,&ComStat); break; } } } else { ClearCommError(COMDEV(npGPSInfo),&dwErrorFlags,&ComStat); return ( FALSE ); } } return ( TRUE ) ; } DWORD FAR PASCAL CommWatchProc(LPSTR) { DWORD dwEvtMask; OVERLAPPED os; int nLength; BYTE abIn[1024]; memset(&os,0,sizeof(OVERLAPPED)); // create I/O event used for overlapped read os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); if (os.hEvent==NULL) { MessageBox(NULL,"Failed to create event for thread!","GPSError!",MB_ICONEXCLAMATION|MB_OK); return ( FALSE ) ; } if (!SetCommMask(COMDEV(npGPSInfo),EV_RXCHAR)) return (FALSE); while (CONNECTED( npGPSInfo)) { dwEvtMask=0 ; WaitCommEvent(COMDEV(npGPSInfo),&dwEvtMask,NULL); if ((dwEvtMask&EV_RXCHAR)==EV_RXCHAR) { do { if(nLength=ReadCommBlock((LPSTR)abIn,1024)) { //WriteCommBlock((LPSTR)abIn,nLength ); *(abIn+nLength)=0; ::SendMessage(hGPSWnd,CN_SEND,nLength,(LONG)(LPSTR)abIn); } } while ((nLength>0)&&(CONNECTED( npGPSInfo))); } } CloseHandle(os.hEvent); THREADID(npGPSInfo)=0; HTHREAD(npGPSInfo)=NULL; return(TRUE); } 就这些了,希望能对问这些问题的朋友有所帮助! 一般使用的顺序是: CreateGPSInfo(被通知的窗口句柄,串口端口号1或2); OpenConnection();//建立联结它会调用SetupConnection DestroyGPSInfo();//解除联结它会调用CloseConnection 可以用ReadCommBlock/WriteCommBlock来读/写串口 CommWatchProc是监视串口的线程,由OpenConnection建立 当串口有数据来的时侯,它会通知'被通知的窗口句柄'的窗口数据传到的消息(自定义的) SendMessage(hGPSWnd,CN_SEND,nLength,(LONG)(LPSTR)abIn);好了,文章结束了!希望能帮助你!