找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 62|回复: 0
打印 上一主题 下一主题
收起左侧

VB6.0上位机,下位机modbus 远程模块,控制接触器启停

[复制链接]
跳转到指定楼层
楼主
ID:1094208 发表于 2026-3-21 20:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
先学51单片机,后觉得232串口数据传输距离紧,继续学modbus rtu协议。学着写一个远程启停程序,请指正,利于我提高。
'用远程IO模块,4路输入,4路输出(常开、常闭)
'接触器接通,断开
'接触器线圈接Y1常开用于启动,接Y2常闭用于停止,辅助触头常开接X1,用于指示接触器已经吸合。
Option Explicit                        '强制显式声明

Dim Receiveover_shuzimokuai2 As Boolean              '1号接收成功或失败
'Dim Sendover As Boolean                                              '发送完毕 comm事件

Dim sendshuzimokuai2(7) As Byte      '数字模块2发送查询
Dim sendshuzimokuai2_Y1_c(7) As Byte      '数字模块2 Y1通    线圈接常开点用于启动  c  代表closed
Dim sendshuzimokuai2_Y1_o(7) As Byte      '数字模块2 Y1断                                            o 代表open
Dim sendshuzimokuai2_Y2_c(7) As Byte      '数字模块2 Y2通   线圈接常闭点用于停止
Dim sendshuzimokuai2_Y2_o(7) As Byte      '数字模块2 Y2断


Public lunxun_jishu As Integer                    '轮询计数,此程序只有一个模块,先串口发送查询,下一秒分析串口回传数据

Public flag_Y1_c As Integer                          '标志位  Y1接通
Public flag_Y1_o As Integer
Public flag_Y2_c As Integer
Public flag_Y2_o As Integer
'''''''''''''''''''''''''''''''''''''
Dim receiveArr_shuzimokuai2() As Byte       '下位机回传数据
' CRC计算函数
Public Function CRC16(data() As Byte, crc() As Byte) As String
Dim CRC16Hi As Byte
Dim CRC16Lo As Byte
CRC16Hi = &HFF
CRC16Lo = &HFF
Dim i As Integer
Dim iIndex As Long

For i = 0 To 10            '不同情况下需修改数值,看具体回传数据位数
iIndex = CRC16Lo Xor data(i)
CRC16Lo = CRC16Hi Xor GetCRCLo(iIndex)
CRC16Hi = GetCRCHi(iIndex)
Next i

crc(0) = CRC16Hi
crc(1) = CRC16Lo
End Function
'''''''''''''''''''''''''''''''''
'CRC低位字节值表
   Public Function GetCRCLo(Ind As Long) As Byte

    GetCRCLo = 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高位字节值表
  Public Function GetCRCHi(Ind As Long) As Byte

      GetCRCHi = 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, &HAD, _
&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 Function

'''''''''''''''''''''''''''''''''''
Private Sub cmd启动_Click()      '命令按钮
    flag_Y1_c = 1
End Sub
Private Sub cmd停止_Click()
    flag_Y2_c = 1
End Sub
''''''''''''''''''''''
Private Sub Form_Load()
        lunxun_jishu = 0                             '轮询计数
      '    以下数字模块查询字符  2号站
        sendshuzimokuai2(0) = &H2     '查询4个输入口状态
        sendshuzimokuai2(1) = &H4
        sendshuzimokuai2(2) = &H0
        sendshuzimokuai2(3) = &H0
        sendshuzimokuai2(4) = &H0
        sendshuzimokuai2(5) = &H4
        sendshuzimokuai2(6) = &HF1
        sendshuzimokuai2(7) = &HFA

        sendshuzimokuai2_Y1_c(0) = &H2   'Y1接通
        sendshuzimokuai2_Y1_c(1) = &H6
        sendshuzimokuai2_Y1_c(2) = &H0
        sendshuzimokuai2_Y1_c(3) = &H0
        sendshuzimokuai2_Y1_c(4) = &H0
        sendshuzimokuai2_Y1_c(5) = &H1
        sendshuzimokuai2_Y1_c(6) = &H48
        sendshuzimokuai2_Y1_c(7) = &H39

        sendshuzimokuai2_Y1_o(0) = &H2   'Y1断开
        sendshuzimokuai2_Y1_o(1) = &H6
        sendshuzimokuai2_Y1_o(2) = &H0
        sendshuzimokuai2_Y1_o(3) = &H0
        sendshuzimokuai2_Y1_o(4) = &H0
        sendshuzimokuai2_Y1_o(5) = &H0
        sendshuzimokuai2_Y1_o(6) = &H89
        sendshuzimokuai2_Y1_o(7) = &HF9

        sendshuzimokuai2_Y2_c(0) = &H2   'Y2接通
        sendshuzimokuai2_Y2_c(1) = &H6
        sendshuzimokuai2_Y2_c(2) = &H0
        sendshuzimokuai2_Y2_c(3) = &H1
        sendshuzimokuai2_Y2_c(4) = &H0
        sendshuzimokuai2_Y2_c(5) = &H1
        sendshuzimokuai2_Y2_c(6) = &H19
        sendshuzimokuai2_Y2_c(7) = &HF9

        sendshuzimokuai2_Y2_o(0) = &H2   'Y2断开
        sendshuzimokuai2_Y2_o(1) = &H6
        sendshuzimokuai2_Y2_o(2) = &H0
        sendshuzimokuai2_Y2_o(3) = &H1
        sendshuzimokuai2_Y2_o(4) = &H0
        sendshuzimokuai2_Y2_o(5) = &H0
        sendshuzimokuai2_Y2_o(6) = &HD8
        sendshuzimokuai2_Y2_o(7) = &H39

        Timer_lx.Enabled = True                         '一秒轮询一次
        Timer_lx.Interval = 1000

        MSComm1.CommPort = 4                    '设置Com4为通信端口
        MSComm1.Settings = "4800,n,8,1"

        MSComm1.InBufferSize = 128               '设置接收缓冲区128字节
        MSComm1.OutBufferSize = 128              '设置发送缓冲区
        MSComm1.InBufferCount = 0                '清空输入缓冲区
        MSComm1.OutBufferCount = 0               '清空输出缓冲区
        MSComm1.SThreshold = 1                   '发送缓冲区空触发发送事件   代表发送完毕
        MSComm1.InputMode = comInputModeBinary     '二进制
         MSComm1.PortOpen = True

End Sub
'''''''''''''''''''''''''''''''''''''''
Private Sub Timer_lx_Timer()
           lunxun_jishu = lunxun_jishu + 1      '计数正确,这样1秒轮巡一次 最快

            If lunxun_jishu = 1 Then
                 MSComm1.RThreshold = 13                        '回传数据13位,每13个字符到接收缓冲区引起触发接收事件
                 Receiveover_shuzimokuai2 = False               '先否定
                 MSComm1.OutBufferCount = 0               '清空输出缓冲区
                 MSComm1.InBufferCount = 0                '清空输入缓冲区
                 MSComm1.Output = sendshuzimokuai2     '发送  查询作用
            End If


            If lunxun_jishu = 2 Then     '分析数据
                   If (Receiveover_shuzimokuai2 = False) Then
                         txt_lunxun1 = "数字通讯失败"              '没有收到回传数据
                   End If

                   If (Receiveover_shuzimokuai2 = True) Then
                        txt_lunxun1 = "数字通讯正常"
                   End If

                  If flag_Y1_c = 1 Then                                         '启动按钮按下
                        MSComm1.OutBufferCount = 0               '清空输出缓冲区
                        MSComm1.Output = sendshuzimokuai2_Y1_c    'Y1接通
                  End If

                If flag_Y2_c = 1 Then                                            '停止按钮按下
                        MSComm1.OutBufferCount = 0                '清空输出缓冲区
                        MSComm1.Output = sendshuzimokuai2_Y2_c    'Y2接通
                End If

            End If

            If lunxun_jishu = 3 Then

                If flag_Y1_c = 1 Then
                        MSComm1.OutBufferCount = 0               '清空输出缓冲区
                        MSComm1.Output = sendshuzimokuai2_Y1_o    'Y1断开  相当于松开启动按钮,不能保持接通,因为接触器会自锁
                        flag_Y1_c = 0                                                '按钮命令复位
                End If

                  If flag_Y2_c = 1 Then
                     MSComm1.OutBufferCount = 0               '清空输出缓冲区
                        MSComm1.Output = sendshuzimokuai2_Y2_o    'Y2断开,常闭点闭合,为下一次启动准备
                        flag_Y2_c = 0                                             '按钮命令复位
                  End If

            End If

            If lunxun_jishu = 4 Then
                lunxun_jishu = 0
            End If

End Sub
''''''''''''''''''''''''''''''''''''''''
Private Sub hexReceive()

If (MSComm1.InBufferCount = 13) Then                '数据回传了

    receiveArr_shuzimokuai2 = MSComm1.Input
    Dim crcc(1) As Byte                                                 '用于CRC校验
    Dim jisuandedao(1) As Byte                                   '计算得到
    Dim ret As String

    Dim yanzheng(11) As Byte                                      '取前11位
    yanzheng(0) = receiveArr_shuzimokuai2(0)
    yanzheng(1) = receiveArr_shuzimokuai2(1)
    yanzheng(2) = receiveArr_shuzimokuai2(2)
    yanzheng(3) = receiveArr_shuzimokuai2(3)
    yanzheng(4) = receiveArr_shuzimokuai2(4)
    yanzheng(5) = receiveArr_shuzimokuai2(5)
    yanzheng(6) = receiveArr_shuzimokuai2(6)
    yanzheng(7) = receiveArr_shuzimokuai2(7)
    yanzheng(8) = receiveArr_shuzimokuai2(8)
    yanzheng(9) = receiveArr_shuzimokuai2(9)
    yanzheng(10) = receiveArr_shuzimokuai2(10)

    ret = CRC16(yanzheng, crcc())                          '计算校验码函数

    jisuandedao(0) = crcc(1)                                  '得到两位校验码
    jisuandedao(1) = crcc(0)

   '如果计算得到的校验码与回传的校验码一致,shape颜色改变
    If (jisuandedao(0) = receiveArr_shuzimokuai2(11)) And (jisuandedao(1) = receiveArr_shuzimokuai2(12)) Then
           Shape_yanzheng.FillColor = RGB(255, 123, 0)
    End If



    MSComm1.InBufferCount = 0                '清空输入缓冲区
        If receiveArr_shuzimokuai2(0) = &H2 Then     '地址站号2
            Receiveover_shuzimokuai2 = True

                If (receiveArr_shuzimokuai2(4) = &H1) Then           'X1接通,代表接触器吸合
                    Shape_run.FillColor = RGB(255, 0, 0)                     '运行小红灯红色,代表运行
                Else
                    Shape_run.FillColor = RGB(255, 255, 255)
                End If

        End If

End If

End Sub
''''''''''''''''''''''''''''''''''''''''''
Private Sub MSComm1_OnComm()

    Select Case MSComm1.CommEvent     '
        Case comEvReceive          '接收事件  接收到?个字符,产生事件
            Call hexReceive              '去处理接收到的数据
        Case comEvSend                '发送事件  发送缓冲区空,发生事件 重要*,对应属性
'            Sendover = True             '发送完毕

    End Select

End Sub


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表