手把手教你用VB实现Modbus RTU串行通讯工程实例

合集下载

VB控件MSComm串口通讯实例教程

VB控件MSComm串口通讯实例教程

现有电子秤一台,使用串口与计算机进行通讯。

编写VB程序来访问串口,达到读取电子秤上显示的数据。

该电子秤为BE01型仪表,输出为RS-232C标准接口,波特率为300-9600、偶校验、7个数据位、2个停止位。

所有字符现有电子秤一台,使用串口与计算机进行通讯。

编写VB程序来访问串口,达到读取电子秤上显示的数据。

该电子秤为BE01型仪表,输出为RS-232C 标准接口,波特率为300-9600、偶校验、7个数据位、2个停止位。

所有字符均发送11位ASCII码,一个起始位。

在VB中与串口通讯需要引入控件MSComm串口通讯控件(在Microsoft Comm Control 6.0中)。

具体程序如下:控件简称:MSCDim Out(12) As Byte '接收var中的值Dim var As Variant '接收MSC.input中的数值Dim nRece As Integer '计算MSC.inputbuffer的个数Dim i As Integer, j As Integer '随即变量,计算循环************************************************************************** **Private Sub Form_Load()ClearTextWith MSC.CommPort = 1 '设置Com1为通信端口.Settings = "9600,E,7,2" '设置通信端口参数 9600赫兹、偶校验、7个数据位、2个停止位.(这里需要进一步说明的是:.Setting=”BBBB,P,D,S”。

含义是:B:Baud Rate(波特率);P:Parity(奇偶);D:Data Bit;S:Stop Bit).InBufferSize = 40 '设置缓冲区接收数据为40字节.InputLen = 1 '设置Input一次从接收缓冲读取字节数为1.RThreshold = 1 '设置接收一个字节就产生OnComm事件End WithEnd Sub************************************************************************** **Private Sub ClearText()Text3.Text = ""Text2.Text = "5"Text1.Text = ""End SubPrivate Sub Command1_Click()ClearText' nRece = 0 '计数器清零With MSC.InputMode = comInputModeBinary '设置数据接收模式为二进制形式.InBufferCount = 0 '清除接收缓冲区If Not .PortOpen Then.PortOpen = True '打开通信端口End IfEnd WithEnd SubPrivate Sub MSC_OnComm()DelayTime ‘用来延续时间ClearTextWith MSCSelect Case .CommEvent '判断通信事件Case comEvReceive: '收到Rthreshold个字节产生的接收事件SwichVar 1If Out(1) = 2 Then '判断是否为数据的开始标志.RThreshold = 0 '关闭OnComm事件接收End IfDoDoEventsLoop Until .InBufferCount >= 3 '循环等待接收缓冲区>=3个字节' nRece = nRece + 1For i = 2 To 12SwichVar iText1.Text = Text1.Text & Chr(Out(i))NextText1.Text = LTrim(Text1.Text)Text2.Text = Text2.Text & CStr(nRece).RThreshold = 1 '打开MSComm事件接收Case Else' .PortOpen = FalseEnd SelectEnd WithEnd Sub************************************************************************** **Private Sub DelayTime()Dim bDT As BooleanDim sPrevious As Single, sLast As SinglebDT = TruesPrevious = Timer (Timer可以计算从子夜到现在所经过的秒数,在Microsoft Windows中,Timer函数可以返回一秒的小数部分)Do While bDTIf Timer - sPrevious >= 0.3 Then bDT = FalseLoopbDT = True(通信传输速率为9600bps,则最快速度1.04ms发送一个字节,仪表每秒发送50帧数据,每帧数据有4个字节,即每秒发送200个字节,平均5.0ms 发送一个字节,连续读取串口数据时要在程序中添加循环等待程序)Private Sub SwichVar(ByVal nNum As Integer)DelayTimevar = Nullvar = MSC.InputOut(nNum) = var(0)End Sub(设置接收数据模式采用二进制形式,即 InputMode=comInputModeBinary,但用Input 属性读取数据时,不能直接赋值给 Byte 类型变量,只能通过先赋值给一个 Variant 类型变量,返回一个二进制数据的数组,再转换保存到Byte类型数变量中。

VB下基于Modbus规约的串口通信

VB下基于Modbus规约的串口通信

)
工控机通信软件 本文的工控机通信软件主要是利用 !’613G "串口进行编程使用 &6(*// 通信控件来实现的, &6(*// 控件可加快开发进度。该控件主要是为 8+7FHF 的通 用串口而设计。 所以为了利用工控机上现有的 8+7FHF 接口, 通 常是使用 8+FHF I ;<= 的转换器。通过转换器, 我们就可以像开 发通用的 8+7FHF 串口一样来快速开发基于 8+7;<= 接口的工 控机通信软件。 工 控 机 通 过 8+FHF 接 口 , 经 8+FHF I 8+;<= 转 换 模 块 与 数 字显示表相连接,数字显示表被赋予唯一的通讯地址码用以识 别身份,这样上位工控机即能通过 8+7;<= 总线实现对进锥系 统锥位位置的采集与监控。 (? ) 工控机通信软件界面 (F ) &+.*// 控件初始化程序设计 根据数字显示表的串行通信 协 议 规 定 , 在 &+.*// 控 件 初始化程序中, 主要是进行一些必须的串口初始化设定。 具体的 操作如下面代码说明:
间的询问应答环路交换信息。 图 ! 是 T5O.-8 协议的询问应答环路。
图!
T5O.-8 协议的询问应答环路
利 <T,K=R2= 数 字 显 示 表 采 用 T5O.-8 )IZ 通 讯 规 约 , 用通讯命令, 可以进行读取点 ( “保 持 寄 存 器 ” ) 或返回值 ( “输 入 寄存器” ) 的操作。 当通讯命令发送至仪表时, 符合相应地址码的 设备接通讯命令, 并除去地址码, 读取信息, 如果没有出错, 则执 行相应的任务; 然后把执行结果返送给发送者。 保持和输入寄存 器都是 $# 位 (! 字节) 值, 并且高位在前、 低位在后。这样用于仪 表的读取点和返回值都是 ! 字节。由于一些可编程控制器不用 所以功能码 "[ 被用作读取点和返回值。从机 (数字 功能码 "[, 显示表) 响应的命令格式是从机地址、 功能码、 数 据 区 及 ()( 码。如果出错就不发送任何信息。 数字显示表应答命令中的地址码、功能码必须与工控机机 查询命令相同; 命令中的模拟量数据按高位字节在前、 低位字节 在后的顺序放置, 而 ()( 码与此相反, 是低位字节在前、 高位字 节在后。 以工控机通信软件界面的显示为例,介绍数字显示表数值 读取的命令格式和内容。 工控机和数字显示表之间采用查询与应答方式进行通信, 每一种查询命令都对应着一种应答。工控机发出的查询命令格 式如表 $ 所示。

基于MODBUS协议的串行通讯例程(VB)

基于MODBUS协议的串行通讯例程(VB)

基于MODBUS协议的串行通讯例程(VB)'可通过MODBUS协议获取:主电压、电流、运行状态、DIP开关设置、硬接线状态、统计数据等;'并可通过MODBUS协议控制:启动、急停、软停、双重参数调节、慢速正/反转、节能等;'本例程为通过通讯获取软启动器当前运行状态'编制:董斌 dbboss@Private Const Read_Coil_Status = &H1Private Const Read_Input_Status = &H2Private Const Read_Holding_Registers = &H3Private Const Read_Input_Registers = &H4Private Const Force_Single_Coil = &H5Private Const Single_Registers = &H6Private Const Diagnostics = &H8Private Const Force_Multiple_Coil = &HFPrivate Const Force_Multiple_Register = &H10Public Function CRC16(data() As Byte) As tCRCDim CRC16Hi As ByteDim CRC16Lo As ByteDim Result As tCRCCRC16Hi = &HFFCRC16Lo = &HFFDim i As IntegerDim iIndex As LongFor i = 0 To UBound(data)iIndex = CRC16Lo Xor data(i)CRC16Lo = CRC16Hi Xor GetCRCLo(iIndex) '低位处理CRC16Hi = GetCRCHi(iIndex) '高位处理Next iWith Result.bytLow = CRC16Lo 'CRC低位.bytHigh = CRC16Hi 'CRC高位End WithCRC16 = ResultEnd Function'CRC低位字节值表Private Function GetCRCLo(Ind As Long) As ByteGetCRCLo = Choose(Ind + 1, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81 , &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80 , &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &H C1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &H C0, &H80, &H41, &H0, &HC1, &H81, &H40)End Function'CRC高位字节值表Private Function GetCRCHi(Ind As Long) As ByteGetCRCHi = Choose(Ind + 1, &H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7, &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD, &HC D, &HF, &HCF, &HCE, &HE, &HA, &HCA, &HCB, &HB, &HC9, &H9, &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, &H1E, &HDE, &HDF, &H1 F, &HDD, &H1D, &H1C, &HDC, &H14, &HD4, &HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, &H11, &HD1, &HD0, &H10, &HF0, &H30, &H3 1, &HF1, &H33, &HF3, &HF2, &H32, &H36, &HF6, &HF7, &H37, &HF5, &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3 A, &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, &HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF, &H2D, &HED, &HEC, &H2C, &HE 4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, &H22, &HE2, &HE3, &H23, &HE1, &H21, &H20, &HE0, &HA0, &H60, _&H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, &HA5, &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, &H6E, &HAE, &H AA, &H6A, &H6B, &HAB, &H69, &HA9, &HA8, &H68, &H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, &HBD, &HBC, &H 7C, &HB4, &H74, &H75, &HB5, &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, &H70, &HB0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H55, &H95, &H94, &H54, &H9C, &H5C, &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, &H99, &H 59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8B, &H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, &H4D, &H4C, &H8C, &H44, &H84, &H85, &H45, &H 87, &H47, &H46, &H86, &H82, &H42, &H43, &H83, &H41, &H81, &H80, &H40) End FunctionPublic Function Get_Logic_Status(objRS485_Comm As MSComm, nSerialLink As Byte, _tTimeOut As Double) As tLogic_Status'取软启动器逻辑状态Dim CRC As tCRC, blnTimeOut As BooleanDim outByte() As Byte, T As Double, inByte() As Long, i As Long, r As IntegerDim inChr As String, wStatus As Long, Result As tLogic_StatusReDim outByte(0 To 5) As ByteoutByte(0) = nSerialLink '从设备号outByte(1) = Read_Input_Registers '功能调用号outByte(2) = &H0 '数据所在开始地址(高字节)outByte(3) = &H0 '数据所在开始地址(低字节)outByte(4) = &H0 '读取数据个数(高字节)outByte(5) = &H1 '读取数据个数(低字节)CRC = CRC16(outByte()) '计算CRCReDim Preserve outByte(0 To 7) As ByteWith CRCoutByte(6) = .bytLowoutByte(7) = .bytHighEnd WithobjRS485_Comm.InBufferCount = 0 '清通讯口输入缓存区objRS485_Comm.Output = outByte '输出DoDoEventsLoop Until objRS485_Comm.OutBufferCount = 0 '输出直至完毕T = TimerDoIf Timer - T > tTimeOut Then '超时?blnTimeOut = TrueEnd IfLoop Until (objRS485_Comm.InBufferCount >= 7) Or blnTimeOut '超时或接收数据长度〉7时结束接收If objRS485_Comm.InBufferCount > 0 Then '处理接收数据objRS485_Comm.InputLen = 1i = 0DoinChr = objRS485_Comm.InputReDim Preserve inByte(0 To i) As LonginByte(i) = AscB(inChr)i = i + 1Loop Until objRS485_Comm.InBufferCount = 0wStatus = CLng(inByte(3) * 256) + inByte(4)With Result.blnInsulation = wStatus And &H40& '绝缘报警.blnMotorRunningSlowSpeedReverse = wStatus And &H80& '慢速反转.blnMotorRunningSlowSpeedForward = wStatus And &H100& '慢速正转.blnMotorRunningEnergySaveON = wStatus And &H200& '节能.blnDualAdjON = wStatus And &H400& '双重参数调节.blnMotorRunning = wStatus And &H800& '电机运行.blnMotorStartProcess = wStatus And &H1000& '电机起动过程中.blnMotorSoftStopProcess = wStatus And &H2000& ’电机软停过程中.blnMotorStopped = wStatus And &H4000& ‘电机停止.blnTripped = wStatus And &H8000& ‘跳闸End WithGet_Logic_Status = ResultEnd IfobjRS485_Comm.InBufferCount = 0End Function‘本程序在Windows9x/2k/xp vb6.0 下调试通过。

VB编写的Modbus RTU协议通讯源程序

VB编写的Modbus RTU协议通讯源程序

VB编写的Modbus RTU协议通讯源程序modbus rtu协议可以算是一种事实上的工业标准协议,为许多仪表、PLC等所支持。

以前有几个用户问如何使用VB编程来与我们的KND-K3系列PLC通讯,于是整了一个demo程序。

这次把这个demo共享,希望能给大家一点帮助。

1)模块文件:modCRC,其中包含了CRC校验的函数。

'data 待校验的数组名称'no 数组中元素个数'btLoCRC 算出的CRC高字节'btHiCRC 算出的CRC低字节Public Function CalCRC16Fast(data() As Byte, no As Integer, btLoCRC As Byte, btHiCRC As Byte) As StringDim CL As Byte, CH As Byte '多项式码&HA001Dim SaveHi As Byte, SaveLo As ByteDim i As IntegerDim Flag As IntegerbtHiCRC = &HFFbtLoCRC = &HFFCL = &H1CH = &HA0For i = 0 To (no - 1)btHiCRC = btHiCRC Xor data(i) '每一个数据与CRC寄存器进行异或For Flag = 0 To 7SaveHi = btLoCRCSaveLo = btHiCRCbtLoCRC = btLoCRC \ 2 '高位右移一位btHiCRC = btHiCRC \ 2 '低位右移一位If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1btHiCRC = btHiCRC Or &H80 '则低位字节右移后前面补1End If '否则自动补0If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或btLoCRC = btLoCRC Xor CHbtHiCRC = btHiCRC Xor CLEnd IfNext FlagNext iDim ReturnData(1) As ByteReturnData(0) = btHiCRC 'CRC高位ReturnData(1) = btLoCRC 'CRC低位CalCRC16Fast = ReturnDataEnd FunctionPublic Function CalCRC16Tbl(data() As Byte, no As Integer, btLoCRC As Byte, btHiCRC As Byte) As StringDim btLoCRC As ByteDim btHiCRC As BytebtLoCRC = &HFFbtHiCRC = &HFFDim i As IntegerDim iIndex As LongFor i = 0 To (no - 1)iIndex = btHiCRC Xor data(i)btHiCRC = btLoCRC Xor GetCRCLo(iIndex) '低位处理btLoCRC = GetCRCHi(iIndex) '高位处理Next iDim ReturnData(1) As ByteReturnData(0) = btHiCRC 'CRC高位ReturnData(1) = btLoCRC 'CRC低位CalCRC16Tbl = ReturnDataEnd Function'CRC低位字节值表Function GetCRCLo(Ind As Long) As ByteGetCRCLo = Choose(Ind + 1, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, _&H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, _&H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, _&H80, &H41, &H0, &HC1, &H81, &H40, &H0, &HC1, &H81, &H40, _&H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, _&H81, &H40, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40, &H1, &HC0, &H80, &H41, &H1, &HC0, &H80, &H41, &H0, &HC1, &H81, &H40)End Function'CRC高位字节值表Function GetCRCHi(Ind As Long) As ByteGetCRCHi = Choose(Ind + 1, _&H0, &HC0, &HC1, &H1, &HC3, &H3, &H2, &HC2, &HC6, &H6, &H7, &HC7, &H5, &HC5, &HC4, &H4, &HCC, &HC, &HD, &HCD, &HF, &HCF, &HCE, &HE, &HA, &HCA, &HCB, &HB, &HC9, &H9, &H8, &HC8, &HD8, &H18, &H19, &HD9, &H1B, &HDB, &HDA, &H1A, &H1E, &HDE, &HDF, &H1F, &HDD, &H1D, &H1C, &HDC, &H14, &HD4, &HD5, &H15, &HD7, &H17, &H16, &HD6, &HD2, &H12, &H13, &HD3, &H11, &HD1, &HD0, &H10, &HF0, &H30, &H31, &HF1, &H33, &HF3, &HF2, &H32, &H36, &HF6, &HF7, &H37, &HF5, &H35, &H34, &HF4, &H3C, &HFC, &HFD, &H3D, &HFF, &H3F, &H3E, &HFE, &HFA, &H3A, &H3B, &HFB, &H39, &HF9, &HF8, &H38, &H28, &HE8, &HE9, &H29, &HEB, &H2B, &H2A, &HEA, &HEE, &H2E, &H2F, &HEF, &H2D, &HED, &HEC, &H2C, &HE4, &H24, &H25, &HE5, &H27, &HE7, &HE6, &H26, &H22, &HE2, &HE3, &H23, &HE1, &H21, &H20, &HE0, &HA0, &H60, _ &H61, &HA1, &H63, &HA3, &HA2, &H62, &H66, &HA6, &HA7, &H67, &HA5, &H65, &H64, &HA4, &H6C, &HAC, &HAD, &H6D, &HAF, &H6F, &H6E, &HAE, &HAA, &H6A, &H6B, &HAB, &H69, &HA9, &HA8, &H68, &H78, &HB8, &HB9, &H79, &HBB, &H7B, &H7A, &HBA, &HBE, &H7E, &H7F, &HBF, &H7D, &HBD, &HBC, &H7C, &HB4, &H74, &H75, &HB5, &H77, &HB7, &HB6, &H76, &H72, &HB2, &HB3, &H73, &HB1, &H71, &H70, &HB0, &H50, &H90, &H91, &H51, &H93, &H53, &H52, &H92, &H96, &H56, &H57, &H97, &H55, &H95, &H94, &H54, &H9C, &H5C, &H5D, &H9D, &H5F, &H9F, &H9E, &H5E, &H5A, &H9A, &H9B, &H5B, &H99, &H59, &H58, &H98, &H88, &H48, &H49, &H89, &H4B, &H8B, &H8A, &H4A, &H4E, &H8E, &H8F, &H4F, &H8D, &H4D, &H4C, &H8C, &H44, &H84, &H85, &H45, &H87, &H47, &H46, &H86, &H82, &H42, &H43, &H83, &H41, &H81, &H80, &H40)End Function2)窗体:FORM1,上面放置的控件如下:Begin VB.Form frmComCaption = "Form1"ClientHeight = 8235ClientLeft = 3885ClientTop = 2250ClientWidth = 6810LinkTopic = "Form1"ScaleHeight = 8235ScaleWidth = 6810Begin VB.TextBox txtReceive ‘注:放置接收上来的IB0数据Height = 495Left = 1200TabIndex = 2Top = 2280Width = 1335EndBegin mandButton Command1Caption = "读取IB0"Height = 495Left = 2760TabIndex = 1Top = 2280Width = 1695EndBegin mandButton cmdSDOCaption = "置位Q1.1"Height = 495Left = 2160TabIndex = 0Top = 3720Width = 1575EndBegin MSCommLib.MSComm ComK3Left = 480Top = 1080_ExtentX = 1005_ExtentY = 1005_V ersion = 393216DTREnable = -1 'TrueEnd①Form_Load事件,在此主要是实现了打开并初始化串口Private Sub Form_Load()With ComK3.CommPort = 1.Settings = "19200,N,8,1".InputMode = comInputModeBinary '二进制收发.InBufferSize = 512.OutBufferSize = 512If (Not .PortOpen) Then .PortOpen = True End WithEnd Sub②Form_UnLoad事件,在此主要是关闭串口Private Sub Form_Unload(Cancel As Integer)If (ComK3.PortOpen) ThenComK3.PortOpen = FalseEnd IfEnd Sub③“置位Q1.1”按钮单击事件'设置Q1.1为1Private Sub cmdSDO_Click()Dim btSend(8) As BytebtSend(0) = &H1 '目标站号btSend(1) = &H5 '功能码btSend(2) = &H0 'Q1.1地址(0009)高字节btSend(3) = &H9 'Q1.1地址(0009)低字节btSend(4) = &HFF '强制值高字节btSend(5) = &H0 '强制值低字节Dim crcDim btCRCHi As Byte, btCRCLo As Bytecrc = CalCRC16Fast(btSend, 6, btCRCLo, btCRCHi)btSend(6) = btCRCHibtSend(7) = btCRCLoComK3.Output = CV ar(btSend)End Sub④“读取IB0”按钮单击事件'查表知I0.0的modbus地址为0000,从I0.0开始读取连续8位Private Sub Command1_Click()'发请求Dim btSend(8) As BytebtSend(0) = &H1 '目标站号btSend(1) = &H2 '功能码btSend(2) = &H0 'I0.0地址(0000)高字节btSend(3) = &H0 'i0.0地址(0000)低字节btSend(4) = &H0 '读取个数高字节btSend(5) = &H8 '读取个数低字节Dim crcDim btCRCHi As Byte, btCRCLo As Bytecrc = CalCRC16Fast(btSend, 6, btCRCLo, btCRCHi)btSend(6) = btCRCHibtSend(7) = btCRCLoComK3.Output = CV ar(btSend)'注意下面编写的接收过程很简单,要编写实际应用的监控程序来说需要更完善Dim btReceive As V ariantWith ComK3DoDoEventsLoop Until .InBufferCount = 6.InputLen = 6btReceive = .InputIf btReceive(1) = &H2 Then '若正确,返回帧的第2个字节为功能码.实际上,此处应首先进行CRC校验txtReceive.Text = Hex$(btReceive(3))End IfEnd WithEnd Sub。

VB中串口通讯的实现

VB中串口通讯的实现

VB中串口通讯的实现在VB中实现串口通讯需要借助于SerialPort类,该类提供了一系列方法和属性用于串口的配置和通讯操作。

接下来,定义一个SerialPort对象和一个字节数组,用于接收和发送数据。

在窗体加载事件中初始化SerialPort对象,并设置串口的一些属性,如波特率、数据位、校验位等,根据实际需求进行配置。

还可以设置数据接收和发送的事件处理函数。

例如,下面的代码演示了如何配置串口:```vbImports System.IO.PortsPublic Class Form1Dim serialPort As New SerialPortDim receiveBuffer(255) As BytePrivate Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load'配置串口属性serialPort.PortName = "COM1"serialPort.BaudRate = 9600serialPort.DataBits = 8serialPort.Parity = Parity.NoneserialPort.StopBits = StopBits.One'数据接收事件处理函数AddHandler serialPort.DataReceived, AddressOfSerialPort_DataReceived'打开串口serialPort.OpenEnd SubPrivate Sub SerialPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs)'接收数据Dim bytesToRead As Integer = serialPort.BytesToReadDim bytesRead As Integer = serialPort.Read(receiveBuffer, 0, bytesToRead)'处理接收到的数据If bytesRead > 0 ThenDim receivedData As String =Encoding.ASCII.GetString(receiveBuffer, 0, bytesRead) '显示接收到的数据UpdateReceivedData(receivedData)End IfEnd SubPrivate Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click'发送数据Dim sendData As String = txtSendData.TextDim sendBuffer As Byte( = Encoding.ASCII.GetBytes(sendData) serialPort.Write(sendBuffer, 0, sendBuffer.Length)'清空发送框txtSendData.Text = ""End SubPrivate Sub UpdateReceivedData(data As String)'更新接收数据的显示If Me.InvokeRequired Then ' 跨线程调用控件Me.Invoke(Sub( UpdateReceivedData(data))ElselblReceivedData.Text = dataEnd IfEnd SubEnd Class```在上述代码中,我们主要关注Form1_Load事件处理函数和btnSend_Click事件处理函数。

VB串口通信(附图教程)

VB串口通信(附图教程)

界面如下:代码如下:Private Sub Form_Load()If MSComm1.PortOpen = True Then MSComm1.PortOpen = False ElseEnd IfCombo1.AddItem "COM1"Combo1.AddItem "COM2"Combo1.AddItem "COM3"Combo1.AddItem "COM4"Combo1.AddItem "COM5"Combo1.AddItem "COM6"Combo1.AddItem "COM7"Combo1.AddItem "COM8"Combo1.AddItem "COM9"Combo1.AddItem "COM10" Combo1.AddItem "COM11" Combo1.AddItem "COM12"Combo1.AddItem "COM13"Combo1.AddItem "COM14"Combo1.AddItem "COM15"Combo1.AddItem "COM16"Combo1.ListIndex = 2Combo2.AddItem "256000"Combo2.AddItem "128000"Combo2.AddItem "115200"Combo2.AddItem "57600"Combo2.AddItem "38400"Combo2.AddItem "28800"Combo2.AddItem "19200"Combo2.AddItem "14400"Combo2.AddItem "12800"Combo2.AddItem "11520"Combo2.AddItem "9600"Combo2.AddItem "4800"Combo2.AddItem "2400"Combo2.AddItem "1200"Combo2.AddItem "600"Combo3.AddItem "无None"Combo3.AddItem "奇Odd"Combo3.AddItem "偶Even"Combo4.AddItem "4"Combo4.AddItem "5"Combo4.AddItem "6"Combo4.AddItem "7"Combo4.AddItem "8"Combo5.AddItem "1"Combo5.AddItem "2"mPort = Combo1.ListIndex + 1 MSComm1.Settings = "9600,n,8,1"ComOpen.Caption = "打开串口"Shape1.FillColor = &HFFFFC0End SubPrivate Sub ComOpen_Click()On Error GoTo uerror '发现错误跳转到错误处理If ComOpen.Caption = "关闭串口" ThenMSComm1.PortOpen = FalseComOpen.Caption = "打开串口" '按钮文字改变Shape1.FillColor = &HFFFFC0 '灯颜色改变ElseMSComm1.PortOpen = TrueComOpen.Caption = "关闭串口"Shape1.FillColor = &HFFEnd IfExit Subuerror:msg$ = "无效端口号" '错误显示Title$ = "串口调试助手"X = MsgBox(msg$, 48, Title$) '48标示显示警告图标End SubPrivate Sub MSComm1_OnComm()Dim BytReceived() As ByteDim strBuff As StringDim i As IntegerSelect Case mEvent '事件发生Case 2ClsMSComm1.InputLen = 0 '读入缓冲区全部内容strBuff = MSComm1.Input '读入到缓冲区Label10.Caption = Label10.Caption + Len(strBuff) '接收计数If MSComm1.InputMode = comInputModeBinary ThenBytReceived() = strBuff '如果是二进制接收模式则进行数据处理,否则直接显示字符串For i = 0 To UBound(BytReceived)If Len(Hex(BytReceived(i))) = 1 ThenstrData = strData & "0" & Hex(BytReceived(i)) & " " '如果只有一个字符,则前补0,如F显示0F,最后补空格Else '方便显示观察如:00 0F FEstrData = strData & Hex(BytReceived(i)) & " "End IfNextTextReceive = TextReceive & strDatastrData = ""ElseTextReceive = TextReceive & strBuffEnd IfEnd SelectEnd SubPrivate Sub ComSend1_Click() '手动发送Dim Temp(0) As ByteDim strBuff As StringIf Option1.Value = True Then '如果显示16进制发送则进行16进制处理,这里只发送一个Temp(0) = "&H" & TextSendMSComm1.Output = Temp '发送一个16进制ElsestrBuff = TextSendEnd IfIf MSComm1.PortOpen = False ThenMsgBox "请打开串口"End IfOn Error GoTo uerrorMSComm1.Output = strBuffLabel11.Caption = Label11.Caption + Len(strBuff) '发送计数uerror:End SubPrivate Sub ComSend2_Click()If ComSend2.Caption = "自动发送" ThenComSend2.Caption = "关闭自动发送"Timer1.Interval = TextTime.TextTimer1.Enabled = TrueElseComSend2.Caption = "自动发送"Timer1.Enabled = FalseEnd IfEnd SubPrivate Sub ComClean1_Click()TextSend.Text = "" '清空发送窗口End SubPrivate Sub Option3_Click()MSComm1.InputMode = comInputModeBinary '选择接收方式End SubPrivate Sub Option4_Click()MSComm1.InputMode = comInputModeText '选择接收方式End SubPrivate Sub Timer1_Timer()Call ComSend1_Click '定时调用手动发送End SubPrivate Sub Timer2_Timer()If Combo3 = "无None" ThenMSComm1.Settings = Str(Combo2) + "N" + Str(Combo4) + Str(Combo5) ElseIf Combo3 = "奇Odd" ThenMSComm1.Settings = Str(Combo2) + "O" + Str(Combo4) + Str(Combo5) ElseIf Combo3 = "偶Even" ThenMSComm1.Settings = Str(Combo2) + "E" + Str(Combo4) + Str(Combo5) End IfEnd SubPrivate Sub Combo1_Click()If MSComm1.PortOpen = True Then '如果串口打开先关闭后再进行其他操作MSComm1.PortOpen = FalseEnd IfmPort = Combo1.ListIndex + 1 '读取com口号End SubPrivate Sub ComClean3_Click()Label10.Caption = 0Label11.Caption = 0End SubPrivate Sub ComClean2_Click()TextReceive.Text = "" '接收窗口End Sub功能上:实现了字符串的发送和接收,8位数据的十六进制发送和接收,有端口,波特率等设置。

VB串口通信程序实例

VB串口通信程序实例

VB 串口通信程序设计典型实例利用 VB 开发串口通信程序既可以使用 MSComm 控件也可以调用 Windows API 函数实 现。

不过,只要 MSComm 控件可以被选用,我们推荐选择此控件实现,因为 MSComm 控 件的功能和 API 调用一样强,甚至比它还好且使用起来更加简单。

在本章提供的串口通信程序设计中,除了 PC 与 PC 串口通信外,PC 与单片机、PC 与 智能仪表、PC 与 PLC、PC 与 GSM 短信模块等串口通信任务的实现均采用 MSComm 控件。

6.1 PC 与 PC 串口通信程序设计当两台串口设备通信距离较近时,可以直接连接,最简单的情况,在通信中只需 3 根线 (发送线、接收线、信号地线)便可实现全双工异步串行通信。

本设计通过两台 PC 串口 3 线连接,介绍了利用 API 函数和 MSComm 控件设计串口通 信程序的方法,包括字符与文件的发送与接收。

6.1.1 PC 与 PC 串口通信程序设计目的(1)掌握 PC 与 PC 串口通信的线路连接方法。

(2)利用 MSComm 控件和 API 函数实现 PC 与 PC 串口通信的程序设计方法。

6.1.2 PC 与 PC 串口通信程序设计用软、硬件本设计用到的硬件和软件清单如表 6-1 所示。

表 6-1 序 1 2 3 号 PC 或 IPC 串口通信线(三线制) Visual Basic 6.0 设计用软、硬件 名 称 数 2 1 1 量6.1.3 PC 与 PC 串口通信程序硬件线路图线路说明,在计算机通电前,按图 6-1 所示将两台 PC 通过串口线连接起来:计算机 A 串口 COM1 端口的 TXD 与计算机 B 串口 COM1 端口的 RXD 相连, 计算机 A 串口 COM1 端 口的 RXD 与计算机 B 串口 COM1 端口的 TXD 相连, 计算机 A 串口 COM1 端口的 GND 与 计算机 B 串口 COM1 端口的 GND 相连。

用VB实现Modbus串行通讯

用VB实现Modbus串行通讯

如何用VB实现Modbus串行通讯在一些应用中可能需要使用诸如VB来进行上位机监控程序的开发,而Modbus协议是这类应用中首选的通讯协议;Modbus协议以其简单易用,在工业领域里已广泛的为其他第三方设备所支持。

这里对VB和Twido PLC间的通讯进行说明。

对于大部分应用,Twido PLC作为从站,它不需要编制通讯程序,只要把通讯口的参数设置好即可,例如下图表示此Twido通过编程口和上位机连接,其站号地址为2;波特率、数据位、校验、停止位和上位机设置保持一致。

VB程序通过利用MSComm控件很容易就能够实现。

1.通讯口初始化:MSComm1.Settings = "9600,n,8,1"mPort = 1MSComm1.SThreshold = 0If Not MSComm1.PortOpen Then MSComm1.PortOpen = True2.CRC校验码的计算方法,如以下函数,可以得到字节数组变量cmdstring指向的字符串的CRC校验码。

Function crc16_1(ByRef cmdstring() As Byte, ByVal j As Integer)Dim data As IntegerDim i As IntegerAddressreg_crc = &HFFFFFor i = 0 To jAddressreg_crc = Addressreg_crc Xor cmdstring(i)For j = 0 To 7data = Addressreg_crc And &H1If data ThenAddressreg_crc = Int(Addressreg_crc / 2)Addressreg_crc = Addressreg_crc And &H7FFFAddressreg_crc = Addressreg_crc Xor &HA001ElseAddressreg_crc = Addressreg_crc / 2Addressreg_crc = Addressreg_crc And &H7FFFEnd IfNext jNext iIf Addressreg_crc < 0 ThenAddressreg_crc = Addressreg_crc - &HFFFF0000End IfHiByte = Addressreg_crc And &HFFLoByte = (Addressreg_crc And &HFF00) / &H100End Function3.读多个字的命令(本例是从2号站读%MW10起始的4个字):Dim SendStr(7) As ByteDim RcvStr() As ByteSendStr(0) = 2 ,从站号是2SendStr(1) = &H3 ,读多个字的命令代码SendStr(2) = 0 ,起始地址高字节SendStr(3) = 10,起始地址低字节SendStr(4) = &H0,数据长度高字节SendStr(5) = 4 ,数据长度低字节Call crc16(SendStr(), 5) ,CRC计算SendStr(6) = HiByteSendStr(7) = LoByte,读命令发送后,当接收5 + SendStr(5) * 2 个字节时产生中断CmdLenth = 5 + SendStr(5) * 2MSComm1.RThreshold = CmdLenthMSComm1.Output = SendStr ,发送命令4.写多个字的命令(本例是写2号站%MW20起始的3个字):Dim WriteStr() As Bytek = 6 ,写6个字节ReDim WriteStr(8 + k)WriteStr(0) = 2 ,从站号是2WriteStr(1) = &H10 ,写多个字的命令代码WriteStr(2) = 0 ,起始地址高字节WriteStr(3) = 20 ,起始地址低字节WriteStr(4) = &H0 ,数据长度高字节<字的个数> WriteStr(5) = k / 2 ,数据长度低字节<字的个数>WriteStr(6) = k ,数据长度<字节的个数> WriteStr(7) = &H12,写的第1个字的高字节WriteStr(8) = &H34,写的第1个字的低字节WriteStr(9) = &H56,写的第2个字的高字节WriteStr(10) = &H78,写的第2个字的低字节WriteStr(11) = &H9A,写的第3个字的高字节WriteStr(12) = &HBC,写的第3个字的低字节Call crc16(WriteStr(), 6 + k)WriteStr(9 + (k / 2 - 1) * 2) = HiByteWriteStr(10 + (k / 2 - 1) * 2) = LoByteMSComm1.InBufferCount = 0MSComm1.Output = WriteStr,写命令发送后,当接收到8个字节时中断CmdLenth = 8MSComm1.RThreshold = CmdLenth5.通讯事件中断产生时的数据处理:Private Sub MSComm1_OnComm()Dim inx() As ByteSelect Case mEventCase comEvReceive ,判断为接收事件MSComm1.InputLen = CmdLenth ,接收数据的长度inx = MSComm1.Input ,接收数据MSComm1.InBufferCount = 0For k = 3 To CmdLenth - 3tmpstr = tmpstr & "/" & Hex(inx(k))NextText1.Text = tmpstr ,以十六进制显示所接收长度的数据BeepEnd SelectEnd Sub。

用VB写的modbusrtu模式通讯源码

用VB写的modbusrtu模式通讯源码

用VB写的modbusrtu模式通讯源码‘用VB 写的modbus rtu模式通讯源码,已在台达PLC上调试通过Private Sub CmdOpen_Click()On Error Resume NextIf (MSComm1.PortOpen) Then ‘打开/关闭串口MSComm1.PortOpen = FalseElseMSComm1.PortOpen = TrueEnd IfIf (MSComm1.PortOpen) ThenCmdOpen.Caption = "关闭串口"Shape5.FillStyle = vbFSSolidElseCmdOpen.Caption = "打开串口"Shape5.FillStyle = vbFSTransparentEnd IfIf Err ThenMsgBox Error$, 48, "错误码信息"Exit SubEnd IfEnd SubPrivate Sub Combo1_Click()/doc/df18763589.html,mPort = Combo1.ListIndex + 1End SubPrivate Sub Combo2_Click()Call SettingEnd SubPrivate Sub Combo3_Click()Call SettingEnd SubPrivate Sub Combo4_Click()Call SettingEnd SubPrivate Sub Combo5_Click()Call SettingEnd SubPrivate Sub Command1_Click()‘S hape1.FillStyle = vbFSSolidDim Y0_status As ByteDim Sendstr As StringDim i As Integer, j As IntegerSendstr = "01 01 05 00 00 10 "HexSend (Sendstr)Sleep (30)HexSend (Sendstr)End SubPrivate Function HexSend(Sendstr As String) As Integer Dim outbuf() As ByteDim Temp(0) As ByteDim crc As String, Sendstrls As StringDim sendlen As IntegerDim i As Integer, j As IntegerIf Sendstr = "" ThenMsgBox "发送数据不能为空!"HexSend = 0Exit FunctionEnd IfS endstrls = Trim(Sendstr) ‘去掉空格sendlen = Len(Sendstrls) + 1 ‘取长度j = 0ReDim outbuf(1 To sendlen \ 3) As ByteFor i = 1 To sendlen Step 3j = j + 1outbuf(j) = Val("&H" & CStr(Mid(Sendstrls, i, 2)))Next icrc = Crc16(outbuf)ReDim Preserve outbuf(1 T o (sendlen \ 3 + 2)) As Byte ‘加上CRC校验码outbuf(sendlen \ 3 + 1) = Val("&H" & CStr(Mid(crc, 1, 2)))outbuf(sendlen \ 3 + 2) = Val("&H" & CStr(Mid(crc, 3, 2)))For i = 1 To (sendlen \ 3 + 2)Temp(0) = outbuf(i)MSComm1.Output = TempNext iFor i = 1 To 2000Next iHexSend = 1End FunctionPrivate Function Setting()MSComm1.Settings = CStr(Combo2.Text) & "," & CStr(Combo3.Text) & "," & CStr(Combo4.Text) & "," & CStr(Combo5.Text) End FunctionPrivate Sub Command2_Click()‘If (MSComm1.RThreshold = 0) Then‘MSComm1.RTh reshold = 1‘Else‘MSComm1.RThreshold = 0‘End IfLabel11.Caption = "接收个数:" & CStr(ReceCount) & " " & "接收帧数:" & CStr(Framecount) End SubPrivate Sub Form_Load()Combo1.AddItem ("COM1")Combo1.AddItem ("COM2")Combo1.AddItem ("COM3")Combo1.AddItem ("COM4")Combo1.AddItem ("COM5")Combo1.ListIndex = 0Combo2.AddItem ("2400")Combo2.AddItem ("4800")Combo2.AddItem ("9600")Combo2.AddItem ("11520")Combo2.ListIndex = 0Combo3.AddItem ("E")Combo3.AddItem ("O")Combo3.AddItem ("N")Combo3.ListIndex = 2Combo4.AddItem ("6")Combo4.AddItem ("7")Combo4.AddItem ("8")Combo4.ListIndex = 2Combo5.AddItem ("1")Combo5.AddItem ("2")Combo5.ListIndex = 0ReceCount = 0End SubPrivate Function Crc16(data() As Byte) As StringDim CRC16Lo As Byte, CRC16Hi As Byte ‘CRC寄存器Dim CL As Byte, CH As Byte ‘多项式码&HA001Dim CrcLo As String, CrcHi As StringDim SaveHi As Byte, SaveLo As ByteDim i As IntegerDim Flag As IntegerCRC16Lo = &HFFCRC16Hi = &HFFCL = &H1CH = &HA0For i = 1 To UBound(data)CRC16Lo = CRC16Lo Xor data(i) ‘每一个数据与CRC寄存器进行异或For Flag = 0 To 7SaveHi = CRC16HiSaveLo = CRC16LoCRC16Hi = CRC16Hi \ 2 ‘高位右移一位CRC16Lo = CRC16Lo \ 2 ‘低位右移一位If ((SaveHi And &H1) = &H1) Then ‘如果高位字节最后一位为1CRC16Lo = CRC16Lo Or &H80 ‘则低位字节右移后前面补1 End If ‘否则自动补0If ((SaveLo And &H1) = &H1) Then ‘如果LSB为1,则与多项式码进行异或CRC16Hi = CRC16Hi Xor CHCRC16Lo = CRC16Lo Xor CLEnd IfNext FlagNext iIf Len(Hex(CRC16Hi)) = 1 ThenCrcHi = "0" + Hex(CRC16Hi)ElseCrcHi = Hex(CRC16Hi)End IfIf Len(Hex(CRC16Lo)) = 1 ThenCrcLo = "0" + Hex(CRC16Lo)ElseCrcLo = Hex(CRC16Lo)End IfCrc16 = CrcLo & CrcHiEnd FunctionPrivate Sub MSComm1_OnComm()Dim inpu() As ByteDim i As IntegerDim tempstr As String, Strdata As StringSelect Case /doc/df18763589.html,mEvent Case comEvReceive ‘接收事件tempstr = MSComm1.Inputinpu() = tempstrFramecount = Framecount + 1 ‘帧个数加1If (Framecount = 1) Thenframepoint(Framecount) = UBound(inpu) + 1 ‘第一帧帧尾Elseframepoint(Framecount) = framepoint(Framecount - 1) + UBound(inpu) + 1 ‘第二帧开始指针End IfFor i = 0 To UB ound(inpu) ‘将字符转换为数组If (Len(Hex(inpu(i))) = 1) ThenStrdata = Strdata & "0" & Hex(inpu(i)) & " "ElseStrdata = Strdata & Hex(inpu(i)) & " "End IfNext iFor i = ReceCount + 1 To UBound(inpu) + 1 ‘数据进入缓冲区Recebuf(i) = inpu(i - 1)NextReceCount = ReceCount + UBound(inpu) + 1TextReceive.Text = TextReceive.Text & StrdataStrdata = ""Case comEvSendEnd SelectEnd SubPrivate Function RtuCheck(data() As Byte) As IntegerDim CrcHi As Byte, CrcLo As ByteDim Checkdata() As ByteDim i As IntegerDim crc As StringCrcHi = data(UBound(data))CrcLo = data(UBound(data) - 1)ReDim Checkdata(1 To (UBound(data) - 1)) As ByteFor i = 1 To (UBound(data) - 1) ‘附值Checkdata(i) = data(i - 1)Nextcrc = Crc16(Checkdata)If (CrcLo = Val("&H" & CStr(Mid(crc, 1, 2))) And CrcHi = Val("&H" & CStr(Mid(crc, 3, 2)))) Then RtuCheck = 1ElseRtuCheck = 0End IfEnd Function。

手把手教你用VB实现Modbus-RTU串行通讯工程实例

手把手教你用VB实现Modbus-RTU串行通讯工程实例

用VB实现Modbus RTU串行通讯在一些应用中可能需要使用诸如VB来进行上位机监控程序的开发,而Modbus协议是这类应用中首选的通讯协议;Modbus协议以其简单易用,在工业领域里已广泛的为其他第三方设备所支持。

这里对VB和Twi do PLC间的通讯进行说明。

对于大部分应用,Twido PLC作为从站,它不需要编制通讯程序,只要把通讯口的参数设置好即可,例如下图表示此Twido通过编程口和上位机连接,其站号地址为2;波特率、数据位、校验、停止位和上位机设置保持一致。

VB程序通过利用MSComm控件很容易就能够实现。

1.通讯口初始化:MSComm1.Settings = "9600,n,8,1"mPort = 1MSComm1.SThreshold = 0If Not MSComm1.PortOpen Then MSComm1.PortOpen = True2.CRC校验码的计算方法,如以下函数,可以得到字节数组变量cmdstring指向的字符串的CRC校验码。

Function crc16_1(ByRef cmdstring() As Byte, ByVal j As Integer)Dim data As IntegerDim i As IntegerAddressreg_crc = &HFFFFFor i = 0 To jAddressreg_crc = Addressreg_crc Xor cmdstring(i)For j = 0 To 7data = Addressreg_crc And &H1If data ThenAddressreg_crc = Int(Addressreg_crc / 2)Addressreg_crc = Addressreg_crc And &H7FFFAddressreg_crc = Addressreg_crc Xor &HA001ElseAddressreg_crc = Addressreg_crc / 2Addressreg_crc = Addressreg_crc And &H7FFFEnd IfNext jNext iIf Addressreg_crc < 0 ThenAddressreg_crc = Addressreg_crc - &HFFFF0000End IfHiByte = Addressreg_crc And &HFFLoByte = (Addressreg_crc And &HFF00) / &H100End Function3.读多个字的命令(本例是从2号站读%MW10起始的4个字):Dim SendStr(7) As ByteDim RcvStr() As ByteSendStr(0) = 2 ,从站号是2SendStr(1) = &H3 ,读多个字的命令代码SendStr(2) = 0 ,起始地址高字节SendStr(3) = 10,起始地址低字节SendStr(4) = &H0,数据长度高字节SendStr(5) = 4 ,数据长度低字节Call crc16(SendStr(), 5) ,CRC计算SendStr(6) = HiByteSendStr(7) = LoByte,读命令发送后,当接收5 + SendStr(5) * 2 个字节时产生中断CmdLenth = 5 + SendStr(5) * 2MSComm1.RThreshold = CmdLenthMSComm1.Output = SendStr ,发送命令4.写多个字的命令(本例是写2号站%MW20起始的3个字):Dim WriteStr() As Bytek = 6 ,写6个字节ReDim WriteStr(8 + k)WriteStr(0) = 2 ,从站号是2WriteStr(1) = &H10 ,写多个字的命令代码WriteStr(2) = 0 ,起始地址高字节WriteStr(3) = 20 ,起始地址低字节WriteStr(4) = &H0 ,数据长度高字节<字的个数>WriteStr(5) = k / 2 ,数据长度低字节<字的个数>WriteStr(6) = k ,数据长度<字节的个数> WriteStr(7) = &H12,写的第1个字的高字节WriteStr(8) = &H34,写的第1个字的低字节WriteStr(9) = &H56,写的第2个字的高字节WriteStr(10) = &H78,写的第2个字的低字节WriteStr(11) = &H9A,写的第3个字的高字节WriteStr(12) = &HBC,写的第3个字的低字节Call crc16(WriteStr(), 6 + k)WriteStr(9 + (k / 2 - 1) * 2) = HiByte WriteStr(10 + (k / 2 - 1) * 2) = LoByteMSComm1.InBufferCount = 0MSComm1.Output = WriteStr,写命令发送后,当接收到8个字节时中断CmdLenth = 8MSComm1.RThreshold = CmdLenth5.通讯事件中断产生时的数据处理:Private Sub MSComm1_OnComm()Dim inx() As ByteSelect Case mEventCase comEvReceive ,判断为接收事件MSComm1.InputLen = CmdLenth ,接收数据的长度inx = MSComm1.Input ,接收数据MSComm1.InBufferCount = 0For k = 3 To CmdLenth - 3tmpstr = tmpstr & "/" & Hex(inx(k))NextText1.Text = tmpstr ,以十六进制显示所接收长度的数据BeepEnd SelectEnd Sub。

串口通讯及其在VB平台下的实现

串口通讯及其在VB平台下的实现

串口通讯及其在VB平台下的实现摘要:本文首先介绍串行通讯的基础知识,然后结合示例剖析在VB平台下的串口通讯的编程技巧。

随着计算机系统的普及与外围设备技术的发展,计算机与外围设备之间的通讯就显得越来越重要了。

由于串行通信是在一根传输线上一位一位的传送信息,所用的传输线少,并且可以借助现成的电话网进行信息传送,因此,特别适合于远距离传输。

对于那些与计算机相距不远的人-机交换设备和串行存储的外部设备如终端、打印机、逻辑分析仪、磁盘等,采用串行方式交换数据也很普遍。

在实时控制和管理方面,采用多台微机处理机组成分级分布控制系统中,各CPU之间的通信一般都是串行方式。

所以串行接口是微机应用系统常用的接口,而相应的应用程序也成为今年来研究的热点。

本文旨在阐述一般的穿口通讯的原理及其程序设计,希望借此能够抛砖引玉,为更深入的研究打下一定的基础。

一、串行通讯的基本原理所谓"串行通信"是指外设和计算机间使用一根数据信号线,数据在一根数据信号线上按位进行传输,每一位数据都占据一个固定的时间长度。

这种通信方式使用的数据线少,在远距离通信中可以节约通信成本,当然,其传输速度比并行传输慢。

相比之下,由于高速率的要求,处于计算机内部的CPU与串口之间的通讯仍然采用并行的通讯方式,所以串行口的本质就是实现CPU与外围数据设备的数据格式转换(或者称为串并转换器),即当数据从外围设备输入计算机时,数据格式由位(bit)转化为字节数据;反之,当计算机发送下行数据到外围设备时,串口又将字节数据转化为位数据。

二、串口通讯的程序设计原理前面介绍了串行通讯的基本原理,那么如何在程序设计中实现它呢?事实上,这个过程并不复杂,一般有两种实现途径:其一就是使用MSCOMM控件,此控件提供很多方便操作的属性和方法,利用它们可以很方便地实现你的目的;另外一种途径就是使用Windows API,微软为开发者提供了很多相关的串行操作的编程接口,使用这些接口,可以很完成更为强大的功能。

vb串口编程实例

vb串口编程实例

VB串口编程实例介绍VB(Visual Basic)是一种基于对象的编程语言,可用于开发Windows应用程序。

串口编程是指通过串行通信接口与外部设备进行数据交互。

本文将介绍如何使用VB进行串口编程,以实现与外部设备的通信。

前提条件在开始编写VB串口程序之前,需要确保以下条件已满足: - 安装了Visual Studio开发环境,可以选择最新版本的Visual Studio Community免费版。

- 确保计算机上有可用的串口(如COM1、COM2等)或USB转串口适配器。

步骤1. 创建新项目打开Visual Studio,选择创建一个新的VB Windows应用程序项目。

2. 添加控件在窗体上添加以下控件: - 一个ListBox控件用于显示接收到的数据。

- 两个Button控件分别用于打开和关闭串口。

- 一个ComboBox控件用于选择串口号。

- 一个TextBox控件用于输入要发送的数据。

- 一个Button控件用于发送数据。

3. 设置串口属性在窗体代码中添加如下代码:Imports System.IO.PortsPublic Class Form1Dim serialPort As New SerialPort()Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Lo ad' 获取可用的串口号并添加到ComboBox中Dim ports As String() = SerialPort.GetPortNames()ComboBox1.Items.AddRange(ports)End SubPrivate Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click' 打开串口TryserialPort.PortName = ComboBox1.SelectedItem.ToString()serialPort.BaudRate = 9600serialPort.Parity = Parity.NoneserialPort.DataBits = 8serialPort.StopBits = StopBits.OneserialPort.Open()Button1.Enabled = FalseButton2.Enabled = TrueCatch ex As ExceptionMessageBox.Show("无法打开串口:" + ex.Message)End TryEnd SubPrivate Sub Button2_Click(sender As Object, e As EventArgs) Handles Button 2.Click' 关闭串口TryserialPort.Close()Button1.Enabled = TrueButton2.Enabled = FalseCatch ex As ExceptionMessageBox.Show("无法关闭串口:" + ex.Message)End TryEnd SubEnd Class4. 接收数据和发送数据在窗体代码中添加如下代码:Imports System.IO.PortsPublic Class Form1Dim serialPort As New SerialPort()Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Lo ad' 获取可用的串口号并添加到ComboBox中Dim ports As String() = SerialPort.GetPortNames()ComboBox1.Items.AddRange(ports)End SubPrivate Sub Button1_Click(sender As Object, e As EventArgs) Handles Button 1.Click' 打开串口' 省略部分代码...AddHandler serialPort.DataReceived, AddressOf DataReceivedHandlerserialPort.Open()Button1.Enabled = FalseButton2.Enabled = TrueEnd SubPrivate Sub Button2_Click(sender As Object, e As EventArgs) Handles Button 2.Click' 关闭串口' 省略部分代码...RemoveHandler serialPort.DataReceived, AddressOf DataReceivedHandler serialPort.Close()Button1.Enabled = TrueButton2.Enabled = FalseEnd SubPrivate Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedE ventArgs)' 接收数据并显示在ListBox中Dim data As String = serialPort.ReadLine()ListBox1.Invoke(Sub() ListBox1.Items.Add(data))End SubPrivate Sub Button3_Click(sender As Object, e As EventArgs) Handles Button 3.Click' 发送数据If serialPort.IsOpen ThenDim dataToSend As String = TextBox1.TextserialPort.WriteLine(dataToSend)TextBox1.Clear()ElseMessageBox.Show("请先打开串口")End IfEnd SubEnd Class5. 运行程序点击运行按钮,程序将打开一个窗口,其中包含串口选择、打开/关闭串口、接收数据和发送数据的功能。

VB下实现串口通信的方法

VB下实现串口通信的方法

VB下实现串口通信的方法1 VB下实现串口通信的方法1.1 通信控件MSComm简介VB下的串行端口通信是通过其提供的控件Microsoft Comm control(简称MSComm)实现的。

该控件屏蔽了通信过程中的底层操作,程序员只需设置并监视MSComm控件的属性和事件,结合其它VB提供的控件就可完成对串口的初始化和数据的发送接收。

本系统中用到的主要MSComm控件属性如下:①、Commport:设置并返回通信端口代码。

默认值为1,最大值为16,需要使用超过16个通信端口时,要采用其他方式操控通信端口(如PcommPro软件)。

例如将串口2设为通信端口:mPort=2。

②、Setting:设置初始化参数。

其格式为“****,P,D,S”,其中****为波特率(baud),P为校验方式,D为数据位数,S为停止位。

默认值为“9600,N,8,1”,意为“串口通信速度为9600Baud,无校验,每次数据为8个Bit,停止位为1个Bit”。

波特率可为110,300,600,1200,2400,9600,14400,19200,28800,38400(保留)等等。

校验位默认为None(无校验),若传输距离长,可增加校验位,可选M为符号校验,E为偶校验,O为奇校验,S为空白校验。

停止位的设定值可为:1(默认值),1.5,2。

此处的设置要和单片机侧的设置保持一致,否则不能实现正常的通信。

例如我们采用的初始化参数为“2400,N,8,1”,则单片机侧的设置相应项为:定时器1的初值为E6并且SMOD(串行口波特率加倍位)为1(对应2400Bit),串口控制寄存器SCON为40(10位异步收发,对应8Bit数据位,1Bit停止位)。

③、PortOpen:设置或返回通信端口状态。

④、Input:从缓冲区返回并删除字符。

将串行输入寄存器的数据读出,并清除寄存器中已读取的数据。

寄存器的特性是FIFO(First In First Out,先进先出)。

基于vb程序的串口通信实验2

基于vb程序的串口通信实验2

基于vb程序的串口通信实验一:实验目的:1通过实验,了解网络通讯的原理。

2了解TCP和UDP协议的基本知识。

3使用WINSLCK控件编写简单的网络应用程序。

4了解VB的WITH语句及枚举方法。

二:实验器材:两台pc机,一根电缆线。

三:实验原理:1. 通信部分:RS-232定义了21条接口电路的功能,接口连线叫做互换电路,简称电路。

21条电路按照功能可分为五类,每个电路都有一个具体的功能。

在本实验中,我们只是用到了其PIN2:发送数据TXD;PIN3:接收数据等引脚。

2.网络协议部分:协议就是一组程序或者标准,通过它们,不同类型和配置的计算机得以通讯.目前所有的计算机网络互连协议,都是基于ISO制定的OSI标准,OSI模型把网络连接从低到高划分为7个层次,物理层是最低的一层.在这一层上,主要解决电气上的技术问题.TCP协议是一个基于连结的允许创建和维护与远程计算机的连接.连结两台计算机就可以彼此进行数据传输.UDP协议则是一个无连结的协议.3.VB 部分:在里面我们用到了WINSOCK控件.四:实验运行结果: 1.发送:2.接收:3.设置参数:4.实验程序:五.实验总结:经过本次实验,使我学到了关于VB的相关知识,虽然我对VB的编程还不是很熟练,但是我相信在今后的学习中我一定可以加强编程能力的.六.程序清单:Private Sub Command1_Click()If MSComm1.PortOpen = True ThenMSComm1.PortOpen = FalseEnd IfMSComm1.Settings = "9600,N,8,1"MSComm1.RThreshold = 1MSComm1.PortOpen = TrueMSComm1.InputLen = 0End SubPrivate Sub Command2_Click()Call CommPortCloseintCommFlag = 0End SubCall FileSendManager(0)intCommFlag = 1End IfFileError:If intCommFlag > 0 ThenintCommFlag = 1ElseMsgBoxEnd IfEnd SubPrivate Sub xSend_Click()abc = tc.TextIf MSComm1.PortOpen = True Then MSComm1.PortOpen = FalseEnd IfMSComm1.Settings = "9600,N,8,1" MSComm1.PortOpen = TrueMSComm1.Output = abcMSComm1.PortOpen = FalseEnd SubPrivate Sub Command5_Click()abc = MSComm1.Inputtt.Text = abcEnd SubPrivate Sub Form_Load()Text1 = Winsock1.LocalIPIf MSComm1.PortOpen = False Then MSComm1.PortOpen = TrueEnd Ifabc = 0blnShowFlag = TrueMain.Height = 7000Call SetComm("9600,N,8,1", 2, 4096)intOutBufferSize = 2048imtCommFlag = 0monDialog1.Flags = &H200000 Or H2monDialog1.CancelError = TrueblnFileTransFlag = FalselReceive.Text = ""intArrayCount = 0End Sub基于vb程序的串口通信实验。

执行ModBus RTU协议应答的设备与VB的连接实例

执行ModBus RTU协议应答的设备与VB的连接实例

执行ModBus RTU协议应答的设备与VB的连接实例
关键词:ModBus RTU VB 通信OCX控件
ModBus RTU协议广泛应用于工业现场,监控软件除了使用商业组态软件外,使用VB是最基础且简单可行的办法,但对于不熟悉VB代码的工控界朋友也是个繁琐事,为此这里简单介绍一种可行的办法,使用ytmc.ocx控件!
l无需了解规约,不用一条条看规约,然后去编程,把这个任务交给ytmc控件。

l不用去编写繁琐的程序代码,只需填写控件属性。

l支持最大256个从机设备轮询。

关于该控件如何使用,下面我们来看个实例:
1、新建工程窗口,添加OCX组件
2、设置添加控件的属性
3、添加3局语句即可,仅此3句!
* 指定模块类型,自定义模块请参考说明书添加
ytmc1.ModuleName(address) = “M6001TRv100"
* 启动通信
call ytmc1.StartComm
* 定时刷新
call DMSS_All()
4、至此设置完毕,连接设备运行即可查看效果!
控件下载链接:/item.htm?id=19191725736 经检测有效!。

用VisualBasic实现串口通信的三种方法

用VisualBasic实现串口通信的三种方法

2. 利用通信控件的实例
Sub Form1 —load ()
form1. show ′设置 COM1
comm1. commport = 1
comm1. Setting = " 9600 ,o ,8 ,1" ′波特率 : 9600 奇校验 ,8
位数据 ,1 位停止位
comm1. Inputlen = 0
一 、利用通信控件( MSCOMM) 完成串口通信
VB 提供了通信控件 MSCOMM,文件名为 MSCOMM. VBX。 该控件可设置串行通信的数据发送和接收 ,对串口状态及串 行通信的信息格式和协议进行设置 。在通信过程中可以触发 OnComm 事件 ,在该事件过程进行数据检验处理及检错 ,还可 以通过编程访问 CommEvent 属性来了解通信的情况 ,进行收 发数据的处理 。每个通信控件对应一个串口 ,如果要访问多 个通信口 ,则要设计多个通信控件 。
利用 VB 提供的这些功能 ,我们可以有三种方法完成串 口通信 。一种是用 VB 提供的具有强大功能的通信控件 ;另一 种方法是调用 WINDOWS API 函数 ,使用 WINDOWS 提供的 通信函数编写移植性强的应用程序 ;第三是利用文件的输 入/ 输出完成 ,该方法简便易行 ,但有一定的局限性 。
EofChar As String 3 1
·6 ·
参数 As 类型 ]) As 类型 在声明中 :DECLARE 表示声明 DLL 中的函数 ,当声明是
不具有返回值的过程时用 SUB 关键字 ,而如果调用的函数具 有返回值 ,则必须用 FUNCTION 关键字将其声明为函数并在 声明语句的最后用 AS 指明函数返回值的类型 。LIB 关键字表 示当前声明的过程或函数是库名所指定的库中函数而非 VB 本身的函数 。库名 ,就是对应动态链接库的名称 ,其中通信函 数在 USER 库中 。ByVal 关键字将原参数数据类型一一对应到 VB 类型中 。

VB中串口通讯的实现详解说明

VB中串口通讯的实现详解说明

VB中串口通讯的实现VB中串口通讯的实现一、概述串口通讯作为一种古老而又灵活的通讯方式,被广泛地应用于PC间的通讯以及PC和单片机之间的通讯之中。

提到串口通讯的编程,人们往往立刻想到C、汇编等对系统底层操作支持较好的编程语言以及大串繁琐的代码。

实际上,只要我们借助相关ActiveX控件的帮助,即使是在底层操作一向不被人看好的VB 中,一样能够实现串口通讯,甚至其实现方法和C、汇编相比,要更加快捷方便。

下面,笔者就介绍一下在VB中实现串口通讯的方法。

在Visual Basic中有一个名为Microsoft Communication Control(简称MSComm)的通讯控件。

我们只要通过对此控件的属性和事件进行相应编程操作,就可以轻松地实现串口通讯。

下面,笔者就简要地介绍一下MSComm控件的使用方法。

二、MSComm控件的主要属性、事件1、MSComm的属性由于MSComm控件属性很多,在此笔者仅介绍与实现串口通讯密切相关的核心属性。

Commport:设置通讯所占用的串口号。

如设成1(默认值),表示对Com1进行操作。

Setting:对串口通讯的相关参数。

包括串口通讯的比特率,奇偶校验,数据位长度、停止位等。

其默认值是“9600,N,8,1”,表示串口比特率是9600bit/s,不作奇偶校验,8位数据位,1个停止位。

Portopen:设置串口状态,值为True时打开串口,值为False时关闭串口。

Input:从输入寄存器读取数据,返回值为从串口读取的数据内容,同时输入寄存器将被清空。

Ouput:发送数据到输出寄存器。

InBufferCount:设置输入寄存器所存储的字符数,当将其值设为0时,则输入寄存器将被清空。

InputMode:设置从输入寄存器中读取数据的形式。

若值为0,则表示以文本形式读取;值为1,则表示以二进制形式读取。

OutBufferCount:设置输出寄存器所存储的字符数,当将其值设为0时,则输出寄存器将被清空。

visualbasic串口通信及编程实例

visualbasic串口通信及编程实例

visualbasic串口通信及编程实例Visual Basic串口通信及编程实例在实际的工业控制、机器人控制、智能家居等领域中,使用串口通信是一种非常广泛的方式。

Visual Basic (VB) 是一种微软公司开发的高级编程语言,它不仅易于学习,而且拥有丰富的图形界面设计和数据处理功能。

在本篇文章中,我们将深入介绍如何使用VB实现串口通信。

1. 建立串口通信首先,我们需要在VB中创建一个新的窗口(Form),然后打开工具箱,从中拖拽出一个SerialPort(串口)控件。

在控件属性中,我们需要为其指定相关的参数,例如串口名称、波特率、数据位、停止位、校验位等。

通常情况下,这些参数需要根据硬件设备的配置来进行调整。

在VB中实现串口通信的核心部分是对于SerialPort控件的事件监控。

具体来讲,当SerialPort收到一个数据包时,它会触发一个DataReceived事件。

对于这个事件,我们可以在程序中编写回调函数进行处理。

例如:Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e AsSystem.IO.Ports.SerialDataReceivedEventArgs) HandlesSerialPort1.DataReceived'在这里实现对于数据包的解析和处理End Sub2. 数据读取和发送在SerialPort控件中,有几种方法可以实现数据的读取和发送。

下面我们将介绍其中两种方法:(1) ReadExisting这个方法可以从串口中读取所有现有的数据,例如:Dim data As String = SerialPort1.ReadExisting()(2) Write这个方法可以向串口发送数据,例如:SerialPort1.Write("Hello World")注意,这个函数只能发送字符串数据。

基于VB的MODBUS_RTU通信规约实现办法(1)

基于VB的MODBUS_RTU通信规约实现办法(1)

基于VB的MODBUS_RTU通信规约实现办法(1)一、MODBUS_RTU通信规约1、通信数据类型及格式标准的MODBUS协议使用串行接口,保护、测控装置(以下称从机,相应称微机为主机)上使用RS-485通信接口,主机上则需要一个RS-232转RS-485转接卡,才能和从机联接。

因此通信信息是标准的串口格式,串行数据字节格式如表1。

表1:串行数据字节格式RTU模式下每个8Bit字节包含两个4Bit的十六进制数字。

这种方式的主要优点是:在同样的波特率下,可比ASCII方式传送更多的数据。

通信数据帧格式如表2。

表2:通信数据帧格式2、地址码和功能码地址码是标识接在同一RS-485总线上不同从机的编号,只有符合地址码的从机才能响应并根据命令回送信息。

地址码是一个字节,从0到255,要求从机地址码不能重复,每个从机只有唯一的地址码。

可定义的功能码为1到127,常用的几个功能码如表3。

表3:常用功能码3、错误校验MODBUS_RTU的数据校验方式采用CRC-16(循环冗余错误校验)其步骤如下:①预置一个16位寄存器为十六进制FFFF,称此寄存器为CRC寄存器。

②把第一个8位二进制数据与CRC低8位字节进行异或运算,将结果放入CRC寄存器。

③把这个16寄存器向右移一位,用0填补最高位,检查移出位。

④若向右移出的数位是0,则返回③,若向右(标记位)移出的数位是1,则CRC寄存器与多项式1010000000000001(A001)进行异或运算。

⑤重复③和④,直至移出8位。

⑥重复②~⑤,进行下一字节处理。

⑦所有字节处理完毕,得到的16位CRC寄存器的高低字节进行交换。

⑧最后得到的CRC寄存器内容即CRC码。

二、VB中串行通信组件设置使用“Microsoft Comm Control 6.0”即MSComm控件,参数设置如图1。

图1:MSComm控件参数设置端口主要参数有端口代号,即串口号,常见的有微机标准配置1和2,其他的号则是由PCI或USB接口转换来的。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

用VB实现Modbus RTU串行通讯在一些应用中可能需要使用诸如VB来进行上位机监控程序的开发,而Modbus协议是这类应用中首选的通讯协议;Modbus协议以其简单易用,在工业领域里已广泛的为其他第三方设备所支持。

这里对VB和Twido PLC间的通讯进行说明。

对于大部分应用,Twido PLC作为从站,它不需要编制通讯程序,只要把通讯口的参数设置好即可,例如下图表示此Twido通过编程口和上位机连接,其站号地址为2;波特率、数据位、校验、停止位和上位机设置保持一致。

VB程序通过利用MSComm控件很容易就能够实现。

1.通讯口初始化:
MSComm1.Settings = "9600,n,8,1"
mPort = 1
MSComm1.SThreshold = 0
If Not MSComm1.PortOpen Then MSComm1.PortOpen = True
2.CRC校验码的计算方法,如以下函数,可以得到字节数组变量cmdstring指向的字符串的CRC校验码。

Function crc16_1(ByRef cmdstring() As Byte, ByVal j As Integer)
Dim data As Integer
Dim i As Integer
Addressreg_crc = &HFFFF
For i = 0 To j
Addressreg_crc = Addressreg_crc Xor cmdstring(i)
For j = 0 To 7
data = Addressreg_crc And &H1
If data Then
Addressreg_crc = Int(Addressreg_crc / 2)
Addressreg_crc = Addressreg_crc And &H7FFF
Addressreg_crc = Addressreg_crc Xor &HA001
Else
Addressreg_crc = Addressreg_crc / 2
Addressreg_crc = Addressreg_crc And &H7FFF
End If
Next j
Next i
If Addressreg_crc < 0 Then
Addressreg_crc = Addressreg_crc - &HFFFF0000
End If
HiByte = Addressreg_crc And &HFF
LoByte = (Addressreg_crc And &HFF00) / &H100
End Function
3.读多个字的命令(本例是从2号站读%MW10起始的4个字):Dim SendStr(7) As Byte
Dim RcvStr() As Byte
SendStr(0) = 2 ,从站号是2
SendStr(1) = &H3 ,读多个字的命令代码
SendStr(2) = 0 ,起始地址高字节
SendStr(3) = 10,起始地址低字节
SendStr(4) = &H0,数据长度高字节
SendStr(5) = 4 ,数据长度低字节
Call crc16(SendStr(), 5) ,CRC计算
SendStr(6) = HiByte
SendStr(7) = LoByte
,读命令发送后,当接收5 + SendStr(5) * 2 个字节时产生中断CmdLenth = 5 + SendStr(5) * 2
MSComm1.RThreshold = CmdLenth
MSComm1.Output = SendStr ,发送命令
4.写多个字的命令(本例是写2号站%MW20起始的3个字):Dim WriteStr() As Byte
k = 6 ,写6个字节
ReDim WriteStr(8 + k)
WriteStr(0) = 2 ,从站号是2
WriteStr(1) = &H10 ,写多个字的命令代码
WriteStr(2) = 0 ,起始地址高字节
WriteStr(3) = 20 ,起始地址低字节
WriteStr(4) = &H0 ,数据长度高字节<字的个数>
WriteStr(5) = k / 2 ,数据长度低字节<字的个数>
WriteStr(6) = k ,数据长度<字节的个数> WriteStr(7) = &H12,写的第1个字的高字节WriteStr(8) = &H34,写的第1个字的低字节WriteStr(9) = &H56,写的第2个字的高字节WriteStr(10) = &H78,写的第2个字的低字节WriteStr(11) = &H9A,写的第3个字的高字节WriteStr(12) = &HBC,写的第3个字的低字节
Call crc16(WriteStr(), 6 + k)
WriteStr(9 + (k / 2 - 1) * 2) = HiByte WriteStr(10 + (k / 2 - 1) * 2) = LoByte
MSComm1.InBufferCount = 0
MSComm1.Output = WriteStr
,写命令发送后,当接收到8个字节时中断CmdLenth = 8
MSComm1.RThreshold = CmdLenth
5.通讯事件中断产生时的数据处理:Private Sub MSComm1_OnComm()
Dim inx() As Byte
Select Case mEvent
Case comEvReceive ,判断为接收事件
MSComm1.InputLen = CmdLenth ,接收数据的长度
inx = MSComm1.Input ,接收数据
MSComm1.InBufferCount = 0
For k = 3 To CmdLenth - 3
tmpstr = tmpstr & "/" & Hex(inx(k))
Next
Text1.Text = tmpstr ,以十六进制显示所接收长度的数据
Beep
End Select
End Sub。

相关文档
最新文档