下载
加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 vc++串口编程

vc++串口编程.doc

vc++串口编程

lliuh2009
2013-01-15 0人阅读 举报 0 0 暂无简介

简介:本文档为《vc++串口编程doc》,可适用于IT/计算机领域

深入浅出VC串口编程之基本概念:作者:宋宝华出处:天极开发责任编辑:方舟  引言  在PC机的主板上有一种类型的接口可能为我们所忽视那就是RSC串行接口在微软的Windows系统中称其为COM。我们可以通过设备管理器来查看COM的硬件参数设置如图。图在Windows上查看PC串口设置  迄今为止几乎每一台PC都包含COM。本质而言COM是PC为和外界通信所提供的一种串行数据传输的接口。作为一种物理通信的途径和设备它和目前风靡的另一种串行接口――USB所提供的功能是一致的。不过RSC显然已经开始被后起之秀USB赶超因为USB的传输速率已经远远超过了RSC。  尽管如此RSC仍然具有非常广泛的应用在相对长的一段时间里难以被USB等接口取代。RSC接口(又称EIARSC)年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定全名是"数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准"。  本文将对这一接口进行硬件原理的介绍随后我们将逐章学习DOS平台的串口编程及Windows平台下基于API、控件和第三方类的串口编程最后本文将给出一个综合实例。  在本文的连载过程中您可以通过如下方式联系作者(热忱欢迎读者朋友对本文的内容提出质疑或给出修改意见):作者email:cnbaocncom(可以来信提问笔者将力求予以回信解答并摘取其中的典型问题在本系列文章最后一次连载的《读者反馈》中予以阐述)  硬件原理  众所周知CPU与存储芯片和IO芯片的通信是并行的(并行传输的最大位数依赖于CPU的字长、数据总线的宽度)一种叫做UART(通用异步收发器UniversalAsynchronousReceiverTransmitter)的芯片提供了并行数据传输和RSC串行数据传输方式的转换。这样的设备通常有如图所示的管脚分布当其向外传输数据时CPU并行的将数据写入这类芯片的寄存器UART再将寄存器中的数据一位一位地移动并向外传输当外界向其传输数据时UART一位一位地接收数据并将其移位组合为并行数据CPU再并行地读取这些数据。实际上由于UART芯片一般以TTLCMOS电平工作在UART连接接口之前还要经过一个TTLCMOS和RSC电平的转换。RSC规定了其标准的电气特性逻辑对应的电压必须在~V之间逻辑对应的的电压必须在~V之间。图UART并串转换  一个常见的TTLCMOS和RSC电平转换芯片如图。图常见的TTLCMOS和RSC电平转换芯片  RSC通常以两类接插件与外界相连分别称为DB和DB如图所示。图DB和DB  而接插件中各个针的定义则如表:  表DB和DB引脚定义DBDB针号功能说明缩写针号功能说明缩写数据载波检测DCD数据载波检测DCD接收数据RXD接收数据RXD发送数据TXD发送数据TXD数据终端准备DTR数据终端准备DTR信号地GND信号地GND数据设备准备好DSR数据准备好DSR请求发送RTS请求发送RTS清除发送CTS清除发送CTS振铃指示DELL振铃指示DELL  RSC定义为数据通信设备(DCE)和数据终端设备(DTE)之间的互连实现上到现在为止究竟一个设备属于DCE还是属于DTE已经没有明显的界限PC即可作为DCE又可作为DTE。两串口互连连接方法主要有二:  一种方法是数据的发送和接收由软件控制不进行硬件握手其连接方法如图(最常用DB连接示意)和表(DB、DB三线连接表)真正需要互相连接的是RXD、TXD和GND图无硬件握手时两串口连接  表DB、DB三线连接针-针针-针针-针  软件握手又称为XONXOFF通常以CTRLS(x)和CTRLQ(x)两个字符来实现流控制。前者用于请求对方暂停发送后者用于清除暂停传送的请求继续发送数据。  另一种方法是数据的发送和接收由硬件控制进行硬件握手其连接方法如图(最常用DB连接示意)需要连接的信号除RXD、TXD和GND外还包括DTR、DSR、RTS和CTS。  硬件握手依赖于RTS和CTS信号当发送设备欲发送数据时将RTS信号置为有效表示请求发送接收设备准备好后置CTS信号有效接着发送设备通过信号线TXD开始发送串行数据。  这里我们联想开来RTSCTS模式在许多领域里都出现过。回忆一下IEEE无线局域网协议标准在其MAC协议中就使用了RTSCTSRTSCTS抽象开来就是一种请求应答。笔者曾经在拙作中多次以实例论证计算机领域里许多知识的相通性这又是一个明证。图有硬件握手时两串口连接  实际上目前我们经常使用的是方法一即只连接RXD、TXD和GND简单灵活。另外串口之间互连还有诸多途径如图所示。图其它互连方式Win串口编程作者:韩耀旭下载源代码  在工业控制中工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信。串口通信方便易行应用广泛。一般情况下工控机和各智能仪表通过RS总线进行通信。RS的通信方式是半双工的只能由作为主节点的工控PC机依次轮询网络上的各智能控制单元子节点。每次通信都是由PC机通过串口向智能控制单元发布命令智能控制单元在接收到正确的命令后作出应答。  在Win下可以使用两种编程方式实现串口通信其一是使用ActiveX控件这种方法程序简单但欠灵活。其二是调用Windows的API函数这种方法可以清楚地掌握串口通信的机制并且自由灵活。本文我们只介绍API串口通信部分。  串口的操作可以有两种操作方式:同步操作方式和重叠操作方式(又称为异步操作方式)。同步操作时API函数会阻塞直到操作完成以后才能返回(在多线程方式中虽然不会阻塞主线程但是仍然会阻塞监听线程)而重叠操作方式API函数会立即返回操作在后台进行避免线程的阻塞。无论那种操作方式一般都通过四个步骤来完成:()打开串口()配置串口()读写串口()关闭串口()打开串口  Win系统把文件的概念进行了扩展。无论是文件、通信设备、命名管道、邮件槽、磁盘、还是控制台都是用API函数CreateFile来打开或创建的。该函数的原型为:HANDLECreateFile(LPCTSTRlpFileName,DWORDdwDesiredAccess,DWORDdwShareMode,LPSECURITYATTRIBUTESlpSecurityAttributes,DWORDdwCreationDistribution,DWORDdwFlagsAndAttributes,HANDLEhTemplateFile)·lpFileName:将要打开的串口逻辑名如“COM”·dwDesiredAccess:指定串口访问的类型可以是读取、写入或二者并列·dwShareMode:指定共享属性由于串口不能共享该参数必须置为·lpSecurityAttributes:引用安全性属性结构缺省值为·dwCreationDistribution:创建标志对串口操作该参数必须置为OPENEXISTING·dwFlagsAndAttributes:属性描述用于指定该串口是否进行异步操作该值为FILEFLAGOVERLAPPED表示使用异步的IO该值为表示同步IO操作·hTemplateFile:对串口而言该参数必须置为同步IO方式打开串口的示例代码:HANDLEhCom全局变量串口句柄hCom=CreateFile("COM",COM口GENERICREAD|GENERICWRITE,允许读和写,独占方式,OPENEXISTING,打开而不是创建,同步方式)if(hCom==(HANDLE)){AfxMessageBox("打开COM失败!")returnFALSE}returnTRUE重叠IO打开串口的示例代码:HANDLEhCom全局变量串口句柄hCom=CreateFile("COM",COM口GENERICREAD|GENERICWRITE,允许读和写,独占方式,OPENEXISTING,打开而不是创建FILEATTRIBUTENORMAL|FILEFLAGOVERLAPPED,重叠方式)if(hCom==INVALIDHANDLEVALUE){AfxMessageBox("打开COM失败!")returnFALSE}returnTRUE()、配置串口  在打开通讯设备句柄后常常需要对串口进行一些初始化配置工作。这需要通过一个DCB结构来进行。DCB结构包含了诸如波特率、数据位数、奇偶校验和停止位数等信息。在查询或配置串口的属性时都要用DCB结构来作为缓冲区。  一般用CreateFile打开串口后可以调用GetCommState函数来获取串口的初始配置。要修改串口的配置应该先修改DCB结构然后再调用SetCommState函数设置串口。  DCB结构包含了串口的各项参数设置下面仅介绍几个该结构常用的变量:typedefstructDCB{………波特率指定通信设备的传输速率。这个成员可以是实际波特率值或者下面的常量值之一:DWORDBaudRateCBRCBRCBRCBRCBRCBRCBRCBRCBRCBRCBRCBRCBRCBRCBRDWORDfParity指定奇偶校验使能。若此成员为允许奇偶校验检查…BYTEByteSize通信字节位数BYTEParity指定奇偶校验方法。此成员可以有下列值:EVENPARITY偶校验NOPARITY无校验MARKPARITY标记校验ODDPARITY奇校验BYTEStopBits指定停止位的位数。此成员可以有下列值:ONESTOPBIT位停止位TWOSTOPBITS位停止位ONESTOPBITS位停止位………}DCBwinbaseh文件中定义了以上用到的常量。如下:#defineNOPARITY#defineODDPARITY#defineEVENPARITY#defineONESTOPBIT#defineONESTOPBITS#defineTWOSTOPBITS#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBR#defineCBRGetCommState函数可以获得COM口的设备控制块从而获得相关参数:BOOLGetCommState(HANDLEhFile,标识通讯端口的句柄LPDCBlpDCB指向一个设备控制块(DCB结构)的指针)SetCommState函数设置COM口的设备控制块:BOOLSetCommState(HANDLEhFile,LPDCBlpDCB)  除了在BCD中的设置外程序一般还需要设置IO缓冲区的大小和超时。Windows用IO缓冲区来暂存串口输入和输出的数据。如果通信的速率较高则应该设置较大的缓冲区。调用SetupComm函数可以设置串行口的输入和输出缓冲区的大小。BOOLSetupComm(HANDLEhFile,通信设备的句柄DWORDdwInQueue,输入缓冲区的大小(字节数)DWORDdwOutQueue输出缓冲区的大小(字节数))  在用ReadFile和WriteFile读写串行口时需要考虑超时问题。超时的作用是在指定的时间内没有读入或发送指定数量的字符ReadFile或WriteFile的操作仍然会结束。  要查询当前的超时设置应调用GetCommTimeouts函数该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。  读写串口的超时有两种:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延。总超时是指读写操作总共花费的最大时间。写操作只支持总超时而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读写操作的超时。COMMTIMEOUTS结构的定义为:typedefstructCOMMTIMEOUTS{DWORDReadIntervalTimeout读间隔超时DWORDReadTotalTimeoutMultiplier读时间系数DWORDReadTotalTimeoutConstant读时间常量DWORDWriteTotalTimeoutMultiplier写时间系数DWORDWriteTotalTimeoutConstant写时间常量}COMMTIMEOUTS,*LPCOMMTIMEOUTSCOMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是:总超时=时间系数×要求读写的字符数+时间常量例如要读入个字符那么读操作的总超时的计算公式为:读总超时=ReadTotalTimeoutMultiplier×+ReadTotalTimeoutConstant可以看出:间隔超时和总超时的设置是不相关的这可以方便通信程序灵活地设置各种超时。如果所有写超时参数均为那么就不使用写超时。如果ReadIntervalTimeout为那么就不使用读间隔超时。如果ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为则不使用读总超时。如果读间隔超时被设置成MAXDWORD并且读时间系数和读时间常量都为那么在读一次输入缓冲区的内容后读操作就立即返回而不管是否读入了要求的字符。  在用重叠方式读写串口时虽然ReadFile和WriteFile在完成操作以前就可能返回但超时仍然是起作用的。在这种情况下超时规定的是操作的完成时间而不是ReadFile和WriteFile的返回时间。配置串口的示例代码:SetupComm(hCom,,)输入缓冲区和输出缓冲区的大小都是COMMTIMEOUTSTimeOuts设定读超时TimeOutsReadIntervalTimeout=TimeOutsReadTotalTimeoutMultiplier=TimeOutsReadTotalTimeoutConstant=设定写超时TimeOutsWriteTotalTimeoutMultiplier=TimeOutsWriteTotalTimeoutConstant=SetCommTimeouts(hCom,TimeOuts)设置超时DCBdcbGetCommState(hCom,dcb)dcbBaudRate=波特率为dcbByteSize=每个字节有位dcbParity=NOPARITY无奇偶校验位dcbStopBits=TWOSTOPBITS两个停止位SetCommState(hCom,dcb)PurgeComm(hCom,PURGETXCLEAR|PURGERXCLEAR)在读写串口之前还要用PurgeComm()函数清空缓冲区该函数原型:BOOLPurgeComm(HANDLEhFile,串口句柄DWORDdwFlags需要完成的操作)参数dwFlags指定要完成的操作可以是下列值的组合:PURGETXABORT中断所有写操作并立即返回即使写操作还没有完成。PURGERXABORT中断所有读操作并立即返回即使读操作还没有完成。PURGETXCLEAR清除输出缓冲区PURGERXCLEAR清除输入缓冲区()、读写串口我们使用ReadFile和WriteFile读写串口下面是两个函数的声明:BOOLReadFile(HANDLEhFile,串口的句柄读入的数据存储的地址即读入的数据将存储在以该指针的值为首地址的一片内存区LPVOIDlpBuffer,DWORDnNumberOfBytesToRead,要读入的数据的字节数指向一个DWORD数值该数值返回读操作实际读入的字节数LPDWORDlpNumberOfBytesRead,重叠操作时该参数指向一个OVERLAPPED结构同步操作时该参数为。LPOVERLAPPEDlpOverlapped)BOOLWriteFile(HANDLEhFile,串口的句柄写入的数据存储的地址即以该指针的值为首地址的nNumberOfBytesToWrite个字节的数据将要写入串口的发送数据缓冲区。LPCVOIDlpBuffer,DWORDnNumberOfBytesToWrite,要写入的数据的字节数指向指向一个DWORD数值该数值返回实际写入的字节数LPDWORDlpNumberOfBytesWritten,重叠操作时该参数指向一个OVERLAPPED结构同步操作时该参数为。LPOVERLAPPEDlpOverlapped)  在用ReadFile和WriteFile读写串口时既可以同步执行也可以重叠执行。在同步执行时函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞从而导致效率下降。在重叠执行时即使操作还未完成这两个函数也会立即返回费时的IO操作在后台进行。  ReadFile和WriteFile函数是同步还是异步由CreateFile函数决定如果在调用CreateFile创建句柄时指定了FILEFLAGOVERLAPPED标志那么调用ReadFile和WriteFile对该句柄进行的操作就应该是重叠的如果未指定重叠标志则读写操作应该是同步的。ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。  ReadFile函数只要在串口输入缓冲区中读入指定数量的字符就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区而且要等这些字符从串行口送出去后才算完成操作。  如果操作成功这两个函数都返回TRUE。需要注意的是当ReadFile和WriteFile返回FALSE时不一定就是操作失败线程应该调用GetLastError函数分析返回的结果。例如在重叠操作时如果操作还未完成函数就返回那么函数就返回FALSE而且GetLastError函数返回ERRORIOPENDING。这说明重叠操作还未完成。同步方式读写串口比较简单下面先例举同步方式读写串口的代码:同步读串口charstrDWORDwCount读取的字节数BOOLbReadStatbReadStat=ReadFile(hCom,str,,wCount,)if(!bReadStat){AfxMessageBox("读串口失败!")returnFALSE}returnTRUE同步写串口charlpOutBufferDWORDdwBytesWrite=COMSTATComStatDWORDdwErrorFlagsBOOLbWriteStatClearCommError(hCom,dwErrorFlags,ComStat)bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,dwBytesWrite,)if(!bWriteStat){AfxMessageBox("写串口失败!")}PurgeComm(hCom,PURGETXABORT|PURGERXABORT|PURGETXCLEAR|PURGERXCLEAR)在重叠操作时,操作还未完成函数就返回。  重叠IO非常灵活它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。有两种方法可以等待操作完成:一种方法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员另一种方法是调用GetOverlappedResult函数等待后面将演示说明。下面我们先简单说一下OVERLAPPED结构和GetOverlappedResult函数:OVERLAPPED结构OVERLAPPED结构包含了重叠IO的一些信息定义如下:typedefstructOVERLAPPED{oDWORDInternalDWORDInternalHighDWORDOffsetDWORDOffsetHighHANDLEhEvent}OVERLAPPED  在使用ReadFile和WriteFile重叠操作时线程需要创建OVERLAPPED结构以供这两个函数使用。线程通过OVERLAPPED结构获得当前的操作状态该结构最重要的成员是hEvent。hEvent是读写事件。当串口使用异步通讯时函数返回时操作可能还没有完成程序可以通过检查该事件得知是否读写完毕。  当调用ReadFile,WriteFile函数的时候该成员会自动被置为无信号状态当重叠操作完成后该成员变量会自动被置为有信号状态。GetOverlappedResult函数BOOLGetOverlappedResult(HANDLEhFile,串口的句柄指向重叠操作开始时指定的OVERLAPPED结构LPOVERLAPPEDlpOverlapped,指向一个位变量该变量的值返回实际读写操作传输的字节数。LPDWORDlpNumberOfBytesTransferred,该参数用于指定函数是否一直等到重叠操作结束。如果该参数为TRUE函数直到操作结束才返回。如果该参数为FALSE函数直接返回这时如果操作没有完成通过调用GetLastError()函数会返回ERRORIOINCOMPLETE。BOOLbWait)该函数返回重叠操作的结果用来判断异步操作是否完成它是通过判断OVERLAPPED结构中的hEvent是否被置位来实现的。异步读串口的示例代码:charlpInBufferDWORDdwBytesRead=COMSTATComStatDWORDdwErrorFlagsOVERLAPPEDmosReadmemset(mosRead,,sizeof(OVERLAPPED))mosReadhEvent=CreateEvent(,TRUE,FALSE,)ClearCommError(hCom,dwErrorFlags,ComStat)dwBytesRead=min(dwBytesRead,(DWORD)ComStatcbInQue)if(!dwBytesRead)returnFALSEBOOLbReadStatusbReadStatus=ReadFile(hCom,lpInBuffer,dwBytesRead,dwBytesRead,mosRead)if(!bReadStatus)如果ReadFile函数返回FALSE{if(GetLastError()==ERRORIOPENDING)GetLastError()函数返回ERRORIOPENDING,表明串口正在进行读操作{WaitForSingleObject(mosReadhEvent,)使用WaitForSingleObject函数等待直到读操作完成或延时已达到秒钟当串口读操作进行完毕后mosRead的hEvent事件会变为有信号PurgeComm(hCom,PURGETXABORT|PURGERXABORT|PURGETXCLEAR|PURGERXCLEAR)returndwBytesRead}return}PurgeComm(hCom,PURGETXABORT|PURGERXABORT|PURGETXCLEAR|PURGERXCLEAR)returndwBytesRead  对以上代码再作简要说明:在使用ReadFile函数进行读操作前应先使用ClearCommError函数清除错误。ClearCommError函数的原型如下:BOOLClearCommError(HANDLEhFile,串口句柄LPDWORDlpErrors,指向接收错误码的变量LPCOMSTATlpStat指向通讯状态缓冲区)该函数获得通信错误并报告串口的当前状态同时该函数清除串口的错误标志以便继续输入、输出操作。参数lpStat指向一个COMSTAT结构该结构返回串口状态信息。COMSTAT结构COMSTAT结构包含串口的信息结构定义如下:typedefstructCOMSTAT{cstDWORDfCtsHold:TxwaitingforCTSsignalDWORDfDsrHold:TxwaitingforDSRsignalDWORDfRlsdHold:TxwaitingforRLSDsignalDWORDfXoffHold:Txwaiting,XOFFcharrec''dDWORDfXoffSent:Txwaiting,XOFFcharsentDWORDfEof:EOFcharactersentDWORDfTxim:characterwaitingforTxDWORDfReserved:reservedDWORDcbInQuebytesininputbufferDWORDcbOutQuebytesinoutputbuffer}COMSTAT,*LPCOMSTAT本文只用到了cbInQue成员变量该成员变量的值代表输入缓冲区的字节数。  最后用PurgeComm函数清空串口的输入输出缓冲区。  这段代码用WaitForSingleObject函数来等待OVERLAPPED结构的hEvent成员下面我们再演示一段调用GetOverlappedResult函数等待的异步读串口示例代码:charlpInBufferDWORDdwBytesRead=BOOLbReadStatusDWORDdwErrorFlagsCOMSTATComStatOVERLAPPEDmosReadClearCommError(hCom,dwErrorFlags,ComStat)if(!ComStatcbInQue)returndwBytesRead=min(dwBytesRead,(DWORD)ComStatcbInQue)bReadStatus=ReadFile(hCom,lpInBuffer,dwBytesRead,dwBytesRead,mosRead)if(!bReadStatus)如果ReadFile函数返回FALSE{if(GetLastError()==ERRORIOPENDING){GetOverlappedResult(hCom,mosRead,dwBytesRead,TRUE)GetOverlappedResult函数的最后一个参数设为TRUE函数会一直等待直到读操作完成或由于错误而返回。returndwBytesRead}return}returndwBytesRead异步写串口的示例代码:charbufferDWORDdwBytesWritten=DWORDdwErrorFlagsCOMSTATComStatOVERLAPPEDmosWriteBOOLbWriteStatbWriteStat=WriteFile(hCom,buffer,dwBytesWritten,dwBytesWritten,mOsWrite)if(!bWriteStat){if(GetLastError()==ERRORIOPENDING){WaitForSingleObject(mosWritehEvent,)returndwBytesWritten}return}returndwBytesWritten()、关闭串口  利用API函数关闭串口非常简单只需使用CreateFile函数返回的句柄作为参数调用CloseHandle即可:BOOLCloseHandle(HANDLEhObjecthandletoobjecttoclose)串口编程的一个实例  为了让您更好地理解串口编程,下面我们分别编写两个例程(见附带的源码部分),这两个例程都实现了工控机与百特显示仪表通过RS接口进行的串口通信。其中第一个例程采用同步串口操作,第二个例程采用异步串口操作。  我们只介绍软件部分RS接口接线方法不作介绍感兴趣的读者可以查阅相关资料。例程  打开VC新建基于对话框的工程RSComm在主对话框窗口IDDRSCOMMDIALOG上添加两个按钮ID分别为IDCSEND和IDCRECEIVE标题分别为“发送”和“接收”添加一个静态文本框IDCDISP用于显示串口接收到的内容。在RSCommDlgcpp文件中添加全局变量:HANDLEhCom全局变量串口句柄在RSCommDlgcpp文件中的OnInitDialog()函数添加如下代码:TODO:AddextrainitializationherehCom=CreateFile("COM",COM口GENERICREAD|GENERICWRITE,允许读和写,独占方式,OPENEXISTING,打开而不是创建,同步方式)if(hCom==(HANDLE)){AfxMessageBox("打开COM失败!")returnFALSE}SetupComm(hCom,,)输入缓冲区和输出缓冲区的大小都是COMMTIMEOUTSTimeOuts设定读超时TimeOutsReadIntervalTimeout=MAXDWORDTimeOutsReadTotalTimeoutMultiplier=TimeOutsReadTotalTimeoutConstant=在读一次输入缓冲区的内容后读操作就立即返回而不管是否读入了要求的字符。设定写超时TimeOutsWriteTotalTimeoutMultiplier=TimeOutsWriteTotalTimeoutConstant=SetCommTimeouts(hCom,TimeOuts)设置超时DCBdcbGetCommState(hCom,dcb)dcbBaudRate=波特率为dcbByteSize=每个字节有位dcbParity=NOPARITY无奇偶校验位dcbStopBits=TWOSTOPBITS两个停止位SetCommState(hCom,dcb)PurgeComm(hCom,PURGETXCLEAR|PURGERXCLEAR)分别双击IDCSEND按钮和IDCRECEIVE按钮添加两个按钮的响应函数:voidCRSCommDlg::OnSend(){TODO:Addyourcontrolnotificationhandlercodehere在此需要简单介绍百特公司XMA的通讯协议:该仪表RS通讯采用主机广播方式通讯。串行半双工帧位个起始位()个数据位个停止位()如:读仪表显示的瞬时值主机发送:DCAAABBETX其中:DC是标准ASCII码的一个控制符号码值为H(十进制的)在XMA的通讯协议中DC表示读瞬时值AAA是从机地址码也就是XMA显示仪表的通讯地址BB为通道号读瞬时值时该值为ETX也是标准ASCII码的一个控制符号码值为H在XMA的通讯协议中ETX表示主机结束符charlpOutBuffermemset(lpOutBuffer,'''',)前个字节先清零lpOutBuffer=''x''发送缓冲区的第个字节为DClpOutBuffer=''''第个字节为字符(H)lpOutBuffer=''''第个字节为字符(H)lpOutBuffer=''''第个字节为字符(H)lpOutBuffer=''''第个字节为字符(H)lpOutBuffer=''''第个字节为字符(H)lpOutBuffer=''x''第个字节为字符ETX从该段代码可以看出仪表的通讯地址为DWORDdwBytesWrite=COMSTATComStatDWORDdwErrorFlagsBOOLbWriteStatClearCommError(hCom,dwErrorFlags,ComStat)bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,dwBytesWrite,)if(!bWriteStat){AfxMessageBox("写串口失败!")}}voidCRSCommDlg::OnReceive(){TODO:Addyourcontrolnotificationhandlercodeherecharstrmemset(str,'''',)DWORDwCount=读取的字节数BOOLbReadStatbReadStat=ReadFile(hCom,str,wCount,wCount,)if(!bReadStat)AfxMessageBox("读串口失败!")PurgeComm(hCom,PURGETXABORT|PURGERXABORT|PURGETXCLEAR|PURGERXCLEAR)mdisp=strUpdateData(FALSE)}您可以观察返回的字符串其中有和仪表显示值相同的部分您可以进行相应的字符串操作取出仪表的显示值。打开ClassWizard,为静态文本框IDCDISP添加CString类型变量mdisp同时添加WMCLOSE的相应函数:voidCRSCommDlg::OnClose(){TODO:AddyourmessagehandlercodehereandorcalldefaultCloseHandle(hCom)程序退出时关闭串口CDialog::OnClose()}程序的相应部分已经在代码内部作了详细介绍。连接好硬件部分编译运行程序细心体会串口同步操作部分。例程  打开VC新建基于对话框的工程RSComm在主对话框窗口IDDRSCOMMDIALOG上添加两个按钮ID分别为IDCSEND和IDCRECEIVE标题分别为“发送”和“接收”添加一个静态文本框IDCDISP用于显示串口接收到的内容。在RSCommDlgcpp文件中添加全局变量:HANDLEhCom全局变量串口句柄在RSCommDlgcpp文件中的OnInitDialog()函数添加如下代码:hCom=CreateFile("COM",COM口GENERICREAD|GENERICWRITE,允许读和写,独占方式,OPENEXISTING,打开而不是创建FILEATTRIBUTENORMAL|FILEFLAGOVERLAPPED,重叠方式)if(hCom==(HANDLE)){AfxMessageBox("打开COM失败!")returnFALSE}SetupComm(hCom,,)输入缓冲区和输出缓冲区的大小都是COMMTIMEOUTSTimeOuts设定读超时TimeOutsReadIntervalTimeout=MAXDWORDTimeOutsReadTotalTimeoutMultiplier=TimeOutsReadTotalTimeoutConstant=在读一次输入缓冲区的内容后读操作就立即返回而不管是否读入了要求的字符。设定写超时TimeOutsWriteTotalTimeoutMultiplier=TimeOutsWriteTotalTimeoutConstant=SetCommTimeouts(hCom,TimeOuts)设置超时DCBdcbGetCommState(hCom,dcb)dcbBaudRate=波特率为dcbByteSize=每个字节有位dcbParity=NOPARITY无奇偶校验位dcbStopBits=TWOSTOPBITS两个停止位SetCommState(hCom,dcb)PurgeComm(hCom,PURGETXCLEAR|PURGERXCLEAR)分别双击IDCSEND按钮和IDCRECEIVE按钮添加两个按钮的响应函数:voidCRSCommDlg::OnSend(){TODO:AddyourcontrolnotificationhandlercodehereOVERLAPPEDmosWritememset(mosWrite,,sizeof(OVERLAPPED))mosWritehEvent=CreateEvent(,TRUE,FALSE,)charlpOutBuffermemset(lpOutBuffer,'''',)lpOutBuffer=''x''lpOutBuffer=''''lpOutBuffer=''''lpOutBuffer=''''lpOutBuffer=''''lpOutBuffer=''''lpOutBuffer=''x''DWORDdwBytesWrite=COMSTATComStatDWORDdwErrorFlagsBOOLbWriteStatClearCommError(hCom,dwErrorFlags,ComStat)bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,dwBytesWrite,mosWrite)if(!bWriteStat){if(GetLastError

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/35

vc++串口编程

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利