User Tools

Site Tools

한국어

cubloc:basic_modbus_rtu_slave:index

An Example Modbus RTU Slave in BASIC

The CUBLOC's built-in Modbus slave only operates on serial channel 1. To use a Modbus RTU slave on any other port requires one being implemented in BASIC. A demonstration of such an implementation can be found below.

It may still be necessary to configure your digital inputs and outputs with UsePin commands for the IO to function correctly.

#include "MSB6XX" 
 
Ramclear
 
Dim RecvFrameBuffer(256) As Byte
Dim RespFrameBuffer(256) As Byte
 
Dim bufferLength As Byte
Dim address As Integer
Dim dataLength As Byte
Dim computedCrc As Integer
Dim wordValue As Integer
Dim numOfWords As Integer
Dim byteIndex As Byte
Dim bitIndex As Byte
 
'Use COM 3 (MSB RS-485 port) in this example
'--------------------------------------------
Const COM_PORT As Byte = 3
On Recv3 Gosub MODBUS_RTU_HANDLER
 
'If using COM 2
'--------------
'Const COM_PORT As Byte = 2
'Opencom 2, 38400, 3, 256, 256
'On Recv2 Gosub MODBUS_RTU_HANDLER
 
Const SLAVE_ADDRESS As Byte = 1
 
Set Ladder On
 
Do
Loop
 
MODBUS_RTU_HANDLER:    
    'Wait for all data to arrive. This may need to be increased for slower baud rates.  A delay greater than
    '30ms should work well for all, but could be lowered for faster baud rates.
    Delay 10
 
    bufferLength = Blen(COM_PORT, 0)
    Geta COM_PORT, RecvFrameBuffer, bufferLength
 
    'Debug "Buffer Length "
    'Debug Dec bufferLength, Cr
 
    'Check the CRC
    Getcrc computedCrc, RecvFrameBuffer, bufferLength - 2
 
    'Debug "CRC "
    'Debug Hex computedCrc.Byte1
    'Debug Hex computedCrc.Byte0, Cr
 
    If computedCrc.Byte0 = RecvFrameBuffer(bufferLength-1) And computedCrc.Byte1 = RecvFrameBuffer(bufferLength-2) Then
        'Frame Is good
        'Debug "Received Frame", Cr
 
        Dim respIndex As Byte
        respIndex = 0
 
        Dim recvIndex As Byte
        recvIndex = 0
 
        'Check the slave address
        If RecvFrameBuffer(recvIndex) = SLAVE_ADDRESS Then
            'Debug "Slave Address is good: "
            'Debug Dec RecvFrameBuffer(recvIndex), Cr
 
            'Add slave address to response
            RespFrameBuffer(respIndex) = SLAVE_ADDRESS
 
            'Add function code to response
            Incr recvIndex
            Incr respIndex
            RespFrameBuffer(respIndex) = RecvFrameBuffer(recvIndex)
 
            'Read Bit
            If RecvFrameBuffer(recvIndex) = 1 Or RecvFrameBuffer(recvIndex) = 2 Then
                'Function code
                'Debug "Read Bit: "
                'Debug Dec RecvFrameBuffer(recvIndex), Cr
 
                'Address
                Incr recvIndex
                address.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                address.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Address: "
                'Debug Hex address, Cr
 
                'number of bits
                Dim numOfBits As Integer
                Incr recvIndex
                numOfBits.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                numOfBits.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Number Of Bits: "
                'Debug Dec numOfBits, Cr
 
                'Compute data length
                dataLength = numOfBits / 8
                If (numOfBits Mod 8) <> 0 Then
                    Incr dataLength
                End If
 
                Incr respIndex
                RespFrameBuffer(respIndex) = dataLength
 
                'Debug "Data Length: "
                'Debug Dec dataLength, Cr
 
                'Get Data
                For bitIndex = 0 To numOfBits - 1                    
                    'If we are starting on a new byte
                    If (bitIndex mod 8) = 0 Then
                        Incr respIndex
                        RespFrameBuffer(respIndex) = 0
                    End If
 
                    Dim bitAddress As Integer
                    bitAddress = bitIndex + address
 
                    Dim bitValue As Byte
                    If (bitAddress < &H1000) Then
                        bitValue = _P(bitAddress)
                    Elseif (bitAddress < &H4000) Then
                        bitValue = _M(bitAddress - &H1000)
                    Else
                        bitValue = _F(bitAddress - &H4000)
                    End If
 
                    RespFrameBuffer(respIndex) = RespFrameBuffer(respIndex) + (bitValue << (bitIndex Mod 8))
                Next
 
            'Read Words
            Elseif RecvFrameBuffer(recvIndex) = 3 Or RecvFrameBuffer(recvIndex) = 4 Then
                'Function code
                'Debug "Read Word: "
                'Debug Dec RecvFrameBuffer(recvIndex), Cr
 
                'Address
                Incr recvIndex
                address.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                address.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Address: "
                'Debug Hex address, Cr
 
                'number of words
                Incr recvIndex
                numOfWords.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                numOfWords.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Number Of Words: "
                'Debug Dec numOfWords, Cr
 
                'Compute data length
                dataLength = numOfWords * 2
 
                Incr respIndex
                RespFrameBuffer(respIndex) = dataLength
 
                'Debug "Data Length: "
                'Debug Dec dataLength, Cr
 
                'Get Data
                Dim wordIndex As Byte
                For wordIndex = 0 To numOfWords - 1
                    Dim wordAddress As Integer
                    wordAddress = wordIndex + address
 
                    'Debug "Data Address: "
                    'Debug Hex wordAddress, Cr
 
                    If wordAddress < &H6000 Then
                        wordValue = _T(wordAddress - &H5000)
                    Elseif wordAddress < &H7000 Then
                        wordValue = _C(wordAddress - &H6000)
                    Elseif wordAddress < &H8000 Then
                        wordValue = _D(wordAddress - &H7000)
                    Elseif wordAddress < &H9000 Then
                        wordValue = _WP(wordAddress - &H8000)
                    Elseif wordAddress < &HA000 Then
                        wordValue = _WM(wordAddress - &H9000)
                    Else
                        wordValue = _WM(wordAddress - &HA000)
                    End If
 
                    Incr respIndex
                    RespFrameBuffer(respIndex) = wordValue.Byte1
                    Incr respIndex
                    RespFrameBuffer(respIndex) = wordValue.Byte0
                Next
 
            'Write Bit
            Elseif RecvFrameBuffer(recvIndex) = 5 Then
                'Function code
                'Debug "Write Bit: "
                'Debug Dec RecvFrameBuffer(recvIndex), Cr
 
                'Address
                Incr recvIndex
                address.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                address.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Address: "
                'Debug Hex address, Cr
 
                'value to write
                Dim bitWriteCommand As Integer
                Incr recvIndex
                bitWriteCommand.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                bitWriteCommand.Byte0 = RecvFrameBuffer(recvIndex)
 
                If bitWriteCommand = &HFF00 Then
                    WriteBit address, 1
                Else
                    WriteBit address, 0
                Endif
 
                'Echo address in response
                Incr respIndex
                RespFrameBuffer(respIndex) = address.Byte1
                Incr respIndex
                RespFrameBuffer(respIndex) = address.Byte0
 
                'Echo value in response
                Incr respIndex
                RespFrameBuffer(respIndex) = bitWriteCommand.Byte1
                Incr respIndex
                RespFrameBuffer(respIndex) = bitWriteCommand.Byte0
 
            'Write word
            Elseif RecvFrameBuffer(recvIndex) = 6 Then
                'Function code
                'Debug "Write Word: "
                'Debug Dec RecvFrameBuffer(recvIndex), Cr
 
                'Address
                Incr recvIndex
                address.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                address.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Address: "
                'Debug Hex address, Cr
 
                'value to write
                Incr recvIndex
                wordValue.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                wordValue.Byte0 = RecvFrameBuffer(recvIndex)
 
                WriteWord address, wordValue
 
                'Echo address in response
                Incr respIndex
                RespFrameBuffer(respIndex) = address.Byte1
                Incr respIndex
                RespFrameBuffer(respIndex) = address.Byte0
 
                'Echo value in response
                Incr respIndex
                RespFrameBuffer(respIndex) = wordValue.Byte1
                Incr respIndex
                RespFrameBuffer(respIndex) = wordValue.Byte0
 
            'Write multiple bits
            Elseif RecvFrameBuffer(recvIndex) = 15 Then
                'Function code
                'Debug "Write Multiple Bits: "
                'Debug Dec RecvFrameBuffer(recvIndex), Cr
 
                'Address
                Incr recvIndex
                address.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                address.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Address: "
                'Debug Hex address, Cr
 
                'number of bits
                Incr recvIndex
                numOfBits.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                numOfBits.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Number Of Bits: "
                'Debug Dec numOfBits, Cr
 
                'Ignore the byte count
                Incr recvIndex
                Incr recvIndex
 
                'Write each bit value
                For bitIndex = 0 To numOfBits - 1
                    byteIndex = bitIndex / 8
                    'Debug "Byte Index: "
                    'Debug Dec byteIndex, Cr
 
                    'Debug "Byte Value: "
                    'Debug Hex RecvFrameBuffer(recvIndex + byteIndex), Cr
 
                    bitValue = RecvFrameBuffer(recvIndex + byteIndex) >> (bitIndex mod 8) And 1
                    'Debug "Bit Value: "
                    'Debug Dec bitValue, Cr
                    WriteBit address + bitIndex, bitValue
                Next
 
 
                'Echo address in response
                Incr respIndex
                RespFrameBuffer(respIndex) = address.Byte1
                Incr respIndex
                RespFrameBuffer(respIndex) = address.Byte0
 
                'Echo value in response
                Incr respIndex
                RespFrameBuffer(respIndex) = numOfBits.Byte1
                Incr respIndex
                RespFrameBuffer(respIndex) = numOfBits.Byte0
 
            'Write multiple words
            Elseif RecvFrameBuffer(recvIndex) = 16 Then
                'Function code
                'Debug "Write Multiple Words: "
                'Debug Dec RecvFrameBuffer(recvIndex), Cr
 
                'Address
                Incr recvIndex
                address.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                address.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Debug "Address: "
                'Debug Hex address, Cr
 
                'number of words
                Incr recvIndex
                numOfWords.Byte1 = RecvFrameBuffer(recvIndex)
                Incr recvIndex
                numOfWords.Byte0 = RecvFrameBuffer(recvIndex)
 
                'Ignore the byte count
                Incr recvIndex
                Incr recvIndex
 
                'Write each word value
                For wordIndex = 0 To numOfWords - 1
                    Incr recvIndex
                    wordValue.Byte1 = RecvFrameBuffer(recvIndex)
                    Incr recvIndex
                    wordValue.Byte0 = RecvFrameBuffer(recvIndex)
 
                    WriteWord address + wordIndex, wordValue
                Next
 
                'Echo address in response
                Incr respIndex
                RespFrameBuffer(respIndex) = address.Byte1
                Incr respIndex
                RespFrameBuffer(respIndex) = address.Byte0
 
                'Echo value in response
                Incr respIndex
                RespFrameBuffer(respIndex) = numOfWords.Byte1
                Incr respIndex
                RespFrameBuffer(respIndex) = numOfWords.Byte0
            End If
 
            'Compute CRC
            Incr respIndex
            Getcrc computedCrc, RespFrameBuffer, respIndex
            RespFrameBuffer(respIndex) = computedCrc.Byte1
            Incr respIndex
            RespFrameBuffer(respIndex) = computedCrc.Byte0
 
            Puta COM_PORT, RespFrameBuffer, respIndex + 1
        End If
 
    End If
 
    Bclr COM_PORT, 0
Return
 
Sub WriteBit(writeBitAddress As Integer, writeBitValue As Byte)
    If (writeBitAddress < &H1000) Then
        _P(writeBitAddress) = writeBitValue
    Elseif (writeBitAddress < &H4000) Then
        _M(writeBitAddress - &H1000) = writeBitValue
    Else
        _F(writeBitAddress - &H4000) = writeBitValue
    End If
End Sub
 
Sub WriteWord(writeWordAddress As Integer, writeWordValue As Integer)
    If writeWordAddress < &H6000 Then
        _T(writeWordAddress - &H5000) = writeWordValue
    Elseif writeWordAddress < &H7000 Then
        _C(writeWordAddress - &H6000) = writeWordValue
    Elseif writeWordAddress < &H8000 Then
        _D(writeWordAddress - &H7000) = writeWordValue
    Elseif writeWordAddress < &H9000 Then
        _WP(writeWordAddress - &H8000) = writeWordValue
    Elseif writeWordAddress < &HA000 Then
        _WM(writeWordAddress - &H9000) = writeWordValue
    Else
        _WM(writeWordAddress - &HA000) = writeWordValue
    End If
End Sub
cubloc/basic_modbus_rtu_slave/index.txt · Last modified: 2023/03/28 16:36 by COMFILE Technology