MSComm控件在中文Windows下的通信问题与处理方法_第1页
MSComm控件在中文Windows下的通信问题与处理方法_第2页
MSComm控件在中文Windows下的通信问题与处理方法_第3页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

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

文档简介

MSComm控件在中文Windows下的通信问题与处理方法

摘要VB5.0/6.0的MSComm通信控件提供了一系列标准通信命令的接口,它允许建立串口连接,但在实际通信软件设计过程中,MSComm控件并非像想像中那样完美和容易控制,特别是在中文Windows下通信时更会出现问题。本文就MSComm控件在实际应用中可能出现的问题以及编程技巧进行探讨。关键词MsComm控件串口通信

处理1.MSComm控件的基础理论一般说来,计算机都有一个或多个串行端口,它们依次为Com1、Com2、...。这些串口还提供了外部设备与PC进行数据传输和通信的通道,这些串口在CPU和外设之间充当解释器的角色。当字符数据从CPU发送给外设时,这些字符数据将被转换成串行比特流数据;当接收数据时,比特流数据被转换为字符数据传递给CPU。再进一步说,在操作系统方面,Windows用通信驱动程序(COMM.DRV)调用API函数发送和接收数据。当用通信控件或声明调用API函数时,它们由COMM.DRV解释并传递给设备驱动程序。作为一个VB程序员,要编写通信程序,只需知道通信控件提供给Windows通信API函数的接口即可,换句话说,只需设定和监视通信控件的属性和事件即可。2.利用MSComm控件进行数据的接收和发送搞清楚以上基本属性和事件后就可以开始编写通信程序了:在VB5.0/6.0中新建一个工程文件,添加MicrosoftCommcontrol5.0组件,在窗体Form1中加入Command命令按钮并取名为cmdTest,MSComm控件取名为MSComm1,写入以下代码:PrivateSubcmdTest_Click()MSComm1.CommPort=1'设定Com1口IfMSComm1.PortOpen=FalseThen

MSComm1.Settings="9600,N,8,1"

'9600波特率,无校验,8位数据位,1位停止位

MSComm1.PortOpen=True

'打开串口EndIfMSComm1.OutBufferCount=0

'清空发送缓冲区MSComm1.InBufferCount=0

'清空接收缓冲区'发送字符数据,注意必须用回车符(vbCr)结束MSComm1.Output="Thisisagoodbook!"&vbCr'拨打电话号码或发送AT命令MSComm1.Output="ATDT0294563622"&vbCr'发送字符数组数据,注意ByteArray必须事先定义赋值DimByteArrayasbyte()

'定义动态数组

ReDimByteArray(1)'重定义数组大小

ByteArray(0)=0

ByteArray(1)=1

MSComm1.Output=ByteArray'发送字符数组数据EndSubPrivateSubMSComm1_OnComm()SelectCaseMSComm1.CommEvent

CasecomEvReceive'接收字符数据DimBufferAsVariantMSComm1.InputLen=0'当InputMode属性值为0(文本模式)时,变量中含String型数据。'当InputMode属性值为1(二进制模式)时,变量中含Byte型数组数据。MSComm1.InputMode=comInputModeBinaryBuffer=MSComm1.Input

'接收二进制数据MSComm1.InputMode=comInputModeTextBuffer=MSComm1.Input

CaseelseEndSelectEndSub3.中文Windows下的通信问题与解决方法3.1接收的数据少于发送的数据如果通过MSComm控件一次性传送较多的二进制数据,那么,很可能收到的数据不足。例如在设置为2400bps传输率的情况下,一次性可以传输2048个字符数据,那么在大多数情况下一次只能收到1200个字符左右,这是因为新版的MSComm32.OCX中存在一个影响传输二进制数据的Bug。32位WindowsAPI函数使用了几个用COMMTIMEOUTS结构表示的限时变量,WriteTotalTimeOutConstant即是其中的一个,它被Windows内部设定为5000(即5秒),这个常量决定了在通信驱动程序停止传输之前花费在发送缓冲区中数据的时间的长短。5秒钟意味着通信速度为1200bps情况下仅能发送600个字符,2400bps情况下仅能发送1200个左右的字符。事实上,在一个缓冲区内一次性发送更多的数据是非常可能的。VB5.0/6.0版本的MSComm控件有一个新增的重要的属性称为CommID,CommID指的是当串口被打开时,被API所调用的串口句柄(或标志),这也意味着能利用API接口函数去修改这个常量。每次串口关闭后,Windows会自动将之恢复为5000,所以,每次打开串口后需要重新设定。以下是API声明代码:TypeCOMMTIMEOUTSReadIntervalTimeoutAsLongReadTotalTimeoutMultiplierAsLong

ReadTotalTimeoutConstantAsLong

WriteTotalTimeoutMultiplierAsLong

WriteTotalTimeoutConstantAsLongEndTypeDeclareFunctionSetCommTimeoutsLib"Kernel32"(ByValhFileAsLong,_lpCommTimeoutsAsCOMMTIMEOUTS)AsLongDeclareFunctionGetCommTimeoutsLib"Kernel32"(ByValhFileAsLong,_lpCommTimeoutsAsCOMMTIMEOUTS)AsLongDimtimeoutsAsCOMMTIMEOUTSDimRetAsLongIfComm1.PortOpen=FalseThen

Comm1.PortOpen=TrueEndIf'打开串口后重新设定串口句柄Ret=GetCommTimeouts(Comm1.CommID,timeouts)'Setsomedefaulttimeoutstimeouts.ReadIntervalTimeout=1timeouts.ReadTotalTimeoutMultiplier=1timeouts.ReadTotalTimeoutConstant=1timeouts.WriteTotalTimeoutMultiplier=1timeouts.WriteTotalTimeoutConstant=(Comm1.OutBufferSize\Val(Comm1.Settings))*10000+1000Ret=SetCommTimeouts(Comm1.CommID,timeouts)3.2如何发送大于128的字符数据在通信程序中,以单字符方式逐个发送数据时,每一个数据范围为0-255(即十六进制的00-FF)。在单字符版本的英文Windows或DOS版的BASIC程序中,只需要将相应的数据转换成相应的字符发送到通信端口即可。但在中文Windows下却行不通,假设在中文Windows下运行以下程序:DimiasIntegerFori=0To255

MSComm1.Output=chr(i)Nexti希望在接收端得到预期的0-255之间的数据,结果却是:前129个数据接收正确,为0-128,后面127个数据为126个0和一个255。造成这种结果的原因在于中文Windows使用的是双字节字符集(DBCS)系统。DBCS系统使用0-128之间的数字表示ASCII字符,大于128的数字仅作为前导字符,它只是显示是一个非拉丁语系的字符,而并不代表实际意义。上述程序在调用CHR()函数时用到了DBCS字符集,因此产生了此类错误。那么,如何发送大于128的数据呢?答案是使用字节数组,将以上程序改为:DimMyData(255)AsByteFori=0To255

MyData(i)=iNextiMSComm1.Output=MyDataDo

DoEventsLoopUntilMSComm1.OutBufferCount=0'接收过程PrivateSubMSComm1_OnComm()

SelectCaseMSComm1.CommEventCasecomEvReceive

DimBufferAsVariant

MSComm1.InputMode=comInputModeBinary

MSComm1.InputLen=0

Buffer=MSComm1.Input

Fori=LBound(Buffer)ToUBound(Buffer)Text1.Text=Buffer(i);NextiCaseElseEndSelectEndSub3.3如何发送中文字符串VB5.0/6.0中可以直接把中文字符等同于英文字符发送,如:MSComm1.output="现在发送中文数据!",但这种方法发送的中文数据不能太长,发送缓冲区和接收缓冲区的大小需设定为中文字符的两倍以上,而且发送与接收系统所处的操作系统版本最好要一致,否则会出现接收或发送缓冲区溢出之类的错误。这种方法可用于一般要求不太高的场合。除了上述方法外,还可以采用间接方式发送中文字符串。在发送端将汉字或字符转换为机器内码或区位码数据数组,然后将转换后的数据发送到串口,在接收端接收到数据后,按照相反的顺序将得到的数据转换为相应的汉字或字符。在转换过程中,要用到位运算,如取得汉字的内码后需要将高字节和低字节分开,而VB5.0/6.0中并没有提供此类函数,以下是求整数高、低字节的函数。PublicFunctionHiByte(aAsInteger)

DimbAsInteger

b=aAnd&HFF00

b=b/256

Ifb<0Thenb=b+256

HiByte=bEndFunction

PublicFunctionLowByte(aAsInteger)

DimbAsInteger

b=aAnd&HFF

LowByte=bEndFunction3.4如何在通信过程中进行延时在某些通信过程中,常常需要在发送完一组数据后进行一段延时,以等待对方处理上组数据,以下是延时函数代码。PublicSubDelay(PauseTimeAsSingle)

DimStartStart=Timer

'设定开始时间DoWhileTimer<Sta

温馨提示

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

评论

0/150

提交评论