(3) ReadFile()函数:从串口输入缓冲区读取数据流。
(4) WriteFile()函数:向串口输出缓冲区发送数据。
(5) GetCommState()函数:获取串口的当前配置。
(6) SetCommState()函数:重新分配串口资源的各个参数。
由于Windows API函数大部分是用C或C++编写,所以在Visual Basic 6.0 中调用Windows API函数之前必须先在模块级代码上用Declare语句对所调用的函数和用到的数据结构进行声明,具体的函数声明及数据结构请参考朱友芹编《新编Windows API参考大全》。
3.3调用第三方函数库(如Pcomm函数库)
DLL(Dynamic Link Library)动态链接库是一种可以被VB语言调用的程序模块。DLL中包含的可执行代码不能单独执行,而应由Windows应用程序调用执行。一般数据采集卡的供应商都会提供该采集卡的DLL库函数,使用这些DLL库函数,可以做到程序代码共享,减少程序的编写工作量。用户不需要知道这些代码的实现细节,只需要了解调用函数的参数和函数处理后的返回值。
Pcomm函数库是由台湾Moxa公司为开发串口通信程序提供的一套函数库。通过对Windows API函数的进一步封装,提供50多个串口操作函数。覆盖了Windows操作系统下几乎所有异步通
(4) WriteFile()函数:向串口输出缓冲区发送数据。
(5) GetCommState()函数:获取串口的当前配置。
(6) SetCommState()函数:重新分配串口资源的各个参数。
由于Windows API函数大部分是用C或C++编写,所以在Visual Basic 6.0 中调用Windows API函数之前必须先在模块级代码上用Declare语句对所调用的函数和用到的数据结构进行声明,具体的函数声明及数据结构请参考朱友芹编《新编Windows API参考大全》。
3.3调用第三方函数库(如Pcomm函数库)
DLL(Dynamic Link Library)动态链接库是一种可以被VB语言调用的程序模块。DLL中包含的可执行代码不能单独执行,而应由Windows应用程序调用执行。一般数据采集卡的供应商都会提供该采集卡的DLL库函数,使用这些DLL库函数,可以做到程序代码共享,减少程序的编写工作量。用户不需要知道这些代码的实现细节,只需要了解调用函数的参数和函数处理后的返回值。
Pcomm函数库是由台湾Moxa公司为开发串口通信程序提供的一套函数库。通过对Windows API函数的进一步封装,提供50多个串口操作函数。覆盖了Windows操作系统下几乎所有异步通
信的问题,可以简洁的开发多线程通讯程序。采用该库,通信的可靠性与使用MSComm32控件比较有了明显提高, 而相对直接使用Win32API函数编程则降低了程序开发难度, 缩短了程序开发周期。
这种方式上述直接调用Windows API函数有相似之处,但也有明显的差异。API函数常采取的方法是在串口监视线程中设置串口通信事件掩码及重叠机制,允许程序在后台等待串口通信事件。通过WaitCommEvent检测特定的串行通信事件。而在Pcomm中,可以采用中断处理的方式,为各种事件指定相应的中断处理函数,如接收到一定数目的字符,接收到结束字符,接收到中止信号以及发送缓冲区为空等;同时还可以采用线程控制的方式,直接采用库中的sio_read()和sio_write()函数读写串口。
Pcomm..DLL中的函数按功能分为6项:端口设置、数据发送与接收、串口状态检测、事件服务、文件传输、杂项。Pcomm..DLL中主要的函数介绍如下。
sio_open:打开端口;sio_close: 关闭端口。
sio_ioctl:设置端口参数,如波特率等。
sio_read:从端口接收数据;sio_write向端口发送数据。
sio_iqueue:得到接收缓冲区中的数据长度。
这种方式上述直接调用Windows API函数有相似之处,但也有明显的差异。API函数常采取的方法是在串口监视线程中设置串口通信事件掩码及重叠机制,允许程序在后台等待串口通信事件。通过WaitCommEvent检测特定的串行通信事件。而在Pcomm中,可以采用中断处理的方式,为各种事件指定相应的中断处理函数,如接收到一定数目的字符,接收到结束字符,接收到中止信号以及发送缓冲区为空等;同时还可以采用线程控制的方式,直接采用库中的sio_read()和sio_write()函数读写串口。
Pcomm..DLL中的函数按功能分为6项:端口设置、数据发送与接收、串口状态检测、事件服务、文件传输、杂项。Pcomm..DLL中主要的函数介绍如下。
sio_open:打开端口;sio_close: 关闭端口。
sio_ioctl:设置端口参数,如波特率等。
sio_read:从端口接收数据;sio_write向端口发送数据。
sio_iqueue:得到接收缓冲区中的数据长度。
sio_oqueue:得到发送缓冲区中的数据长度。
Pcomm在串口通信中的功能十分强大,但基于篇幅的考虑,在此不便赘述,读者可参考相关书籍或Pcomm自带的帮助文档。
4串口通讯的错误及处理
由于外界干扰或电压波动等原因,串口通讯可能会出现错误,如接受缓冲区溢出,奇偶校验错误等。为了处理这些错误,在Mscomm控件中就提供了一个OnComm事件,它可以捕获通信时发生的串口事件和错误信息,自动转入事件处理程序。在OnComm事件中,CommEvent属性是OnComm事件的指示,下面简单介绍几个重要的CommEvent属性值。
ComEventBreak:表示收到一个中断信号;
ComEventFrame:表示硬件检测到一个数据帧错误;
ComEvenRxover:表示接收缓冲区溢出;
ComEventTxFull:表示输出缓冲区已满;
ComEvReceive:表示接手到了Rthreshold个字符;
ComEvEOF:表示接受到了EOF字符(ASCII字符26)。
编程时用SelectCase语句,根据不同的CommEvent属性值,去执行不同的处理程序。
Pcomm在串口通信中的功能十分强大,但基于篇幅的考虑,在此不便赘述,读者可参考相关书籍或Pcomm自带的帮助文档。
4串口通讯的错误及处理
由于外界干扰或电压波动等原因,串口通讯可能会出现错误,如接受缓冲区溢出,奇偶校验错误等。为了处理这些错误,在Mscomm控件中就提供了一个OnComm事件,它可以捕获通信时发生的串口事件和错误信息,自动转入事件处理程序。在OnComm事件中,CommEvent属性是OnComm事件的指示,下面简单介绍几个重要的CommEvent属性值。
ComEventBreak:表示收到一个中断信号;
ComEventFrame:表示硬件检测到一个数据帧错误;
ComEvenRxover:表示接收缓冲区溢出;
ComEventTxFull:表示输出缓冲区已满;
ComEvReceive:表示接手到了Rthreshold个字符;
ComEvEOF:表示接受到了EOF字符(ASCII字符26)。
编程时用SelectCase语句,根据不同的CommEvent属性值,去执行不同的处理程序。
除了以上所述的通讯错误外,在串口通信时,如果数据传输突然中断,对串口的读写操作可能会进入无限期的等待状态, 为避免这种情况发生, 必须设置串口读写操作的等待时间, 等待超时后,串口的读写操作将被主动放弃,这样即使数据传输突然中断程序也不会被挂起或阻塞。可以根据具体要求规定串口读写操作的最长时间值,即串口读写必须在这段时间内完成,否则提示串口操作失败。
5串口通讯实例
本实例是一个采集设备电流及功率的通讯程序,采集仪为横河WT230数字功率计,因为要采集的数据量不大,且工程结构简单,故采用Mscomm控件的形式进行串口读写操作。
具体实现步骤如下:
(1) 在窗体Form上添加两个重要的控件:Timer1和Mscomm1;
(2) 在程序的Form_Load事件过程中添加如下代码:
MSComm1.CommPort=1 ‘使用COM1端口
MSComm1.Setting=“9600,o,8,1” ‘设置通信口参数,注意是奇校验,具体的校验方式要视具体的仪器而定
MSComm1.InputMode=comInputModeBinary ‘设置接收模式为二进制形式,注意一般对于数
5串口通讯实例
本实例是一个采集设备电流及功率的通讯程序,采集仪为横河WT230数字功率计,因为要采集的数据量不大,且工程结构简单,故采用Mscomm控件的形式进行串口读写操作。
具体实现步骤如下:
(1) 在窗体Form上添加两个重要的控件:Timer1和Mscomm1;
(2) 在程序的Form_Load事件过程中添加如下代码:
MSComm1.CommPort=1 ‘使用COM1端口
MSComm1.Setting=“9600,o,8,1” ‘设置通信口参数,注意是奇校验,具体的校验方式要视具体的仪器而定
MSComm1.InputMode=comInputModeBinary ‘设置接收模式为二进制形式,注意一般对于数
据采集这类设备通信,都应该设置为二进制形式
MSComm1.PortOpen=True ‘参数设置好后打开端口
MSComm1.HandShaking=2-comRTS ‘设置为硬件流控制,可以有效避免数据丢失的情况发生
(3) 程序开始后在一定情况设置Timer1.Enabled属性值为True 激活Timer1_Time事件,可以在固定的时间间隔下执行Timer1_Timer过程中的代码程序,完成数据采集。在Timer1_Timer过程中添加如下代码:
MSComm1.Output = "COMMUNICATE:WAIT 1" + Chr(13) + Chr(10)
MSComm1.Output = "MEASURE:NORMAL:VALUE?" + Chr(13) + Chr(10)
上述语句是将读取指令发送到串口输出缓冲区(注意每个命令字符串后都要加上回车和换行符Chr(13) + Chr(10)),再由系统将其自动发送给通过RS232通信线与计算机端口连接的WT230数字功率计,功率计在接收到命令字符串后,经过自身的单片机处理,就自动地把它测到的电压、电流、功率数据以固定的格式和字符形式通过RS232通信线传回至计算机,计算机程序从输入缓冲区读取这些字符数据并利用VB字符处理函数(如Val,InStr)进行处理就得到了所要的数据,下面是具体的程序代码。
MSComm1.PortOpen=True ‘参数设置好后打开端口
MSComm1.HandShaking=2-comRTS ‘设置为硬件流控制,可以有效避免数据丢失的情况发生
(3) 程序开始后在一定情况设置Timer1.Enabled属性值为True 激活Timer1_Time事件,可以在固定的时间间隔下执行Timer1_Timer过程中的代码程序,完成数据采集。在Timer1_Timer过程中添加如下代码:
MSComm1.Output = "COMMUNICATE:WAIT 1" + Chr(13) + Chr(10)
MSComm1.Output = "MEASURE:NORMAL:VALUE?" + Chr(13) + Chr(10)
上述语句是将读取指令发送到串口输出缓冲区(注意每个命令字符串后都要加上回车和换行符Chr(13) + Chr(10)),再由系统将其自动发送给通过RS232通信线与计算机端口连接的WT230数字功率计,功率计在接收到命令字符串后,经过自身的单片机处理,就自动地把它测到的电压、电流、功率数据以固定的格式和字符形式通过RS232通信线传回至计算机,计算机程序从输入缓冲区读取这些字符数据并利用VB字符处理函数(如Val,InStr)进行处理就得到了所要的数据,下面是具体的程序代码。
Dim bytinput() as byte ‘注意要将bytinput定义为不定长数组
Dim strtem As String
Dim i as Integer
bytinput =MSComm1.Input ‘将输入缓冲区数据读入给字节型数组bytinput
For i = 0 To UBound(bytinput)
strtem = strtem + Chr(bytinput(i)) ‘字节数组中的ASCII码值转换成相应 Next 的字符
得到的strtem字符就形象的展示了电流、电压和功率值。对于WT230而言,它的数据结构是这样的,每个数据之间由逗号字符“,”隔开,每个数据以用科学计数法表示,且每个数据以字符“E”分为前半部分和后半部分,前半部分为具体的数据(整数形式),后半部分为此数据的指数,指数的底为10。
Dim strtem As String
Dim i as Integer
bytinput =MSComm1.Input ‘将输入缓冲区数据读入给字节型数组bytinput
For i = 0 To UBound(bytinput)
strtem = strtem + Chr(bytinput(i)) ‘字节数组中的ASCII码值转换成相应 Next 的字符
得到的strtem字符就形象的展示了电流、电压和功率值。对于WT230而言,它的数据结构是这样的,每个数据之间由逗号字符“,”隔开,每个数据以用科学计数法表示,且每个数据以字符“E”分为前半部分和后半部分,前半部分为具体的数据(整数形式),后半部分为此数据的指数,指数的底为10。
VB好象是我大二学的,具体时间我也忘了,反正就记得做课设的时候用它连个ACCESS实现了插入删除查询工作。以后知道这个周四我也没有用过,甚至没有见到过它的界面。我选择它一个因为我选择,我喜欢。更重要的是它安装了自带串口控件,不用下载什么的了,用起来实打实的心里有底。
大家现在知道我的底子了吧?周四我借公司里的一本VB书看了一天的串口,然后心理有底了,
大家现在知道我的底子了吧?周四我借公司里的一本VB书看了一天的串口,然后心理有底了,
周五动手一天,收获很大,今天早晨8点起床,心理还琢磨着程序的事情,由于家里没有实验仪器,于是打算去公司,一直做到现在,终于搞定拉。这个礼拜上网源代码的时候看着好多像我一样源码的人发帖子要源程序,但是大多只是网页写了一大堆代码。没有用!为什么呢?你怎么知道人家用什么控件,什么功能呢?还是老老实实的自己写吧。没什么的,很简单的啊。说实话,这个程序只要你把浮躁的心放下来写就可以了。我自从毕业一直没有做过WINDOWS编程,都是直接对单片机的,上学那会也是天天乐呼呼的,没学到什么东西,就这样我还不是搞定了吗?(当然这个建立在看网上那堆源程序的基础上)。
现在我就把这个程序发在网页上,这个程序已经调通了,写在这里的目的是让大家做个程序参考,你也不知道我界面上的控件,所以没有必要复制粘贴。(不是我小气,是因为这个工程涉及到公司机密,这个产品还没有送检,所以不给。
发布啊,望谅解)欢迎大家和我讨论,谢谢!
'Global Data Definitions
字符串转数组怎么处理Dim MyHandle As Long 'Handle to Connection
Dim MyStatus As Integer 'Status returned from mbMasterV7 Control
Dim Slave As Integer 'Slave, Cmd, Address, & Length
现在我就把这个程序发在网页上,这个程序已经调通了,写在这里的目的是让大家做个程序参考,你也不知道我界面上的控件,所以没有必要复制粘贴。(不是我小气,是因为这个工程涉及到公司机密,这个产品还没有送检,所以不给。
发布啊,望谅解)欢迎大家和我讨论,谢谢!
'Global Data Definitions
字符串转数组怎么处理Dim MyHandle As Long 'Handle to Connection
Dim MyStatus As Integer 'Status returned from mbMasterV7 Control
Dim Slave As Integer 'Slave, Cmd, Address, & Length
Dim Cmd As Integer
Dim Address As Long
Dim Length As Integer
Dim LoopbackMsg(20) As Byte
Dim Address As Long
Dim Length As Integer
Dim LoopbackMsg(20) As Byte
Public Sub show_status(ErrCode As Integer)
If (ErrCode = 0) Then
STATUS.Text = "正常通行ing"
ElseIf (ErrCode < 255) Then
' STATUS.Text = "Slave Device Exception Response"
STATUS.Text = "从设备没有响应"
ElseIf (ErrCode = 256) Then
STATUS.Text = "无效连接"
ElseIf (ErrCode = 257) Then
STATUS.Text = "消息超时"
STATUS.Text = "正常通行ing"
ElseIf (ErrCode < 255) Then
' STATUS.Text = "Slave Device Exception Response"
STATUS.Text = "从设备没有响应"
ElseIf (ErrCode = 256) Then
STATUS.Text = "无效连接"
ElseIf (ErrCode = 257) Then
STATUS.Text = "消息超时"
ElseIf (ErrCode = 258) Then
STATUS.Text = "无效地址"
ElseIf (ErrCode = 259) Then
STATUS.Text = "无效从设备地址"
ElseIf (ErrCode = 260) Then
STATUS.Text = "无效数据长度"
ElseIf (ErrCode = 261) Then
STATUS.Text = "不支持modbus命令格式"
ElseIf (ErrCode = 263) Then
STATUS.Text = "从设备超时"
ElseIf (ErrCode = 264) Then
STATUS.Text = "无效传输模式"
ElseIf (ErrCode = 265) Then
STATUS.Text = "CRC校验错误"
ElseIf (ErrCode = 266) Then
STATUS.Text = "无效地址"
ElseIf (ErrCode = 259) Then
STATUS.Text = "无效从设备地址"
ElseIf (ErrCode = 260) Then
STATUS.Text = "无效数据长度"
ElseIf (ErrCode = 261) Then
STATUS.Text = "不支持modbus命令格式"
ElseIf (ErrCode = 263) Then
STATUS.Text = "从设备超时"
ElseIf (ErrCode = 264) Then
STATUS.Text = "无效传输模式"
ElseIf (ErrCode = 265) Then
STATUS.Text = "CRC校验错误"
ElseIf (ErrCode = 266) Then
STATUS.Text = "没有建立连接"
ElseIf (ErrCode = 267) Then
STATUS.Text = "无效从设备响应"
ElseIf (ErrCode = 271) Then
STATUS.Text = "演示时间到"
ElseIf (ErrCode = 272) Then
STATUS.Text = "无效 modbus/TCP 命令"
End If
ElseIf (ErrCode = 267) Then
STATUS.Text = "无效从设备响应"
ElseIf (ErrCode = 271) Then
STATUS.Text = "演示时间到"
ElseIf (ErrCode = 272) Then
STATUS.Text = "无效 modbus/TCP 命令"
End If
End Sub
' Hide the contrtol when the form loads
Private Sub Form_Activate()
MbMasterV71.HideControl
End Sub
Private Sub Form_Activate()
MbMasterV71.HideControl
End Sub
' Handler for the CONNECT SERIAL Button
Private Sub ConnectSerial_Click()
' Connect to COMM Port
MbMasterV71.BaudRate = 9600 '9600 Baud
MbMasterV71.Parity = 0 '0=NOPARITY, 1=ODDPARITY, 2=EVENPARITY, 3=MARKPARITY, 4=SPACEPARITY
MbMasterV71.DataBits = 8 '8 DataBits
MbMasterV71.StopBits = 0 '0=ONESTOPBIT, 1=ONE5STOPBITS, 2=TWOSTOPBITS
MbMasterV71.TimeOut = 2000 '2000 msec
MbMasterV71.TransmissionMode = 1 '0=ASCII, 1=RTU
Private Sub ConnectSerial_Click()
' Connect to COMM Port
MbMasterV71.BaudRate = 9600 '9600 Baud
MbMasterV71.Parity = 0 '0=NOPARITY, 1=ODDPARITY, 2=EVENPARITY, 3=MARKPARITY, 4=SPACEPARITY
MbMasterV71.DataBits = 8 '8 DataBits
MbMasterV71.StopBits = 0 '0=ONESTOPBIT, 1=ONE5STOPBITS, 2=TWOSTOPBITS
MbMasterV71.TimeOut = 2000 '2000 msec
MbMasterV71.TransmissionMode = 1 '0=ASCII, 1=RTU
MyHandle = MbMasterV71.ConnectSerial(1) ' Connect to COMM Port 1
If MyHandle > 0 Then
' Connection was successful
' (This example only allows a single connection)
' Disable All Connection Buttons
If MyHandle > 0 Then
' Connection was successful
' (This example only allows a single connection)
' Disable All Connection Buttons
' Enable the Read, Write & Disconnect Buttons
ConnectSerial.Enabled = False
ConnectTAPI.Enabled = False
ConnectTCP.Enabled = False
Disconnect.Enabled = True
' LoopBackTst.Enabled = True
STATUS.Text = "正在连接ing"
READMODBUS.Enabled = True
WRITEMODBUS.Enabled = True
Else
'Connection Attempt Failed
'(Another application must have control of the COM Port)
STATUS.Text = "串口忙,请稍候"
End If
End Sub
ConnectSerial.Enabled = False
ConnectTAPI.Enabled = False
ConnectTCP.Enabled = False
Disconnect.Enabled = True
' LoopBackTst.Enabled = True
STATUS.Text = "正在连接ing"
READMODBUS.Enabled = True
WRITEMODBUS.Enabled = True
Else
'Connection Attempt Failed
'(Another application must have control of the COM Port)
STATUS.Text = "串口忙,请稍候"
End If
End Sub
' Handler for the CONNECT TAPI Button
Private Sub ConnectTAPI_Click()
Dim nTAPIDevices As Long
Dim TAPIDevice As String
Private Sub ConnectTAPI_Click()
Dim nTAPIDevices As Long
Dim TAPIDevice As String
'Go through the motions of getting the TAPI Device List
nTAPIDevices = MbMasterV71.NumberOfTAPIDevices()
TAPIDevice = MbMasterV71.GetTAPIDeviceName(0)
'Setup the phone number to dial
MbMasterV71.PhoneNumber = "645-5966"
'Dial the call
MyHandle = MbMasterV71.DialTAPIDevice(0)
If MyHandle > 0 Then
'Call should be in progress now
'Don't enable the Read & Write Buttons
'until we get the CallEstablished Event
nTAPIDevices = MbMasterV71.NumberOfTAPIDevices()
TAPIDevice = MbMasterV71.GetTAPIDeviceName(0)
'Setup the phone number to dial
MbMasterV71.PhoneNumber = "645-5966"
'Dial the call
MyHandle = MbMasterV71.DialTAPIDevice(0)
If MyHandle > 0 Then
'Call should be in progress now
'Don't enable the Read & Write Buttons
'until we get the CallEstablished Event
STATUS.Text = "正在连接ing"
ConnectSerial.Enabled = False
ConnectTAPI.Enabled = False
ConnectTCP.Enabled = False
Disconnect.Enabled = False
'LoopBackTst.Enabled = False
READMODBUS.Enabled = False
WRITEMODBUS.Enabled = False
Else
STATUS.Text = "没有连接"
End If
ConnectSerial.Enabled = False
ConnectTAPI.Enabled = False
ConnectTCP.Enabled = False
Disconnect.Enabled = False
'LoopBackTst.Enabled = False
READMODBUS.Enabled = False
WRITEMODBUS.Enabled = False
Else
STATUS.Text = "没有连接"
End If
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论