C#调用API串口通信_第1页
C#调用API串口通信_第2页
C#调用API串口通信_第3页
C#调用API串口通信_第4页
C#调用API串口通信_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

c#调api串口通信C#在调试ICU通信设备的时候,由于串口通信老出现故障,所以就怀疑CF实现的SerialPort类是否有问题,所以最后决定用纯API函数实现串口读写。先从网上搜索相关代码(关键字:C#API串口),发现网上相关的资料大约来源于一个版本,那就是所谓的msdn提供的样例代码(msdn的具体出处,我没有考证),其它的代码大都是它的变种。其实这个示例代码是有问题的,也就是说DCB结构体声明的有问题,虽然该代码可以正常通信,不过如果你设置了奇偶校验的话,你会发现奇偶校验无效。VC中的DCB结构声明如下:typedefstruct_DCB{TOC\o"1-5"\h\zDWORDDCBlength;/*sizeof(DCB) */DWORDBaudRate;/*Baudrateatwhichrunning*/DWORDfBinary:1; /*BinaryMode(skipEOFcheck)*/DWORDfParity:1; /*Enableparitychecking*/DWORDfOutxCtsFlow:1;/*CTShandshakingonoutput */DWORDfOutxDsrFlow:1;/*DSRhandshakingonoutput */DWORDfDtrControl:2;/*DTRFlowcontrol */DWORDfDsrSensitivity:1;/*DSRSensitivity */DWORDfTXContinueOnXoff:1;/*ContinueTXwhenXoffsent*/DWORDfOutX:1; /*EnableoutputX-ON/X-OFF*/DWORDfInX:1; /*EnableinputX-ON/X-OFF*/DWORDfErrorChar:1;/*EnableErrReplacement */DWORDfNull:1; /*EnableNullstripping */DWORDfRtsControl:2;/*RtsFlowcontrol */DWORDfAbortOnError:1;/*AbortallreadsandwritesonError*/DWORDfDummy2:17;/*Reserved */WORDwReserved;/*Notcurrentlyused */WORDXonLim; /*TransmitX-ONthreshold*/WORDXoffLim;/*TransmitX-OFFthreshold*/BYTEByteSize;/*Numberofbits/byte,4-8 */BYTEParity;/*0-4=None,Odd,Even,Mark,Space*/BYTEStopBits;/*0,1,2=1,1.5,2 */charXonChar; /*TxandRxX-ONcharacter*/charXoffChar;/*TxandRxX-OFFcharacter*/charErrorChar;/*Errorreplacementchar*/charEofChar;/*EndofInputcharacter*/charEvtChar;/*ReceivedEventcharacter*/WORDwReserved1;/*Fillfornow. */}DCB,*LPDCB;有问题的代码DCB结构声明如下:[StructLayout(LayoutKind.Sequential)]publicstructDCB{publicintDCBlength;publicintBaudRate;publicintfBinary;publicintfParity;publicintfOutxCtsFlow;publicintfOutxDsrFlow;publicintfDtrControl;publicintfDsrSensitivity;publicintfTXContinueOnXoff;publicintfOutX;publicintflnX;publicintfErrorChar;publicintfNull;publicintfRtsControl;publicintfAbortOnError;publicintfDummy2;publicuintflags;publicushortwReserved;publicushortXonLim;publicushortXoffLim;publicbyteByteSize;publicbyteParity;publicbyteStopBits;publicbyteXonChar;publicbyteXoffChar;publicbyteErrorChar;publicbyteEofChar;publicbyteEvtChar;publicushortwReserved1;}对C++比较熟悉网友应该知道,结构体中这种格式的声明,如DWORDfBinary:1;是以位为单位进行变量设置的,DCB中相关位一共占4个字节,也就是相当于C#中的一个int变量所占的空间。很明显上面的DCB结构会有问题,实际上后面你设置的串口参数,如奇偶校验由于偏移有问题,虽然你设置了,其实都没有设置成功。其实也不是我说人家的DCB声明错了就错了,在SerialPort类中你就可以找到微软官方自己的DCB声明(需要反编译SerialPort类),声明如下:[StructLayout(LayoutKind.Sequential)]publicstructDCB{publicintDCBlength;publicintBaudRate;publicuintFlags;publicushortwReserved;publicushortXonLim;publicushortXoffLim;publicbyteByteSize;publicbyteParity;publicbyteStopBits;publicbyteXonChar;publicbyteXoffChar;publicbyteErrorChar;publicbyteEofChar;publicbyteEvtChar;publicushortwReserved1;}并且专门有一个设置位标志的函数,如下:internalvoidSetDcbFlag(intwhichFlag,intsetting){uintnum;setting=setting<<whichFlag;if((whichFlag==4)||(whichFlag==12)){num=3;}elseif(whichFlag==15){num=Ox1ffff;}else{num=1;}dcb.flags&=~(num<<whichFlag);dcb.flags|=(uint)setting;}经过修改能正确运行的API代码如下(注意,由于我是在WinCE平台上运行,所以DLL的路径为"//windows//coredll.dll",你修改为"kernel32"后即可在PC机使用):〃/vsummary>///API串口类/yefanqiu///v/summary>publicclassCommPort{///vsummary>///端口名称(COM1,COM2...COM4..J///v/summary>publicstringPort="COM1:";〃/vsummary>///波特率9600///v/summary>publicintBaudRate=9600;///vsummary>///数据位4-8///v/summary>publicbyteByteSize=8;〃4-8///vsummary>〃/奇偶校验0-4=no,odd,even,mark,space///v/summary>publicbyteParity=0;〃0-4=no,odd,even,mark,space///vsummary>///停止位///v/summary>publicbyteStopBits=0;〃0,1,2=1,1.5,2///vsummary>///超时长///v/summary>publicintReadTimeout=200;///vsummary>///串口是否已经打开///v/summary>publicboolOpened=false;///vsummary>///COM口句柄///v/summary>privateinthComm=-1;#region"API相关定义"privateconststringDLLPATH="//windows//coredll.dll";//"PC机请使用kernel32.dll";///vsummary>///WINAPI常量,写标志///v/summary>privateconstuintGENERIC_READ=0x80000000;///vsummary>///WINAPI常量,读标志///v/summary>privateconstuintGENERIC_WRITE=0x40000000;///vsummary>///WINAPI常量,打开已存在///v/summary>privateconstintOPEN_EXISTING=3;〃/vsummary>IIIWINAPI常量,无效句柄///v/summary>privateconstintINVALID_HANDLE_VALUE=-1;privateconstintPURGE_RXABORT=0x2;privateconstintPURGE_RXCLEAR=0x8;privateconstintPURGE_TXABORT=0x1;privateconstintPURGE_TXCLEAR=0x4;///vsummary>///设备控制块结构体类型///v/summary>[StructLayout(LayoutKind.Sequential)]publicstructDCB{///vsummary>///DCB长度///v/summary>publicintDCBlength;///vsummary>〃/指定当前波特率///v/summary>publicintBaudRate;///vsummary>///标志位///v/summary>publicuintflags;///vsummary>〃/未使用,必须为0///v/summary>publicushortwReserved;///vsummary>〃/指定在XON字符发送这前接收缓冲区中可允许的最小字节数///v/summary>publicushortXonLim;///vsummary>〃/指定在XOFF字符发送这前接收缓冲区中可允许的最小字节数///v/summary>publicushortXoffLim;///vsummary>///指定端口当前使用的数据位///v/summary>publicbyteByteSize;〃/vsummary>///指定端口当前使用的奇偶校验方法,可能为:EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY0-4=no,odd,even,mark,space///v/summary>publicbyteParity;///vsummary>///指定端口当前使用的停止位数,可能为:ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS0,1,2=1,1.5,2///v/summary>publicbyteStopBits;///vsummary>///指定用于发送和接收字符XON的值TxandRxXONcharacter///v/summary>publicbyteXonChar;///vsummary>///指定用于发送和接收字符XOFF值TxandRxXOFFcharacter///v/summary>publicbyteXoffChar;///vsummary>〃/本字符用来代替接收到的奇偶校验发生错误时的值///v/summary>publicbyteErrorChar;///vsummary>〃/当没有使用二进制模式时,本字符可用来指示数据的结束///v/summary>publicbyteEofChar;///vsummary>〃/当接收到此字符时,会产生一个事件///v/summary>publicbyteEvtChar;///vsummary>〃/未使用///v/summary>publicushortwReservedl;}///vsummary>///串口超时时间结构体类型///v/summary>[StructLayout(LayoutKind.Sequential)]privatestructCOMMTIMEOUTS{publicintReadIntervalTimeout;publicintReadTotalTimeoutMultiplier;publicintReadTotalTimeoutConstant;publicintWriteTotalTimeoutMultiplier;publicintWriteTotalTimeoutConstant;}〃/vsummary>///溢出缓冲区结构体类型///v/summary>[StructLayout(LayoutKind.Sequential)]privatestructOVERLAPPED{publicintInternal;publicintInternalHigh;publicintOffset;publicintOffsetHigh;publicinthEvent;}///vsummary>〃/打开串口///v/summary>///vparamname="lpFileName">要打开的串口名称v/param>///vparamname="dwDesiredAccess">指定串口的访问方式,一般设置为可读可写方式v/param>///vparamname="dwShareMode">指定串口的共享模式,串口不能共享,所以设置为0v/param>///vparamname="lpSecurityAttributes">设置串口的安全属性,WIN9X下不支持,应设为NULLv/param>///vparamname="dwCreationDisposition">对于串口通信,创建方式只能为OPEN_EXISTINGv/param>///vparamname="dwFlagsAndAttributes">指定串口属性与标志,设置为FILE_FLAG_OVERLAPPED(重叠I/O操作),指定串口以异步方式通信v/param>///vparamname="hTemplateFile">对于串口通信必须设置为NULLv/param>[DllImport(DLLPATH)]privatestaticexternintCreateFile(stringlpFileName,uintdwDesiredAccess,intdwShareMode,intlpSecurityAttributes,intdwCreationDisposition,intdwFlagsAndAttributes,inthTemplateFile);///vsummary>///得到串口状态///v/summary>///vparamname="hFile">通信设备句柄v/param>///vparamname="lpDCB">设备控制块DCBv/param>[Dlllmport(DLLPATH)]privatestaticexternboolGetCommState(inthFile,refDCBlpDCB);〃/vsummary>///建立串口设备控制块(嵌入版没有)///v/summary>///vparamname="lpDef">设备控制字符串v/param>///vparamname="lpDCB">设备控制块v/param>//[Dlllmport(DLLPATH)]//privatestaticexternboolBuildCommDCB(stringlpDef,refDCBlpDCB);///vsummary>///设置串口状态///v/summary>///vparamname="hFile">通信设备句柄v/param>///vparamname="lpDCB">设备控制块v/param>[Dlllmport(DLLPATH)]privatestaticexternboolSetCommState(inthFile,refDCBlpDCB);///vsummary>〃/读取串口超时时间///v/summary>///vparamname="hFile">通信设备句柄v/param>///vparamname="lpCommTimeouts">超时时间v/param>[Dlllmport(DLLPATH)]privatestaticexternboolGetCommTimeouts(inthFile,refCOMMTIMEOUTSlpCommTimeouts);///vsummary>///设置串口超时时间///v/summary>///vparamname="hFile">通信设备句柄v/param>///vparamname="lpCommTimeouts">超时时间v/param>[Dlllmport(DLLPATH)]privatestaticexternboolSetCommTimeouts(inthFile,refCOMMTIMEOUTSlpCommTimeouts);///vsummary>〃/读取串口数据///v/summary>///vparamname="hFile">通信设备句柄v/param>///vparamname="lpBuffer">数据缓冲区v/param>///vparamname="nNumberOfBytesToRead">多少字节等待读取v/param>///vparamname="lpNumberOfBytesRead">读取多少字节v/param>///vparamname="lpOverlapped">溢出缓冲区v/param>[Dlllmport(DLLPATH)]privatestaticexternboolReadFile(inthFile,byte[]IpBuffer,intnNumberOfBytesToRead,refintIpNumberOfBytesRead,refOVERLAPPEDlpOverlapped);///<summary>///写串口数据///</summary>///vparamname="hFile">通信设备句柄</param>///vparamname="lpBuffer">数据缓冲区v/param>///vparamname="nNumberOfBytesToWrite">多少字节等待写入v/param>///vparamname="lpNumberOfBytesWritten">已经写入多少字节v/param>///vparamname="lpOverlapped">溢出缓冲区v/param>[Dlllmport(DLLPATH)]privatestaticexternboolWriteFile(inthFile,byte[]lpBuffer,intnNumberOfBytesToWrite,refintIpNumberOfBytesWritten,refOVERLAPPEDlpOverlapped);[DllImport(DLLPATH,SetLastError=true)]privatestaticexternboolFlushFileBuffers(inthFile);[DllImport(DLLPATH,SetLastError=true)]privatestaticexternboolPurgeComm(inthFile,uintdwFlags);///vsummary>///关闭串口///v/summary>///vparamname="hObject">通信设备句柄v/param>[Dlllmport(DLLPATH)]privatestaticexternboolCloseHandle(inthObject);///vsummary>///得到串口最后一次返回的错误///v/summary>[Dlllmport(DLLPATH)]privatestaticexternuintGetLastError();#endregion///vsummary>///设置DCB标志位///v/summary>///vparamname="whichFlag"x/param>///vparamname="setting"x/param>///vparamname="dcb"x/param>internalvoidSetDcbFlag(intwhichFlag,intsetting,DCBdcb){uintnum;setting=setting<<whichFlag;if((whichFlag==4)||(whichFlag==12)){num=3;}elseif(whichFlag==15){num=Ox1ffff;}else{num=1;}dcb.flags&=~(num<<whichFlag);dcb.flags|=(uint)setting;}///<summary>〃/建立与串口的连接///</summary>publicintOpen(){DCBdcb=newDCB();COMMTIMEOUTSctoCommPort=newCOMMTIMEOUTS();//打开串口hComm=CreateFile(Port,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);if(hComm==INVALID_HANDLE_VALUE){return-1;}//设置通信超时时间GetCommTimeouts(hComm,refctoCommPort);ctoCommPort.ReadTotalTimeoutConstant=ReadTimeout;ctoCommPort.ReadTotalTimeoutMultiplier=0;ctoCommPort.WriteTotalTimeoutMultiplier=0;ctoCommPort.WriteTotalTimeoutConstant=0;SetCommTimeouts(hComm,refctoCommPort);

〃设置串口参数GetCommState(hComm,refdeb);dcb.DCBIength=Marshal.SizeOf(dcb);dcb.BaudRate=BaudRate;dcb.flags=0;dcb.ByteSize=(byte)ByteSize;dcb.StopBits=StopBits;dcb.Parity=(byte)Parity;// SetDcbFlag(0,1,dcb);SetDcbFlag(1,(Parity==0)SetDcbFlag(2,0,dcb);SetDcbFlag(3,0,dcb);SetDcbFlag(4,0,dcb);SetDcbFlag(6,0,dcb);SetDcbFlag(9,1,dcb);SetDcbFlag(8,0,dcb);SetDcbFlag(10,0,dcb);SetDcbFlag(11,0,dcb);SetDcbFlag(12,0,dcb);SetDcbFlag(14,0,dcb);// dcb.wReserved=0;dcb.XonLim=0;允许的最小字节数dcb.XoffLim=0;小可用字节数dcb.XonChar=0;dcb.XoffChar=0;dcb.ErrorChar=0;dcb.EofChar=0;dcb.EvtChar=0;件dcb.wReserved1=0;〃二进制方式0:1,dcb);〃不用〃二进制方式0:1,dcb);〃不用CTS检测发送流控制〃不用DSR检测发送流控制〃禁止DTR流量控制〃对DTR信号线不敏感〃检测接收缓冲区〃不做发送字符控制〃是否用指定字符替换校验错的字符〃保留NULL字符〃允许RTS流量控制〃发送错误后,继续进行下面的读写操作〃没有使用,必须为0〃指定在XOFF字符发送之前接收到缓冲区中可〃指定在XOFF字符发送之前缓冲区中可允许的最〃发送和接收的XON字符〃发送和接收的XOFF字符〃代替接收到奇偶校验错误的字符〃用来表示数据的结束〃事件字符,接收到此字符时,会产生一个事〃没有使用return-2;}Opened=true;return0;〃/vsummary>///关闭串口,结束通讯///v/s

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论