Byte-stream for Modbus RTU?

T

Thread Starter

Timothy Burgess

For Modbus RTU, I've read that the following general message structure is required for reading holding registers:

3.5 ms frame start
device address
function code
register address (high)
register address (low)
number of registers (high)
number of registers (low)
CRC (low)
CRC (high)
3.5 ms frame end

And there apparently must be no delay between each byte.

Here's a snippet of my current code:

/* SNIPPET START */
crc16 = 0xFFFF;

crc16 = update_crc_16(crc16, slave_dev_addr);

crc16 = update_crc_16(crc16, func_code);

crc16 = update_crc_16(crc16, reg_addr_hi);
crc16 = update_crc_16(crc16, reg_addr_lo);

crc16 = update_crc_16(crc16, num_regs_hi);
crc16 = update_crc_16(crc16, num_regs_lo);

/* Swap CRC bytes for transmission */
crc16 = ((crc16 & 0xFF) * 256) + (crc16>>8);

IntToAsciiHex(lcd_text,4,crc16);
DisplayString(LCD_LINE2, lcd_text);

p0_0 = 1; // 5V to activate switch's pins 8 and 9,
// connected to the QSK62P's transmit pins;
// and deactivate switch's pins 6 and 11,
// connected to the QSK62P's receive pins

u0tb = slave_dev_addr; // send slave address (A; +)
u2tb = ~slave_dev_addr; // send slave address (B; -)

while((ti_u0c1 == 0)&&(ti_u2c1 == 0)); // make sure transmit is complete

u0tb = func_code; // send function code (A; +)
u2tb = ~func_code; // send function code (B; -)

while((ti_u0c1 == 0)&&(ti_u2c1 == 0)); // make sure transmit is complete

u0tb = reg_addr_hi; // send register address (A; +)
u2tb = ~reg_addr_hi; // send register address (B; -)

while((ti_u0c1 == 0)&&(ti_u2c1 == 0)); // make sure transmit is complete

u0tb = reg_addr_lo; // send register address (A; +)
u2tb = ~reg_addr_lo; // send register address (B; -)

while((ti_u0c1 == 0)&&(ti_u2c1 == 0)); // make sure transmit is complete

u0tb = num_regs_hi; // send number of registers to return (A; +)
u2tb = ~num_regs_hi; // send number of registers to return (B; -)

while((ti_u0c1 == 0)&&(ti_u2c1 == 0)); // make sure transmit is complete

u0tb = num_regs_lo; // send number of registers to return (A; +)
u2tb = ~num_regs_lo; // send number of registers to return (B; -)

while((ti_u0c1 == 0)&&(ti_u2c1 == 0)); // make sure transmit is complete
u0tb = crc16; // send CRC (A; +)
u2tb = ~crc16; // send CRC (B; -)

while((ti_u0c1 == 0)&&(ti_u2c1 == 0)); // make sure transmit is complete

p0_0 = 0; // 0V to deactivate switch's pins 8 and 9,
// connected to the QSK62P's transmit pins;
// and activate switch's pins 6 and 11,
// connected to the QSK62P's receive pins

while(ri_u0c1 == 0); // make sure receive is complete
in_data = (long) u0rb; // read in received data

IntToAsciiHex(lcd_text,4,in_data);
DisplayString(LCD_LINE2, lcd_text);
/* SNIPPET END */



The problem I'm running into is that it gets stuck at...

while(ri_u0c1 == 0); // make sure receive is complete

...meaning the slave device doesn't receive the proper query or maybe I've connected the switch wrongly (although I don't see how I could have messed that up lol I paid very close attention). I'm guessing the while loop after each byte is causing a delay between the transmission of bytes and the way to fix it is to join all of the bytes into one string, but I'm not sure how to do this and I'm actually not using any standard headers (stdio.h, string.h, etc.) for this program. Am I guessing correctly?

Another thing I'm concerned about is the delay between transmitting over the positive end and inverting the bits for the negative end then transmitting those, although it should be negligible, right? What should I do? Also, I guess I should note that my CRC calculations have been verified so that shouldn't be an issue.

Thanks in advance,

Tim
 
Top