CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Modbus holding registers map
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
greenbridge



Joined: 14 May 2018
Posts: 19

View user's profile Send private message Send e-mail

Modbus holding registers map
PostPosted: Wed Aug 07, 2019 7:36 am     Reply with quote

Hi,

I have a Modbus RTU master unit that reads and writes holding registers indexed between 200 and 203.

Is there a simple way to adapt ex_modbus_slave.c for such purpose without need for huge holding register arrays?
dluu13



Joined: 28 Sep 2018
Posts: 395
Location: Toronto, ON

View user's profile Send private message Visit poster's website

PostPosted: Wed Aug 07, 2019 7:47 am     Reply with quote

You could make it so that if the function is to read or write holding registers, you just subtract 200 from your register address.

That should be a pretty simple modification to make in the switch statement of the example file.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Wed Aug 07, 2019 8:21 am     Reply with quote

The supplied 'modbus_read_holding_registers function will do this
without any issues.

The syntax is simple:

read_holding_registers
Input: int8 address Slave Address
int16 start_address Address to start reading from
int16 quantity Amount of addresses to read
Output: exception 0 if no error, else the exception

So in your case you just need to call it with 'start_address' set to 200
(query, guess this is probably 0x200?), and a 'quantity' of 4.
greenbridge



Joined: 14 May 2018
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Wed Aug 07, 2019 8:25 am     Reply with quote

Please note that I need code for the slave unit.
dluu13



Joined: 28 Sep 2018
Posts: 395
Location: Toronto, ON

View user's profile Send private message Visit poster's website

PostPosted: Wed Aug 07, 2019 9:46 am     Reply with quote

greenbridge wrote:
Please note that I need code for the slave unit.


Right, I was referring to the large switch statement inside the modbus slave example c program. In there, there are cases where you deal with the read and write holding registers. In there, you can specifically add some code to translate 200 to 203 down to 0 to 3 for example, by subtracting 200 from the part of the message that tells you the start register.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Wed Aug 07, 2019 1:29 pm     Reply with quote

The slave is just as easy. All you need to do, is where the slave code uses:

hold_regs+modbus_rx.data[1], just subtract 200 from the value from
modbus_rx.data[1].

Then in the entry line for this section, where it tests for the same value being >=8, test for it instead being <200 || >203. So it allows values from 200 to 203.
Obviously the variable is needed in both tests.
greenbridge



Joined: 14 May 2018
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 08, 2019 2:48 am     Reply with quote

From some strange reason the slave does not accept offset higher than 128:


Code:
            case FUNC_READ_HOLDING_REGISTERS:
            case FUNC_READ_INPUT_REGISTERS:
               if(modbus_rx.data[0] || modbus_rx.data[2] /* || modbus_rx.data[1] > 203*/)
                  modbus_exception_rsp(input_regs[INPUT_DETECTOR_ADDR],modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
                     modbus_read_holding_registers_rsp(input_regs[INPUT_DETECTOR_ADDR],(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]-127);
                  else{
                  // TODO: beräkna alarm level pct
                     adc_read(0);
                     modbus_read_input_registers_rsp(input_regs[INPUT_DETECTOR_ADDR],(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
                  }
                 
                     
               }
               break;


Traffic:
Code:
[10:44:27] <= Response: 01 03 06 10 68 00 00 08 34 44 3B
[10:44:26] => Poll: 01 03 00 7F 00 03 34 13


Code:
            case FUNC_READ_HOLDING_REGISTERS:
            case FUNC_READ_INPUT_REGISTERS:
               if(modbus_rx.data[0] || modbus_rx.data[2] /* || modbus_rx.data[1] > 203*/)
                  modbus_exception_rsp(input_regs[INPUT_DETECTOR_ADDR],modbus_rx.func,ILLEGAL_DATA_ADDRESS);
               else
               {
                  if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
                     modbus_read_holding_registers_rsp(input_regs[INPUT_DETECTOR_ADDR],(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]-128);
                  else{
                  // TODO: beräkna alarm level pct
                     adc_read(0);
                     modbus_read_input_registers_rsp(input_regs[INPUT_DETECTOR_ADDR],(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
                  }
                 
                     
               }
               break;


Traffic:
Code:
[10:46:32] <= Response: 01 03 06 00 00 00 00 00 00 21 75
[10:46:32] => Poll: 01 03 00 80 00 03 04 23
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Thu Aug 08, 2019 2:53 am     Reply with quote

What chip are you compiling for?.
If this is a PIC24/30, the default for all integers is signed. So an int8, will
only support -127 to 128. You'd need to change the declarations of the buffer
arrays used for the data to unsigned int8, or BYTE (which default to unsigned
int8), instead of 'char'.
Have run into this repeatedly with char arrays on these chips... :(
greenbridge



Joined: 14 May 2018
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 08, 2019 3:00 am     Reply with quote

I am compiling for PIC16F1518.

Last edited by greenbridge on Thu Aug 08, 2019 7:03 am; edited 1 time in total
greenbridge



Joined: 14 May 2018
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 08, 2019 3:55 am     Reply with quote

From the supplied modbus_phy_layer.h:

Code:
struct
{
   unsigned int8 address;
   unsigned int8 len;                       //number of bytes in the message received
   function func;                           //the function of the message received
   exception error;                         //error recieved, if any
   unsigned int8 data[MODBUS_SERIAL_RX_BUFFER_SIZE]; //data of the message received
} modbus_rx;


All the integers are unsigned. It seems that the problem is caused somewhere else, or did I look in the right place?
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Thu Aug 08, 2019 5:06 am     Reply with quote

Try bracketting:

hold_regs+(modbus_rx.data[1]-127));

hold_regs, is a pointer into RAM. Now if you add first, it is probable that it is
taken beyond the available end of the RAM 'area' by the addition, before the
subtraction is then done.
The internal knowledge of how large a pointer is allowed to be may be
interfering.
You have got #device *=16?.
Needed otherwise you are limiting memory address range to 8bits.
greenbridge



Joined: 14 May 2018
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 08, 2019 5:45 am     Reply with quote

Thanks. Works fine for holding registers with offset 200.

Now I have a new problem (surprise!):

The input registers have offset 300.

Code:
300 = 0b000100101100

is read by slave as
Code:
43 =0b‭00101011‬


Do you have any suggestions which hardware would be suitable for this application?
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Thu Aug 08, 2019 6:57 am     Reply with quote

Have you got the register array declared as int16 (it needs to be).
How old is your compiler?.
Critical question. Historically CCS had a fault, that pointers would increment
by one, whatever 'size' the variable being pointed to 'was'. This has been
fixed for a long while, but if your compiler predates this fix, then the
arithmetic to find the actual variable address would need to multiply
the index by two to be pointing to the right location.
Honestly, the PIC16 makes things very hard, any PIC18 would be a lot
better. Except for tiny applications, I'd use a PIC18 every time....
greenbridge



Joined: 14 May 2018
Posts: 19

View user's profile Send private message Send e-mail

PostPosted: Thu Aug 08, 2019 7:01 am     Reply with quote

I have quite new PC running Win10.

I tried to alter the data array definition in modbus_rx structure to unsigned int16 but it messes up the CRC.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Thu Aug 08, 2019 7:19 am     Reply with quote

Again how old is your compiler?.
Where have you sourced the code you are using?.

The standard slave example, with the current compilers has the array
declared as int16, for PCD, PCH & PCM based chips. I've looked back over
ten years at the examples, and they are all using 16bit arrays for the
registers.
They read the data from the receiving (byte) array using the
modbus_read_holding_registers function. They don't attempt to directly
use the receive array.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group