Shop OBEX P1 Docs P2 Docs Learn Events
ModBusSlave — Parallax Forums

ModBusSlave

AlarusAlarus Posts: 48
edited 2013-09-27 10:29 in Propeller 1
Wrote to ModBusSlave object:cool:.
Supports 0x03 0x04 0x06 0x10 function.
Mode ASCII or RTU.
http://obex.parallax.com/object/706

Comments

  • MicksterMickster Posts: 2,694
    edited 2013-08-16 09:45
    Perfect timing. I was just considering using Modbus for I/O expansion.

    Many thanks!

    Mickster
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-23 14:44
    A quick question to anyone more familiar to Modbus than I...
    In this object, he has a variable for number of registers, and then their locations and sizes. Why would there be more than one? How would then be referenced? In my case, I have several status variables that I need to allow to be read over MODBUS (command 0x04) and I am wondering if I can somehow set a pointer to the existing locations, or need to write a routine to copy them over to a new MODBUS specific location...
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-09-23 15:29
    Command 0x04 (read input registers) specifies an address and a count -- the MODBUS object should provide those values to you (I haven't looked). If you have an array of words in your program you can handle the request like this:
    reg_pntr := @inputregs + (regcount << 1)
      repeat regcount
        theregister := word[reg_pntr]
        ' do somthing with it
        reg_pntr += 2
    
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-23 18:22
    Yes, I still haven't figured out why he is establishing an array of pointers to the registers. His example shows four sets of registers, with different numbers of values, but some with the same pointers for each.

    I think I will just have to establish my own array of longs, point to it in his setup, and then update the values in my software periodically...

    MODBUS doesn't have some typical set of four types of registers, or something, does it? So, depending on the command, it would use a different set of registers?
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-09-23 18:54
    I had a look and I can't quite get a grip on it, either. I wrote a MODBUS-enabled app a couple years ago for a client and have promised to rework the MODBUS (RTU only) object for release -- perhaps I should focus on that. I wrote mine trying to be as obvious as I can. Here's a snippet from that application that handles function 0x04.
    pub mb04_read_iregs | reg, qty, idx, work, crc
    
      reg := modbus.address                                         ' starting point, 1..N
      qty := modbus.quantity                                        ' # or regs to read 
    
      ' validate request
    
      if (qty > MB_MAX_IREGS)                                       ' requested qty ok?
        modbus.tx_exception(MB_X_VALUE)
        return
    
      if (reg > MB_MAX_IREGS)                                       ' addr ok?
        modbus.tx_exception(MB_X_ADDR)
        return
    
      if ((reg + qty - 1) > MB_MAX_IREGS)                           ' addr+qty ok?        
        modbus.tx_exception(MB_X_ADDR)
        return
    
        
      ' good request, build response
    
      modbus.clear_response                                          
      modbus.enqueue(MB_SLAVEID)
      modbus.enqueue(modbus.function)                                          
      modbus.enqueue(qty << 1)                                      ' x2 for words  
    
      reg += 30_000                                                 ' mb register
    
      repeat qty
        idx  := reg_index(reg++)                                    ' mb reg to index
        work := read_reg(idx)                                       ' get value
        modbus.enqueue(work.byte[1])                                ' big Endian
        modbus.enqueue(work.byte[0])
    
      crc := modbus.calc_crc16(modbus.obuf_pntr, modbus.obuf_len)  
            
      modbus.enqueue(crc.byte[0])                                   ' little Endian                         
      modbus.enqueue(crc.byte[1])
    
      modbus.tx_response
    
  • AlarusAlarus Posts: 48
    edited 2013-09-23 20:05
    Hi all.

    You can create as many registers as you need.
    CON 
      _CLKMODE = XTAL1 + PLL16X                                                                                                     'Set up the clock mode 
      _XINFREQ = 5_000_000                                                                                                          '5 MHz clock * 16x PLL = 80 MHz system clock speed
    
      ADDRESS  = 1                                                                                                                  'Slave address
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      QUANTITY = 6                                                                                                                  'Quantity registers
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      OFFSET   = 10                                                                                                                 'Offset starting address registers   
      PIN_RX   = 31                                                                                                                 'Receive pin
      PIN_TX   = 30                                                                                                                 'Transmit pin
      PIN_RT   = 29                                                                                                                 'Receive/Transmit pin, only RS-485 mode
      MODE     = 00000                                                                                                           'Mode
      BAUDRATE = 115_200                                                                                                            'Baudrate
                                                                                                                                    
      
    VAR 
      long MBS_Reg_Address                                                                                                          'ModBusSlave Structure 
      long MBS_Reg_Quantity
      long MBS_Reg_Offset  
      long MBS_Reg_Mode                                                                                                                                    
      long MBS_Reg_Baudrate
      long MBS_Pin_RX
      long MBS_Pin_TX
      long MBS_Pin_RT    
      long MBS_Ptr_Registers
      long MBS_Ptr_Minimum
      long MBS_Ptr_Maximum
                        
      word REG_VAL[QUANTITY]                                                                                                        'The array of working registers.
      word REG_MIN[QUANTITY]                                                                                                        'An array the minimum limits of working registers
      word REG_MAX[QUANTITY]                                                                                                        'An array the maximum limits of working registers
    
      
    OBJ
      MBS     : "ModBusSlave"                                                                                                       'Initialization ModbusSlave
      Buttons : "TouchButtons"                                                                                                      'Initialization TouchButtons
    
      
    PUB Main
    {{
         Starts execution of ModBusSlaveTest.spin
    
         This is a very simple test ModBus protocol.
      
         Parameters:    none
    
         Return:        none
    
         Example usage: N/A - executes on startup
    
         
    }}
      REG_VAL[0] := 0                                                                                                               'Initialization working registers
      REG_VAL[1] := 100
      REG_VAL[2] := 0
      REG_VAL[3] := 0
      REG_VAL[4] := 0
      REG_VAL[5] := 0
    
      REG_MIN[0] := 0                                                                                                               'Initialization minimum limits working registers
      REG_MIN[1] := 0
      REG_MIN[2] := 0
      REG_MIN[3] := 0
      REG_MIN[4] := 0
      REG_MIN[5] := 0
    
      REG_MAX[0] := 65535                                                                                                           'Initialization maximum limits working registers
      REG_MAX[1] := 65535
      REG_MAX[2] := 65535
      REG_MAX[3] := 65535
      REG_MAX[4] := 65535
      REG_MAX[5] := 65535  
    
      MBS_Reg_Address   := ADDRESS                                                                                                  'Initialization MBS structure
      MBS_Reg_Quantity  := QUANTITY
      MBS_Reg_Offset    := OFFSET  
      MBS_Reg_Mode      := MODE
      MBS_Reg_Baudrate  := BAUDRATE
      MBS_Pin_RX        := PIN_RX
      MBS_Pin_TX        := PIN_TX
      MBS_Pin_RT        := PIN_RT  
      MBS_Ptr_Registers := @REG_VAL
      MBS_Ptr_Minimum   := @REG_MIN
      MBS_Ptr_Maximum   := @REG_MAX  
      
      MBS.Start(@MBS_Reg_Address)                                                                                                   'Start the ModBusSlave object
    

    You can read from your modbus registers.
    outa[23..16] := REG_VAL[0]
    

    You can write in your modbus registers.
    REG_VAL[1]   := 26
    


    Make modbus register is read-only: constrained by the limits in registers REG_MIN and REG_MAX at a value REG_VAL.
        REG_MIN[3]   := Buttons.State
        REG_MAX[3]   := Buttons.State
        REG_VAL[3]   := Buttons.State
    
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-24 07:41
    Ok, Let's see if I understand this, then.

    REG_VAL[] stores the register values. REG_MIN[] and REG_MAX[] define legal limits for these values. So, to see the registers, you basically read or write to the REG_VAL[] array.

    All the processing for the bus itself are going on auto-magically in the assembly code. It is monitoring the bus, receiving commands, and then responding to them. If so, then this is a nice piece of code, although a little hard to interpret.

    Thank you very much!!!!
  • AlarusAlarus Posts: 48
    edited 2013-09-24 08:16
    Ok, Let's see if I understand this, then.

    REG_VAL[] stores the register values. REG_MIN[] and REG_MAX[] define legal limits for these values. So, to see the registers, you basically read or write to the REG_VAL[] array.

    All the processing for the bus itself are going on auto-magically in the assembly code. It is monitoring the bus, receiving commands, and then responding to them. If so, then this is a nice piece of code, although a little hard to interpret.

    Thank you very much!!!!

    Yes, it is. :smile:
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-24 11:54
    Getting very close now. Newest problem? Whole project is too large, so I need to reduce my memory footprint. I need 786 registers, and I am about 784 longs short. Any quick way to do away with the REG_MIN and REG_MAX arrays and go to a single MIN and MAX value? I would like to keep these tests, and I see that the tests are done in the function definitions, so could I change the array name to a simple constant pointer?

    Was really hoping to not get into assembler for this project... ;-)
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-24 13:41
    Ok, I removed the tests for minimum and maximum values (and went ahead and removed the 0x06 and 0x10 functions I don't need...) Now, I just have to heat up the system, load the software, and start testing! ;-)


    Function_0x03 mov lenght,#3
    mov crc,#$03
    add ptr,#3
    call #READ
    cmp data,reg_quantity wz,wc
    if_be cmp data,#$7D wz,wc
    if_be cmpsub data,#$01 wc
    if_c add data,#$01
    if_nc jmp #Exception
    mov count,data
    shl data,#1
    add lenght,data
    wrbyte data,ptr
    mov crc,#$02
    sub ptr,#2
    call #READ
    mov reg,data
    add reg,count
    ' cmp reg,reg_addr_max wz,wc
    ' if_be cmpsub data,reg_addr_min wc
    ' if_c add data,reg_addr_min
    ' if_nc jmp #Exception
    ' sub data,reg_addr_min
    shl data,#1
    add data,ptr_registers
    mov reg,data
    add ptr,#1
    :loop rdword data,reg
    call #WRITE

    I think these are the lines to remove to remove the size test...
  • AlarusAlarus Posts: 48
    edited 2013-09-24 19:07
    If you need a function read (0x03) you can specify MBS_Structure an array of pointers to your REG_VAL.
    MBS_Reg_Address   := ADDRESS
      MBS_Reg_Quantity  := QUANTITY
      MBS_Reg_Offset    := OFFSET  
      MBS_Reg_Mode      := MODE
      MBS_Reg_Baudrate  := BAUDRATE
      MBS_Pin_RX        := PIN_RX
      MBS_Pin_TX        := PIN_TX
      MBS_Pin_RT        := PIN_RT
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 
      MBS_Ptr_Registers := @REG_VAL
      MBS_Ptr_Minimum   := @REG_VAL
      MBS_Ptr_Maximum   := @REG_VAL
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    And Cut function 0x06 0x10:
    MODBUS                          mov     ptr,ptr_buffer                                                                                                               
                                    rdbyte  data,ptr                                                                                           
                                    cmp     data,reg_address                        wz
                  if_ne             cmp     data,#$00                               wz              
                  if_ne             jmp     #Error
                                    mov     crc,#$01              
                                    add     ptr,#1                                                          
                                    rdbyte  data,ptr                                
                                    mov     reg,#Exception
                                    cmp     data,#$03                               wz              
                  if_e              mov     reg,#Function_0x03
                                    cmp     data,#$04                               wz              
                  if_e              mov     reg,#Function_0x03                                                                              
                                    jmp     reg              
    '&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;'                                                                
    Exception                       mov     ptr,ptr_buffer                                                                          'Clear buffer pointer
                                    mov     lenght,#3
                                    add     ptr,#1                                                                                              
                                    rdbyte  data,ptr                                                                
                                    or      data,#$80                                                           
                                    wrbyte  data,ptr
                                    add     ptr,#1                               
                                    wrbyte  crc,ptr                                                                
                                    jmp     #MODBUS_ret
    '&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;'                                
    Function_0x03                   mov     lenght,#3
                                    mov     crc,#$03                                
                                    add     ptr,#3                                
                                    call    #READ                                                                
                                    cmp     data,reg_quantity                       wz,wc
                  if_be             cmp     data,#$7D                               wz,wc                                              
                  if_be             cmpsub  data,#$01                               wc
                  if_c              add     data,#$01                                         
                  if_nc             jmp     #Exception                                                                                                                                
                                    mov     count,data                                
                                    shl     data,#1
                                    add     lenght,data                                
                                    wrbyte  data,ptr                                
                                    mov     crc,#$02
                                    sub     ptr,#2                                                               
                                    call    #READ                                
                                    mov     reg,data                                
                                    add     reg,count                                
                                    cmp     reg,reg_addr_max                        wz,wc
                  if_be             cmpsub  data,reg_addr_min                       wc              
                  if_c              add     data,reg_addr_min                                                  
                  if_nc             jmp     #Exception                                
                                    sub     data,reg_addr_min
                                    shl     data,#1                                
                                    add     data,ptr_registers                                
                                    mov     reg,data
                                    add     ptr,#1                                
    :loop                           rdword  data,reg                                                                
                                    call    #WRITE
                                    add     reg,#2                                
                                    add     ptr,#2
                                    djnz    count,#:loop                                                                
                                    jmp     #MODBUS_ret
    '&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;'                             
    Broadcast                       mov     ptr,ptr_buffer
                                    rdbyte  data,ptr                                
                                    cmp     data,#$00                               wz              
                  if_e              mov     lenght,#0
    MODBUS_ret                      ret                                                                                                                            
    '&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;'
    
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-25 18:11
    Oh, the joys of debugging when a new system! I have downloaded a MODBUS master program for my PC, and I am trying to use it with a USB serial port to test my device. Of course, device is non-responsive to commands from the master, so the question is: Is it my device? The USB serial port? The master's output? Or the MODBUS code I have modified! Unfortunately, the propeller doesn't have any real debugger, so now I have to try and figure out how I can do debugging of assembly code. Your code looks good, but once you got down into the functions, you stopped putting in any comments! So, now I have to try and interpret what your code is doing, and I am not really an assembly language programmer...
  • AlarusAlarus Posts: 48
    edited 2013-09-25 19:26
    You should check the connection settings. Check also OFFSET parameter in MBS_Structure it sets the starting address of the location registers. Problems with USB-COM adapter should not be.
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-25 22:09
    Ok, what is the real purpose for OFFSET? The REG_VAL array holds the actual registers. It was just set at 10...
  • AlarusAlarus Posts: 48
    edited 2013-09-25 23:17
    OFFSET parameter shifts the MODBUS register address. For example OFFSET = 7
    REG_VAL [0] => MODBUS Address = 7
    REG_VAL [1] => MODBUS Address = 8
    REG_VAL [2] => MODBUS Address = 9
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-26 17:02
    Ok, the end of another day of testing, debugging, and head banging!

    Set up a little debug routine that basically used TRANSMIT to send out a test byte, and then put it into various places in the code. It appears that the problem occurs around here:

    RTU mov ptr,ptr_buffer 'Clear buffer pointer
    xor lenght,lenght 'Clear lenght

    'mov data2,#85
    'call #DEBUG2 '**************DEBUG******************
    test reg_mode,#%0010000 wz 'Test invert PIN_RX
    mov count,reg_cnt_run 'Load counter T3.5
    test msk_rx,ina wc 'Waiting for signal change at pin RX
    if_z_eq_c djnz count,#$-1 'Decrement counter
    if_z_ne_c jmp #RTU 'If there was a change RX signal and the counter is not zero, then the move starting point
    mov data2,#2
    call #DEBUG '**************DEBUG******************
    Next_Byte call #RECIVE 'Recive byte


    If I leave that DEBUG2 call in, I get continuous sends of data. When it is commented out, the code never reaches the second DEBUG call. It looks like the T3.5 test never passes. I looked at my incoming signal, and it looks like it doesn't have the full 3.5b preamble, just a standard start bit, so I tried modifying reg_cnt_run from 77 to 22 to make it just a single bit width. Still no joy, execution never seems to get past that jump back to RTU. Any ideas? Does that test for inverted PIN_RX actually do anything? I even tried setting that, as well...
  • AlarusAlarus Posts: 48
    edited 2013-09-26 19:04
    The preamble defines the beginning package MODBUS. If it does not mean being transmitted by another package. This is described in the specification of MODBUS.
    You can view a piece of code which initializes MODBUS?
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-26 19:23
    Yes, the MODBUS packets are being generated by CAS Modbus Scanner using a standard USB serial port (The Propeller PROP!) so I don't think it can create the usual 3.5 preamble. I have a logic analyzer on the transmit and receive lines, so I can watch the transitions. The code still doesn't get beyond the 3.5 test for the received signal. I have even set reg_cnt_run down to 18, but it still doesn't pass the test. BTW, anyone know if the code

    and dira,NOT msk_rx ' MAKE SURE RX IS IN INPUT MODE

    will make sure the pin is in input mode? I am starting to grasp at straws here...
  • AlarusAlarus Posts: 48
    edited 2013-09-26 19:34
    I find it difficult to evaluate code without seeing it. Show initialization code MODBUS.
    Use the tag "code" in the advanced mode.

    RX pin is no longer where it is not running?
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-26 19:41
    Ok, here is my code as set up right now...
    PUB Start
    {{
         Starts execution of ModBusSlave.spin
    
    
    
         
    }}
      'Begin by filling the MODBUS value and minimum arrays with zeros
      LONGFILL(@REG_VAL, 0, MOD_QUANTITY)
      'LONGFILL(@REG_MIN, 0, MOD_QUANTITY)
      'Fill the maximum value array with our maximum allowed value, 0x007D
      'LONGFILL(@REG_MAX, $007D, MOD_QUANTITY)
      DIRA[4]~~                     'Set the MODE_SEL pin to output
      OUTA[4]~                      'Set theMODE_SEL pin low - RS-232 signals
      MODE := MOD_MODE              'Set the default mode, an RS-232 bus
      if bmsCON#ModMode             'If we have an RS-485 bus, then change to that mode
        MODE := MOD_MODE1           'Set up RS-485 in our code
        OUTA[4]~~                   'Set the MODE_SEL pin high - RS-484 signals
      MBS_Reg_Address   := bmsCON#MOD_ADDRESS
      MBS_Reg_Quantity  := MOD_QUANTITY
      MBS_Reg_Offset    := MOD_OFFSET  
      MBS_Reg_Mode      := MODE
      MBS_Reg_Baudrate  := bmsCON#ModBaudRate
      MBS_Pin_RX        := bmsHWR#ModRx
      MBS_Pin_TX        := bmsHWR#ModTx
      MBS_Pin_RT        := bmsHWR#ModTxEn  
      MBS_Ptr_Registers := @REG_VAL
      'MBS_Ptr_Minimum   := @REG_VAL
      'MBS_Ptr_Maximum   := @REG_VAL
        DIRA[1]~ 
      MBS.Start(@MBS_Reg_Address)                                                                                                   'Start the ModBusSlave object 
      
    
    


    [code]
    PUB Start(MBS_Structure) : okay
    {{
    Start ModBus protocol - starts a cog.

    Parameters: MBS_Structure = Pointer to a structure ModBus

    MBS Structure: MBS_Reg_Address = Slave address
    MBS_Reg_Quantity = Quantity registers
    MBS_Reg_Offset = Offset starting address registers
    MBS_Reg_Mode = Bitwise mode configuration variable, see mode bit description below
    Mode bit 0 = Even/Odd parity bit
    Mode bit 1 = One/Two stop bits (if use two stop bits then parity bit is disabled)
    Mode bit 2 = RS-232/RS-485 interface (use pin RT)
    Mode bit 3 = RTU/ASCII coding (8/7 Data bits)
    Mode bit 4 = Invert pin RX
    Mode bit 5 = Invert pin TX
    Mode bit 6 = Open-drain/source pin TX
    MBS_Reg_Baudrate = Baud rate to transmit bits at (maximum 230400 bps @ 80 MHz)
    MBS_Pin_RX = Propeller pin to set up as RX-ing pin. Range = 0 - 31
    MBS_Pin_TX = Propeller pin to set up as TX-ing pin. Range = 0 - 31
    MBS_Pin_RT = Propeller pin to set up as RT-ing pin. Range = 0 - 31
    MBS_Ptr_Registers = A pointer to an array of data registers
    MBS_Ptr_Minimum = A pointer to an array the minimum limits of working registers
    MBS_Ptr_Maximum = A pointer to an array the maximum limits of working registers

    Return: Numeric value of the cog(1-8) that was started, false(0) if no cog is available.

    Example usage: MBS.Start(@MBS_Reg_Address)


    }}
    Stop 'Make sure the driver isnt already running
    reg_address := long[MBS_Structure][0]
    reg_quantity := long[MBS_Structure][1]
    reg_addr_min := long[MBS_Structure][2]
    reg_addr_max := long[MBS_Structure][2] + long[MBS_Structure][1]
    reg_mode := long[MBS_Structure][3]
    reg_tick := clkfreq / long[MBS_Structure][4] #> 112 'Number of clock ticks per bit for the desired baudrate
    ' change reg_cnt_run multiplier from 77 to 20 for testing
    reg_cnt_run := reg_tick * 18 'Load delay T3.5
    reg_cnt_run := reg_cnt_run >> 4
    reg_cnt_end := reg_tick * 33 'Load delay T1.5
    reg_cnt_end := reg_cnt_end >> 4
    msk_rx := |<long[MBS_Structure][5]
    msk_tx := |<long[MBS_Structure][6]
    msk_rt := |<long[MBS_Structure][7]
    ptr_registers := long[MBS_Structure][8]
    'ptr_minimum := long[MBS_Structure][9]
    'ptr_maximum := long[MBS_Structure][10]
    ptr_buffer := @buffer
    okay := cog := cognew(@ENTRY, 0) + 1



    DAT
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    ' Assembly language ModBus protocol '
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    org 0
    ENTRY mov add_cnt,reg_tick
    shr reg_tick,#1
    test reg_mode,#00100 wc 'Init PIN_RT according to mode
    if_c or dira,msk_rt
    test reg_mode,#00000 wz 'Init PIN_TX according to mode
    test reg_mode,#00000 wc
    if_z_ne_c or outa,msk_tx
    if_z or dira,msk_tx
    and dira,NOT msk_rx ' MAKE SURE RX IS IN INPUT MODE
    test reg_mode,#01000 wc 'Init bits according to mode
    if_nc add bits,#1
    sub shift,bits
    Error test reg_mode,#01000 wc 'Selecting the RTU / ASCII
    if_c jmp #ASCII

    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    RTU mov ptr,ptr_buffer 'Clear buffer pointer
    xor lenght,lenght 'Clear lenght

    'mov data2,#85
    'call #DEBUG2 '**************DEBUG******************
    test reg_mode,#10000 wz 'Test invert PIN_RX
    mov count,reg_cnt_run 'Load counter T3.5
    test msk_rx,ina wc 'Waiting for signal change at pin RX
    if_z_eq_c djnz count,#$-1 'Decrement counter
    if_z_ne_c jmp #RTU 'If there was a change RX signal and the counter is not zero, then the move starting point
    mov data2,#2
    call #DEBUG '**************DEBUG******************
    Next_Byte call #RECIVE 'Recive byte

    cmp lenght,#256 wc 'Buffer is full?
    if_nc jmp #Error 'If the buffer is full then the error
    wrbyte data,ptr 'Write byte to buffer
    add lenght,#1 'Increment lenght
    add ptr,#1 'Increment pointer
    mov count,reg_cnt_end 'Load counter T1.5
    test msk_rx,ina wc 'Waiting for signal change at pin RX
    if_z_eq_c djnz count,#$-1 'Decrement counter
    if_z_ne_c jmp #Next_Byte 'If there was a change in the signal RX and the counter is not zero, then get the next byte

    call #CRC16 'The calculation of CRC
    cmp lenght,#3 wc 'Checking length
    cmp crc,#0 wz 'Checking CRC
    if_c_or_nz jmp #Error 'If you do not comply then the error
    call #MODBUS 'Processing Modbus packet
    cmp lenght,#0 wz 'Checking length
    if_e jmp #RTU 'Next packet
    call #CRC16 'The calculation of CRC
    mov ptr,ptr_buffer 'Clear buffer pointer
    :loop rdbyte data,ptr 'Read byte to buffer
    add ptr,#1 'Increment pointer
    call #TRANSMIT 'Transmit byte
    djnz lenght,#:loop 'If the length is zero, then the finish transmit
    mov data,crc 'Set data low crc byte
    call #TRANSMIT 'Transmit byte
    shr data,#8 'Set data high crc byte
    call #TRANSMIT 'Transmit byte
    jmp #RTU 'Next packet
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    CRC16 mov ptr,ptr_buffer 'Clear buffer pointer
    mov count,lenght 'Load count
    neg crc,#1 'Set crc $FFFFFFFF
    shr crc,#16 'Set crc $0000FFFF
    :loop rdbyte data,ptr 'Read byte to buffer
    add ptr,#1 'Increment pointer
    xor crc,data 'Calculate CRC
    mov reg,#8
    shr crc,#1 wc
    if_c xor crc,poly
    djnz reg,#$-2
    djnz count,#:loop
    CRC16_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    ASCII mov ptr,ptr_buffer 'Clear buffer pointer
    xor lenght,lenght 'Clear lenght
    :loop call #RECIVE 'Recive byte
    cmp data,#$3A wz 'Compare byte received with ":"
    if_ne jmp #:loop 'Next byte
    First_Byte call #RECIVE 'Recive byte
    cmp data,#$0D wz 'Compare byte received with "CR"
    if_e jmp #Last_Byte 'If it is to go to last byte
    call #ASCII2HEX 'Convert ASCII to HEX
    shl data,#4
    mov reg,data
    Second_Byte call #RECIVE 'Recive byte
    call #ASCII2HEX 'Convert ASCII to HEX
    or data,reg
    cmp lenght,#256 wc
    if_nc jmp #Error
    wrbyte data,ptr 'Write byte to buffer
    add lenght,#1 'Increment lenght
    add ptr,#1
    jmp #First_Byte
    Last_Byte call #RECIVE
    cmp data,#$0A wz 'Compare byte received with "CR"
    if_ne jmp #Error
    call #LRC 'Calculate LRC
    cmp lenght,#3 wc 'Checking length
    cmp crc,#0 wz 'Checking LRC
    if_c_or_nz jmp #Error 'If you do not comply then the error
    call #MODBUS 'Processing Modbus packet
    cmp lenght,#0 wz 'Checking length
    if_e jmp #ASCII 'Next packet
    call #LRC 'Calculate LRC
    mov data,#$3A 'Set data ":"
    call #TRANSMIT 'Transmit byte
    mov ptr,ptr_buffer 'Clear buffer pointer
    :loop rdbyte data,ptr 'Read byte to buffer
    add ptr,#1 'Increment pointer
    mov reg,data 'Save data in reg
    shr data,#4 'Set data high byte
    call #HEX2ASCII 'Convert HEX to ASCII
    call #TRANSMIT 'Transmit byte
    mov data,reg 'Set data low byte
    call #HEX2ASCII 'Convert HEX to ASCII
    call #TRANSMIT 'Transmit byte
    djnz lenght,#:loop 'If the length is zero, then the finish transmit
    mov data,crc 'Transmit CRC
    shr data,#4 'Set data high crc byte
    call #HEX2ASCII 'Convert HEX to ASCII
    call #TRANSMIT 'Transmit byte
    mov data,crc 'Set data low crc byte
    call #HEX2ASCII 'Convert HEX to ASCII
    call #TRANSMIT 'Transmit byte
    mov data,#$0D 'Set data "CR"
    call #TRANSMIT 'Transmit byte
    mov data,#$0A 'Set data "LF"
    call #TRANSMIT 'Transmit byte
    jmp #ASCII 'Next packet
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    ASCII2HEX cmp data,#$47 wc
    if_c cmpsub data,#$30 wc
    if_nc jmp #Error
    cmp data,#$0A wc
    muxnc $,$ wc,nr
    if_c sub data,#$07
    if_c cmp data,#$0A wc
    if_c jmp #Error
    ASCII2HEX_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    HEX2ASCII and data,#$0F
    cmp data,#$0A wc
    add data,#$30
    if_nc add data,#$07
    HEX2ASCII_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    LRC mov ptr,ptr_buffer 'Clear buffer pointer
    mov count,lenght 'Load count
    xor crc,crc 'Clear reg_crc
    :loop rdbyte data,ptr 'Read byte to buffer
    add ptr,#1 'Increment pointer
    add crc,data 'Calculate CRC
    djnz count,#:loop
    neg crc,crc
    and crc,#$FF
    LRC_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    RECIVE 'call #DEBUG '**************DEBUG******************
    test reg_mode,#10000 wz

    :loop test msk_rx,ina wc
    if_z_eq_c jmp #:loop

    mov new_cnt,reg_tick
    add new_cnt,cnt
    waitcnt new_cnt,add_cnt
    test msk_rx,ina wc
    if_z_eq_c jmp #Error
    mov parity,reg_mode
    and parity,#1
    mov count,bits
    :bit waitcnt new_cnt,add_cnt

    test msk_rx,ina wc
    if_nz muxnc $,$ wc,nr
    if_c xor parity,#1
    rcr data,#1
    djnz count,#:bit
    shr data,shift
    waitcnt new_cnt,add_cnt
    test msk_rx,ina wc
    if_nz muxnc $,$ wc,nr
    if_c mov count,#1
    test reg_mode,#00010 wc
    if_c mov parity,#1
    xor count,parity wc
    if_c jmp #Error
    waitcnt new_cnt,#0
    test msk_rx,ina wc
    if_z_ne_c jmp #Error
    RECIVE_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    TRANSMIT test reg_mode,#00000 wz
    or outa,msk_rt
    mov parity,reg_mode
    and parity,#1
    or parity,#2
    shl parity,#1
    mov count,bits
    mov new_cnt,add_cnt
    test reg_mode,#00000 wc
    if_z_and_c xor parity,#1
    shr parity,#1 wc
    if_z muxc outa,msk_tx
    if_nz muxnc dira,msk_tx
    add new_cnt,cnt
    :bit test reg_mode,#00000 wc
    waitcnt new_cnt,add_cnt
    if_z_and_c xor data,#1
    ror data,#1 wc
    if_c xor parity,#1
    if_z muxc outa,msk_tx
    if_nz muxnc dira,msk_tx
    djnz count,#:bit
    waitcnt new_cnt,add_cnt
    test reg_mode,#00010 wc
    if_c mov parity,#3
    test reg_mode,#00000 wc
    if_z_and_c xor parity,#1
    shr parity,#1 wc
    if_z muxc outa,msk_tx
    if_nz muxnc dira,msk_tx
    waitcnt new_cnt,add_cnt
    test reg_mode,#00000 wc
    if_z_and_c xor parity,#1
    shr parity,#1 wc
    if_z muxc outa,msk_tx
    if_nz muxnc dira,msk_tx
    ror data,shift
    waitcnt new_cnt,add_cnt
    andn outa,msk_rt
    TRANSMIT_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    READ rdbyte parity,ptr
    shl parity,#8
    add ptr,#1
    rdbyte data,ptr
    or data,parity
    sub ptr,#1
    READ_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    WRITE ror data,#8
    wrbyte data,ptr
    rol data,#8
    add ptr,#1
    wrbyte data,ptr
    sub ptr,#1
    WRITE_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    MODBUS mov ptr,ptr_buffer
    rdbyte data,ptr
    cmp data,reg_address wz
    if_ne cmp data,#$00 wz
    if_ne jmp #Error
    mov crc,#$01
    add ptr,#1
    rdbyte data,ptr
    mov reg,#Exception
    cmp data,#$03 wz
    if_e mov reg,#Function_0x03
    cmp data,#$04 wz
    if_e mov reg,#Function_0x03
    ' cmp data,#$06 wz
    ' if_e mov reg,#Function_0x06
    ' cmp data,#$10 wz
    ' if_e mov reg,#Function_0x10
    jmp reg
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    Exception mov ptr,ptr_buffer 'Clear buffer pointer
    mov lenght,#3
    add ptr,#1
    rdbyte data,ptr
    or data,#$80
    wrbyte data,ptr
    add ptr,#1
    wrbyte crc,ptr
    jmp #MODBUS_ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    Function_0x03 mov lenght,#3
    mov crc,#$03
    add ptr,#3
    call #READ
    cmp data,reg_quantity wz,wc
    if_be cmp data,#$7D wz,wc
    if_be cmpsub data,#$01 wc
    if_c add data,#$01
    if_nc jmp #Exception
    mov count,data
    shl data,#1
    add lenght,data
    wrbyte data,ptr
    mov crc,#$02
    sub ptr,#2
    call #READ
    mov reg,data
    add reg,count
    cmp reg,reg_addr_max wz,wc
    if_be cmpsub data,reg_addr_min wc
    if_c add data,reg_addr_min
    if_nc jmp #Exception
    sub data,reg_addr_min
    shl data,#1
    add data,ptr_registers
    mov reg,data
    add ptr,#1
    :loop rdword data,reg
    call #WRITE
    add reg,#2
    add ptr,#2
    djnz count,#:loop
    jmp #MODBUS_ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    {
    Function_0x06 mov lenght,#6
    mov crc,#$02
    add ptr,#1
    call #READ
    cmp data,reg_addr_max wz,wc
    if_be cmpsub data,reg_addr_min wc
    if_c add data,reg_addr_min
    if_nc jmp #Exception
    sub data,reg_addr_min
    shl data,#1
    mov reg,data
    add data,ptr_minimum
    rdword lim_min,data
    sub data,ptr_minimum
    add data,ptr_maximum
    rdword lim_max,data
    sub data,ptr_maximum
    mov crc,#$03
    add ptr,#2
    call #READ
    cmp data,lim_max wz,wc
    if_be cmpsub data,lim_min wc
    if_c add data,lim_min
    if_nc jmp #Exception
    add reg,ptr_registers
    wrword data,reg
    jmp #Broadcast
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    Function_0x10 mov lenght,#6
    mov crc,#$03
    add ptr,#3
    call #READ
    cmp data,reg_quantity wz,wc
    if_be cmp data,#$7B wz,wc
    if_be cmpsub data,#$01 wc
    if_c add data,#$01
    if_nc jmp #Exception
    mov count,data
    shl count,#1
    add ptr,#2
    rdbyte data,ptr
    cmp data,count wz
    shr count,#1
    if_ne jmp #Exception
    mov crc,#$02
    sub ptr,#4
    call #READ
    mov reg,data
    add reg,count
    cmp reg,reg_addr_max wz,wc
    if_be cmpsub data,reg_addr_min wc
    if_c add data,reg_addr_min
    if_nc jmp #Exception
    mov crc,#$03
    add ptr,#5
    sub data,reg_addr_min
    shl data,#1
    mov reg,data
    test $,#1 wz
    :loop add reg,ptr_minimum
    rdword lim_min,reg
    sub reg,ptr_minimum
    add reg,ptr_maximum
    rdword lim_max,reg
    sub reg,ptr_maximum
    call #READ
    add lim_max,#1
    cmp data,lim_max wc
    if_c cmpsub data,lim_min wc
    if_c add data,lim_min
    if_nc test $,#0 wz
    add reg,ptr_registers
    wrword data,reg
    sub reg,ptr_registers
    add reg,#2
    add ptr,#2
    djnz count,#:loop
    if_z jmp #Exception
    }
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    Broadcast mov ptr,ptr_buffer
    rdbyte data,ptr
    cmp data,#$00 wz
    if_e mov lenght,#0
    MODBUS_ret ret
    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    DEBUG
    mov data_store,data
    'add data2, #1
    mov data,data2
    call #TRANSMIT
    mov data,data_store
    DEBUG_ret ret

    DEBUG2
    mov data,count
    call #TRANSMIT
    DEBUG2_ret ret

    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'
    poly long $A001
    bits long $7
    shift long $20
    reg_address long 0
    reg_quantity long 0
    reg_addr_min long 0
    reg_addr_max long 0
    reg_mode long 0
    reg_tick long 0
    reg_cnt_run long 0
    reg_cnt_end long 0
    msk_rx long 0
    msk_tx long 0
    msk_rt long 0
    ptr_registers long 0
    'ptr_minimum long 0
    'ptr_maximum long 0
    ptr_buffer long 0
    reg res 1
    ptr res 1
    crc res 1
    data res 1
    count res 1
    lenght res 1
    parity res 1
    new_cnt res 1
    add_cnt res 1
    lim_min res 1
    lim_max res 1

    data_store res 1 'Store existing value in data
    data2 res 1 'Value to send for debug


    '───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────'

    {{
    ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────
  • AlarusAlarus Posts: 48
    edited 2013-09-26 20:27
    PUB Start
    {{
         Starts execution of ModBusSlave.spin
    
    
    
         
    }}
      'Begin by filling the MODBUS value and minimum arrays with zeros
      LONGFILL(@REG_VAL, 0, MOD_QUANTITY)
      'LONGFILL(@REG_MIN, 0, MOD_QUANTITY)
      'Fill the maximum value array with our maximum allowed value, 0x007D
      'LONGFILL(@REG_MAX, $007D, MOD_QUANTITY)
      DIRA[4]~~                     'Set the MODE_SEL pin to output
      OUTA[4]~                      'Set theMODE_SEL pin low - RS-232 signals
      MODE := MOD_MODE              'Set the default mode, an RS-232 bus
      if bmsCON#ModMode             'If we have an RS-485 bus, then change to that mode
        MODE := MOD_MODE1           'Set up RS-485 in our code
        OUTA[4]~~                   'Set the MODE_SEL pin high - RS-484 signals
      MBS_Reg_Address   := bmsCON#MOD_ADDRESS
      MBS_Reg_Quantity  := MOD_QUANTITY
      MBS_Reg_Offset    := MOD_OFFSET  
      MBS_Reg_Mode      := MODE
      MBS_Reg_Baudrate  := bmsCON#ModBaudRate
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''                                                                 'Assign the value of direct pins.
      MBS_Pin_RX        := bmsHWR#ModRx                                                                                         'Example MBS_Pin_RX := 31
      MBS_Pin_TX        := bmsHWR#ModTx                                                                                          'Example MBS_Pin_TX := 30
      MBS_Pin_RT        := bmsHWR#ModTxEn                                                                                     'Example MBS_Pin_RT := 29
      MBS_Ptr_Registers := @REG_VAL
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
      MBS_Ptr_Minimum   := @REG_VAL                                                                                              'Don't comment
      MBS_Ptr_Maximum   := @REG_VAL
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        DIRA[1]~ 
      MBS.Start(@MBS_Reg_Address)                                                                                                   'Start the ModBusSlave object
    
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-26 20:54
    Sorry, no joy. New code for this section:
    'Begin by filling the MODBUS value and minimum arrays with zeros
      LONGFILL(@REG_VAL, 0, MOD_QUANTITY)
      'LONGFILL(@REG_MIN, 0, MOD_QUANTITY)
      'Fill the maximum value array with our maximum allowed value, 0x007D
      'LONGFILL(@REG_MAX, $007D, MOD_QUANTITY)
      DIRA[4]~~                     'Set the MODE_SEL pin to output
      OUTA[4]~                      'Set theMODE_SEL pin low - RS-232 signals
      MODE := MOD_MODE              'Set the default mode, an RS-232 bus
      if bmsCON#ModMode             'If we have an RS-485 bus, then change to that mode
        MODE := MOD_MODE1           'Set up RS-485 in our code
        OUTA[4]~~                   'Set the MODE_SEL pin high - RS-484 signals
      MBS_Reg_Address   := bmsCON#MOD_ADDRESS
      MBS_Reg_Quantity  := MOD_QUANTITY
      MBS_Reg_Offset    := MOD_OFFSET  
      MBS_Reg_Mode      := MODE
      MBS_Reg_Baudrate  := bmsCON#ModBaudRate
      MBS_Pin_RX        := 1        'bmsHWR#ModRx
      MBS_Pin_TX        := 0        'bmsHWR#ModTx
      MBS_Pin_RT        := 9        'bmsHWR#ModTxEn  
      MBS_Ptr_Registers := @REG_VAL
      MBS_Ptr_Minimum   := @REG_VAL
      MBS_Ptr_Maximum   := @REG_VAL
        DIRA[1]~ 
      MBS.Start(@MBS_Reg_Address)                                                                                                   'Start the ModBusSlave object 
      
    
    
  • AlarusAlarus Posts: 48
    edited 2013-09-26 21:16
    'Begin by filling the MODBUS value and minimum arrays with zeros
      LONGFILL(@REG_VAL, 0, MOD_QUANTITY)
      'LONGFILL(@REG_MIN, 0, MOD_QUANTITY)
      'Fill the maximum value array with our maximum allowed value, 0x007D
      'LONGFILL(@REG_MAX, $007D, MOD_QUANTITY)
      DIRA[4]~~                     'Set the MODE_SEL pin to output
      OUTA[4]~                      'Set theMODE_SEL pin low - RS-232 signals
      MODE := MOD_MODE              'Set the default mode, an RS-232 bus
      if bmsCON#ModMode             'If we have an RS-485 bus, then change to that mode
        MODE := MOD_MODE1           'Set up RS-485 in our code
        OUTA[4]~~                   'Set the MODE_SEL pin high - RS-484 signals
      MBS_Reg_Address   := bmsCON#MOD_ADDRESS
      MBS_Reg_Quantity  := MOD_QUANTITY
      MBS_Reg_Offset    := MOD_OFFSET  
      MBS_Reg_Mode      := MODE
      MBS_Reg_Baudrate  := bmsCON#ModBaudRate
      MBS_Pin_RX        := 1        'bmsHWR#ModRx
      MBS_Pin_TX        := 0        'bmsHWR#ModTx
      MBS_Pin_RT        := 9        'bmsHWR#ModTxEn  
      MBS_Ptr_Registers := @REG_VAL
      MBS_Ptr_Minimum   := @REG_VAL
      MBS_Ptr_Maximum   := @REG_VAL
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''    
    'DIRA[1]~                                                                                                                                      '?????
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''  
    MBS.Start(@MBS_Reg_Address)                                                                                                   'Start the ModBusSlave object
    

    Check you are using PIN 1 in other cog.
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-26 21:43
    Not that I can find. This is part of a much larger project, and we are replacing an SPI CAN system with MODBUS. No other use of pin 1 that I can find.

    I even tried to compile and run the demo program, with the same results. :-(
  • AlarusAlarus Posts: 48
    edited 2013-09-26 22:37
    May use a different pin.
    I used the QuickStart to check the result.
    Byte format: 8 E 1? You are using a pin RT?
  • Charles EdmondsonCharles Edmondson Posts: 46
    edited 2013-09-27 10:29
    Ok, my apologies to all! I finally pulled the board from my customer, and started toning out the connector pins to the propeller. The pin designations are wrong on the schematic! I will now put the RIGHT pin connections into the software and retest!
Sign In or Register to comment.