串口通讯信息
硬件/系统 串口通讯 |
作者:佚名 在WIN32下是不建议对端口进行操作的,在WIN32中所有的设备都被看成是文件,串行口也不例外也是作为文件来进行处理的。这是我的一份关于串口编程的读书笔记,对于使用VC进行编程的同行应该有一定的帮助。 1.打开串口: 在Window95下串行口作为文件处理,使用文件操作对串行口进行处理。 使用CreateFile()打开串口,CreateFile()将返回串口的句柄。 HANDLECreateFile( LPCTSTRlpFileName,//pointertonameofthefile DWORDdwDesiredAccess,//access(read-write)mode DWORDdwShareMode,//sharemode LPSECURITY_ATTRIBUTESlpSecurityAttributes,//pointertosecurityattributes DWORDdwCreationDistribution,//howtocreate DWORDdwFlagsAndAttributes,//fileattributes HANDLEhTemplateFile//handletofilewithattributestocopy ); lpFileName:指明串口制备,例:COM1,COM2 dwDesiredAccess:指明串口存取方式,例:GENERIC_READ|GENERIC_WRITE dwShareMode:指明串口共享方式 lpSecurityAttributes:指明串口的安全属性结构,NULL为缺省安全属性 dwCreateionDistribution:必须为OPEN_EXISTIN dwFlagAndAttributes:对串口唯一有意义的是FILE_FLAG_OVERLAPPED hTemplateFile:必须为NULL 2.关闭串口: CloseHandle(hCommDev); 3.设置缓冲区长度: BOOLSetupComm( HANDLEhFile,//handleofcommunicationsdevice DWORDdwInQueue,//sizeofinputbuffer DWORDdwOutQueue//sizeofoutputbuffer ); 4.COMMPROP结构: 可使用GetCommProperties()取得COMMPROP结构,COMMPROP结构中记载了系统支持的各项设置。 typedefstruct_COMMPROP{//cmmp WORDwPacketLength;//packetsize,inbytes WORDwPacketVersion;//packetversion DWORDdwServiceMask;//servicesimplemented DWORDdwReserved1;//reserved DWORDdwMaxTxQueue;//maxTxbufsize,inbytes DWORDdwMaxRxQueue;//maxRxbufsize,inbytes DWORDdwMaxBaud;//maxbaudrate,inbps DWORDdwProvSubType;//specificprovidertype DWORDdwProvCapabilities;//capabilitiessupported DWORDdwSettableParams;//changeableparameters DWORDdwSettableBaud;//allowablebaudrates WORDwSettableData;//allowablebytesizes WORDwSettableStopParity;//stopbits/parityallowed DWORDdwCurrentTxQueue;//Txbuffersize,inbytes DWORDdwCurrentRxQueue;//Rxbuffersize,inbytes DWORDdwProvSpec1;//provider-specificdata DWORDdwProvSpec2;//provider-specificdata WCHARwcProvChar[1];//provider-specificdata }COMMPROP; dwMaxBaud: BAUD_07575bps BAUD_110110bps BAUD_134_5134.5bps BAUD_150150bps BAUD_300300bps BAUD_600600bps BAUD_12001200bps BAUD_18001800bps BAUD_24002400bps BAUD_48004800bps BAUD_72007200bps BAUD_96009600bps BAUD_1440014400bps BAUD_1920019200bps BAUD_3840038400bps BAUD_56K56Kbps BAUD_5760057600bps BAUD_115200115200bps BAUD_128K128Kbps BAUD_USERProgrammablebaudratesavailable dwProvSubType: PST_FAX传真设备 PST_LATLAT协议 PST_MODEM调制解调器设备 PST_NETWORK_BRIDGE未指定的网桥 PST_PARALLELPORT并口 PST_RS232RS-232口 PST_RS422RS-422口 PST_RS423RS-432口 PST_RS449RS-449口 PST_SCANNER扫描仪设备 PST_TCPIP_TELNETTCP/IPTelnet协议 PST_UNSPECIFIED未指定 PST_X25X.25标准 dwProvCapabilities PCF_16BITMODE支持特殊的16位模式 PCF_DTRDSR支持DTR(数据终端就绪)/DSR(数据设备就绪) PCF_INTTIMEOUTS支持区间超时 PCF_PARITY_CHECK支持奇偶校验 PCF_RLSD支持RLSD(接收线信号检测) PCF_RTSCTS支持RTS(请求发送)/CTS(清除发送) PCF_SETXCHAR支持可设置的XON/XOFF PCF_SPECIALCHARS支持特殊字符 PCF_TOTALTIMEOUTS支持总(占用时间)超时 PCF_XONXOFF支持XON/XOFF流控制 标准RS-232和WINDOW支持除PCF_16BITMODE和PCF_SPECIALCHAR外的所有功能 dwSettableParams SP_BAUD可配置波特率 SP_DATABITS可配置数据位个数 SP_HANDSHAKING可配置握手(流控制) SP_PARITY可配置奇偶校验模式 SP_PARITY_CHECK可配置奇偶校验允许/禁止 SP_RLSD可配置RLSD(接收信号检测) SP_STOPBITS可配置停止位个数 标准RS-232和WINDOW支持以上所有功能 wSettableData DATABITS_55个数据位 DATABITS_66个数据位 DATABITS_77个数据位 DATABITS_88个数据位 DATABITS_1616个数据位 DATABITS_16X通过串行硬件线路的特殊宽度路径 WINDOWS95支持16的所有设置 5.DCB结构: typedefstruct_DCB{//dcb DWORDDCBlength;//sizeof(DCB) DWORDBaudRate;//currentbaudrate 指定当前的波特率 DWORDfBinary:1;//binarymode,noEOFcheck 指定是否允许二进制模式, WINDOWS95中必须为TRUE DWORDfParity:1;//enableparitychecking 指定奇偶校验是否允许 DWORDfOutxCtsFlow:1;//CTSoutputflowcontrol 指定CTS是否用于检测发送控制。 当为TRUE是CTS为OFF,发送将被挂起。 DWORDfOutxDsrFlow:1;//DSRoutputflowcontrol 指定CTS是否用于检测发送控制。 当为TRUE是CTS为OFF,发送将被挂起。 DWORDfDtrControl:2;//DTRflowcontroltype DTR_CONTROL_DISABLE值将DTR置为OFF, DTR_CONTROL_ENABLE值将DTR置为ON, DTR_CONTROL_HANDSHAKE允许DTR"握手" DWORDfDsrSensitivity:1;//DSRsensitivity 当该值为TRUE时DSR为OFF时接收的字节被忽略 DWORDfTXContinueOnXoff:1;//XOFFcontinuesTx 指定当接收缓冲区已满,并且驱动程序已经发 送出XoffChar字符时发送是否停止。 TRUE时,在接收缓冲区接收到缓冲区已满的字 节XoffLim且驱动程序已经发送出XoffChar字符中 止接收字节之后,发送继续进行。 FALSE时,在接收缓冲区接收到代表缓冲区已空 的字节XonChar且驱动程序已经发送出恢复发送 的XonChar之后,发送继续进行。 DWORDfOutX:1;//XON/XOFFoutflowcontrol TRUE时,接收到XoffChar之后便停止发送 接收到XonChar之后将重新开始 DWORDfInX:1;//XON/XOFFinflowcontrol TRUE时,接收缓冲区接收到代表缓冲区满的 XoffLim之后,XoffChar发送出去 接收缓冲区接收到代表缓冲区空的 XonLim之后,XonChar发送出 去 DWORDfErrorChar:1;//enableerrorreplacement 该值为TRUE且fParity为TRUE时,用ErrorChar 成员指定的字符代替奇偶校验错误的接收字 符 DWORDfNull:1;//enablenullstripping TRUE时,接收时去掉空(0值)字节 DWORDfRtsControl:2;//RTSflowcontrol RTS_CONTROL_DISABLE时,RTS置为OFF RTS_CONTROL_ENABLE时,RTS置为ON RTS_CONTROL_HANDSHAKE时, 当接收缓冲区小于半满时RTS为ON 当接收缓冲区超过四分之三满时RTS为OFF RTS_CONTROL_TOGGLE时, 当接收缓冲区仍有剩余字节时RTS为ON 否则缺省为OFF DWORDfAbortOnError:1;//abortreads/writesonerror TRUE时,有错误发生时中止读和写操作 DWORDfDummy2:17;//reserved 未使用 WORDwReserved;//notcurrentlyused 未使用,必须为0 WORDXonLim;//transmitXONthreshold 指定在XON字符发送这前接收缓冲区中可允许 的最小字节数 WORDXoffLim;//transmitXOFFthreshold 指定在XOFF字符发送这前接收缓冲区中可允许 的最小字节数 BYTEByteSize;//numberofbits/byte,4-8 指定端口当前使用的数据位 BYTEParity;//0-4=no,odd,even,mark,space 指定端口当前使用的奇偶校验方法,可能为: EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY BYTEStopBits;//0,1,2=1,1.5,2 指定端口当前使用的停止位数,可能为: ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS charXonChar;//TxandRxXONcharacter 指定用于发送和接收字符XON的值 charXoffChar;//TxandRxXOFFcharacter 指定用于发送和接收字符XOFF值 charErrorChar;//errorreplacementcharacter 本字符用来代替接收到的奇偶校验发生错误时 的值 charEofChar;//endofinputcharacter 当没有使用二进制模式时,本字符可用来指示 数据的结束 charEvtChar;//receivedeventcharacter 当接收到此字符时,会产生一个事件 WORDwReserved1;//reserved;donotuse 未使用 }DCB; 6.改变端口设置 使用如下的两个方法 BOOLGetCommState(hComm,&dcb); BOOLSetCommState(hComm,&dcb); 7,改变普通设置 BuildCommDCB(szSettings,&DCB); szSettings的格式:baudparitydatastop 例:"baud=96parity=ndata=8stop=1" 简写:"96,N,8,1" szSettings的有效值 baud: 11or110=110bps 15or150=150bps 30or300=300bps 60or600=600bps 12or1200=1200bps 24or2400=2400bps 48or4800=4800bps 96or9600=9600bps 19or19200=19200bps parity: n=none e=even o=odd m=mark s=space data: 5,6,7,8 StopBit 1,1.5,2 8.COMMCONFIG结构: typedefstruct_COMM_CONFIG{ DWORDdwSize; WORDwVersion; WORDwReserved; DCBdcb; DWORDdwProviderSubType; DWORDdwProviderOffset; DWORDdwProviderSize; WCHARwcProviderData[1]; }COMMCONFIG,*LPCOMMCONFIG; 可方便的使用BOOLCommConfigDialog( LPTSTRlpszName, HWNDhWnd, LPCOMMCONFIGlpCC); 来设置串行口。 9.超时设置: 可通过COMMTIMEOUTS结构设置超时, typedefstruct_COMMTIMEOUTS{ DWORDReadIntervalTimeout; DWORDReadTotalTimeoutMultiplier; DWORDReadTotalTimeoutConstant; DWORDWriteTotalTimeoutMultiplier; DWORDWriteTotalTimeoutConstant; }COMMTIMEOUTS,*LPCOMMTIMEOUTS; 区间超时:(仅对从端口中读取数据有用)它指定在读取两个字符之间要经历的时间 总超时:当读或写特定的字节数需要的总时间超过某一阈值时,超时触发. 超时公式: ReadTotalTimeout=(ReadTotalTimeoutMultiplier*bytes_to_read) +ReadToTaltimeoutConstant WriteTotalTimeout=(WriteTotalTimeoutMuliplier*bytes_to_write) +WritetoTotalTimeoutConstant NOTE:在设置超时时参数0为无限等待,既无超时 参数MAXDWORD为立即返回 超时设置: GetCommTimeouts(hComm,&timeouts); SetCommTimeouts(hComm,&timeouts); 10.查询方式读写数据 例程: COMMTIMEOUTSto; DWORDReadThread(LPDWORDlpdwParam) { BYTEinbuff[100]; DWORDnBytesRead; if(!(cp.dwProvCapabilities&PCF_INTTIMEOUTS)) return1L; memset(&to,0,sizeof(to)); to.ReadIntervalTimeout=MAXDWORD; SetCommTimeouts(hComm,&to); while(bReading) { if(!ReadFile(hComm,inbuff,100,&nBytesRead,NULL)) locProcessCommError(GetLastError()); else if(nBytesRead) locProcessBytes(inbuff,nBytesRead); } PurgeComm(hComm,PURGE_RXCLEAR); return0L; } NOTE: PurgeComm()是一个清除函数,它可以中止任何未决的后台读或写,并且 可以冲掉I/O缓冲区. BOOLPurgeComm(HANDLEhFile,DWORDdwFlags); dwFlages的有效值: PURGE_TXABORT:中止后台写操作 PRUGE_RXABORT:中止后台读操作 PRUGE_TXCLEAR:清除发送缓冲区 PRUGE_RXCLEAR:清除接收缓冲区 技巧: 可通过ClearCommError()来确定接收缓区中处于等待的字节数。 BOOLClearCommError( HANDLEhFile,//handletocommunicationsdevice LPDWORDlpErrors,//pointertovariabletoreceiveerrorcodes LPCOMSTATlpStat//pointertobufferforcommunicationsstatus ); ClearCommError()将返回一个COMSTAT结构: typedefstruct_COMSTAT{//cst DWORDfCtsHold:1;//TxwaitingforCTSsignal DWORDfDsrHold:1;//TxwaitingforDSRsignal DWORDfRlsdHold:1;//TxwaitingforRLSDsignal DWORDfXoffHold:1;//Txwaiting,XOFFcharrec`d DWORDfXoffSent:1;//Txwaiting,XOFFcharsent DWORDfEof:1;//EOFcharactersent DWORDfTxim:1;//characterwaitingforTx DWORDfReserved:25;//reserved DWORDcbInQue;//bytesininputbuffer DWORDcbOutQue;//bytesinoutputbuffer }COMSTAT,*LPCOMSTAT; 其中的cbInQue和cbOutQue中即为缓冲区字节。 11.同步I/O读写数据 COMMTIOMOUTSto; DWORDReadThread(LPDWORDlpdwParam) { BYTEinbuff[100]; DWORDnByteRead,dwErrorMask,nToRead; COMSTATcomstat; if(!cp.dwProvCapabilities&PCF_TOTALTIMEOUTS) return1L; memset(&to,0,sizeof(to)); to.ReadTotalTimeoutMultiplier=5; to.ReadTotalTimeoutConstant=50; SetCommTimeouts(hComm,&to); while(bReading) { ClearCommError(hComm,&dwErrorMask,&comstat); if(dwErrorMask) locProcessCommError(dwErrorMask); if(comstat.cbInQue>100) nToRead=100; else nToRead=comstat.cbInQue; if(nToRead==0) continue; if(!ReadFile(hComm,inbuff,nToRead,&nBytesRead,NULL)) locProcessCommError(GetLastError()); else if(nBytesRead) locProcessBytes(inbuff,nBytesRead); } return0L; } 12.异步I/O读写数据 当CreateFile()中的fdwAttrsAndFlags参数为FILE_FLAG_OVERLAPPEN时, 端口是为异步I/O打开的,此时可以在ReadFile的最后一个参数中指定一个 OVERLAPPED结构,使数据的读操作在后台进行。WINDOWS95包括了异步 I/O的许多变种。 typedefstruct_OVERLAPPED{ DWORDInternal; DWORDInternalHigh; DWORDOffset; DWORDOffsetHigh; HANDLEhEvent; }OVERLAPPED; 对于串行口仅hEvent成员有效,其于成员必须为0。 例程: COMMTIMEOUTSto; ... DWORDReadThread((LPDWORDlpdwParam) { BYTEinbuff[100]; DWORDnRytesRead,endtime,lrc; staticOVERLAPPEDo; if(!cp.dwProvCapabilities&PCF_TOTALTIMEOUTS) return1L; memset(&to,0,sizeof(to)); to.ReadTotalTimeoutMultiplier=5; to.ReadTotalTimeoutConstant=1000; SetCommTimeouts(hComm,&to); o.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL); while(bReading) { if(!ReadFile(hComm,inbuff,10,&nBytesRead,&o)) { nBytesRead=0; if(lrc=GetLastError()==ERROR_IO_PENDING) { endtime=GetTickCount()+1000; while(!GetOverlappedResult(hComm,&o,&nBytesRead,FALSE)) if(GetTickCount()>endtime)break; } if(nBytesRead)locProcessBytes(inbuff,nBytesRead); } else { if(nBytesRead)locProcessBytes(inbuff,nBytesRead); ResetEvent(o.hEvent); } } PurgeComm(hComm,PURGE_RXCLEAR); return0L; } 这一例程是对一开始读缓冲区就读到所需的字节时的处理: while(bReading) { if(!ReadFile(hComm,inbuff,10,&nBytesRead,&o)) { if((lrc=GetLastError())==ERROR_IO_PENDING) { if(GetOverlappedResult(hComm,&o,&nBytesRead,TRUE)) { if(nBytesRead) locProcessBytesa(inbuff,nBytesRead); } else locProcessCommError(GetLastError()); } else locProcessCommError(GetLastError)); } else if(nBytesRead)locProcessBytes(inbuff,nBytesRead); ResetEvent(o.hEvent); } 13.事件驱I/O读写: GetCommMask(hComm,&dwMask) Windows95报告给应用程序的事件由此方法返回。 SetCommMasl(hComm,&dwMask) 添加或修改Windows95所报告的事件列表。 事件掩码如下: EV_BREAK检测到输入为止 EV_CTSCTS(清除发送)信号改变状态 EV_DSRDSR(数据设置就绪)信号改变状态 EV_ERR发生了线路状态错误. 线路状态错误为: CE_FRAME(帧错误) CE_OVERRUN(接收缓冲区超限) CE_RXPARITY(奇偶校验错误) EV_RING检测到振铃 EV_RLSDRLSD(接收线路信号检测)信号改变状态 EV_EXCHAR接收到一个字符,并放入输入缓冲区 EV_RXFLAG接收到事件字符(DCB成员的EvtChar成员),度放入输入缓冲区 EV_TXEMPTY输出缓冲区中最后一个字符发送出去 在用SetCommMask指定了有用的事件后,应用程序可调用WaitCommEvent()来等 待事件发生. BOOLWaitCommEvent( HANDLEhFile,//handleofcommunicationsdevice LPDWORDlpEvtMask,//addressofvariableforeventthatoccurred LPOVERLAPPEDlpOverlapped,//addressofoverlappedstructure ); 此方法可以以同步或异步方式操作 例程: COMMTIMEOUTSto; ... DWORDReadTherad(LPDWORDlpdwParam) { BYTEbinbuff[100]; DWORDnBytesRead,dwEvent,dwError; COMSTATcs; SetCommMask(hComm,EV_RXHAR); while(bReading) { if(WaitCommEvent(hComm,&dwEvent,NULL)) { ClearCommError(hComm,&dwError,&cs); if((dwEvent&EV_RXCHAR)&&cs.cbInQue) { if(!ReadFile(hComm,inbuff,cs.cbInQue,&nBytesRead,NULL) locProcessCommError(GetLastError()); } else { if(nByteRead) locProcessBytes(inbuff,nBytesRead); } else locProcessCommError(GetLastError()); } PurgeComm(hComm,PURGE_RXCLEAR); return0L; } NOTE:SetCommMask(hComm,0)可使WaitCommEvent()中止. 可使用GetCommmodemStatus()方法,例程: if(cp.dwProvCapabilities&PCF_RTSCTS) { SetCommMask(hComm,EV_CTS); WaitCommEvent(hComm,&dwMask,NULL); if(dwMask&EV_CTS) { GetCommModemStatus(hComm,&dwStatus) if(dwStatus&MS_CTS_ON)/*CTSstransitionOFF-ON*/ else/*CTSstransitionON-OFF*/ } } MS_CTS_ONCTS为ON MS_DSR_ONDSR为ON MS_RING_ONRING为ON MS_ELSD_ONRLSD为ON 14.错误 当发生错误时应用方法ClearCommError(hComm,&dwErrorMask,&constat) 得到错误掩码。 CE_BREAK中止条件 CE_FRAME帧错误 CW_IOE一般I/O错误,常伴有更为详细的错误标志 CE_MODE不支持请求的模式 CE_OVERRUN缓冲区超限下一个字符将丢失 CE_RXOVER接收缓冲区超限 CE_RXPARITY奇偶校验错误 CE_TXFULL发送缓冲区满 CE_DNS没有选择并行设备 CE_PTO并行设备发生超时 CE_OOP并行设备缺纸 15.控制命令 EscapeCommFunction()可将硬件信号置ON或OFF,模拟XON或XOFF BOOLEscapeCommFunction( HANDLEhFile,//handletocommunicationsdevice DWORDdwFunc//extendedfunctiontoperform ); dwFunc的有效值(可用‘|’同时使用多个值) CLRDTRDTR置OFF CLRRTSRTS置OFF SETDTRSTR置ON SETRTSTRS置ON SETXOFF模拟XOFF字符的接收 SETXON模拟XON字符的接收 SETBREAK在发送中产生一个中止 CLRBREAK在发送中清除中止 CSDN VC编程经验总结 |
本文地址:http://www.45fan.com/dnjc/73388.html