Hello,
i'm using libmodbus 3.1.6 on OpenWrt 21 the following simple rtu master program seems do not transmit on rs485 interface.
#include .....
.......
int main(int argc, char **argv)
{
//Create a new RTU context with proper serial parameters (in this example,
//device name /dev/ttyS0, baud rate 9600, no parity bit, 8 data bits, 1 stop bit)
modbus_t *ctx = modbus_new_rtu("/dev/rs485", 9600, 'N', 8, 1);
if (!ctx) {
fprintf(stderr, "Failed to create the context: %s\n", modbus_strerror(errno));
exit(1);
}
if(modbus_set_debug(ctx, TRUE) < 0)
printf("Error on setting debug mode (%s)\n",modbus_strerror(errno));
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Unable to connect: %s\n", modbus_strerror(errno));
modbus_free(ctx);
exit(1);
}
/* START ADD */
if( modbus_rtu_set_serial_mode(ctx,MODBUS_RTU_RS485 ) < 0 ){
printf("Error on setting RS485 (%s)\n",modbus_strerror(errno));
}
int i=modbus_rtu_get_serial_mode(ctx);
if(i == MODBUS_RTU_RS232 )
printf("serial type is RS232\n");
else if( i == MODBUS_RTU_RS485)
printf("serial type is RS485\n");
i=modbus_rtu_get_rts(ctx);
if(i == MODBUS_RTU_RTS_NONE )
printf("RTS NONE\n");
else if( i == MODBUS_RTU_RTS_UP)
printf("RTS UP\n");
else if (i == MODBUS_RTU_RTS_DOWN)
printf("RTS DOWN\n");
/* End Add */
//Set the Modbus address of the remote slave (to 3)
modbus_set_slave(ctx, 3);
uint16_t reg[5];// will store read registers values
//Read 5 holding registers starting from address 10
int num = modbus_read_registers(ctx, 10, 5, reg);
if (num != 5) {// number of read registers is not the one expected
fprintf(stderr, "Failed to read: %s\n", modbus_strerror(errno));
}
modbus_close(ctx);
modbus_free(ctx);
}
The environment is correct due to the fact that the other following small program that do not use libmodbus work correct
struct serial_rs485 rs485conf;
struct serial_rs485 rs485conf_orig;
int main(void) {
char dev[] = "/dev/rs485";
// [4E][03][00][14][00][01][CA][31]
char buffer_to_send[] = { 0x4E, 0x03, 0x00, 0x14, 0x00, 0x01, 0xCA, 0x31 };
int baudrate = B9600;
int fd = 0;
fd = open (dev, O_RDWR);
if (fd < 0) {
printf("SerialPort opening failed.\n");
return -1;
}
if (ioctl (fd, TIOCGRS485, &rs485conf_orig) < 0) {
printf("SerialPort orig config get failed.\n");
return -1;
}
/* Enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;
/* Set logical level for RTS pin equal to 1 when sending: */
//rs485conf.flags |= SER_RS485_RTS_ON_SEND;
/* or, set logical level for RTS pin equal to 0 when sending: */
rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
/* Set logical level for RTS pin equal to 1 after sending: */
//rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
/* or, set logical level for RTS pin equal to 0 after sending: */
rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
/* Set rts delay before send, if needed: */
rs485conf.delay_rts_before_send = 0;
/* Set rts delay after send, if needed: */
rs485conf.delay_rts_after_send = 0;
/* Set this flag if you want to receive data even whilst sending data */
//rs485conf.flags |= SER_RS485_RX_DURING_TX;
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
printf("SerialPort config failed.\n");
return -1;
}
struct termios option;
struct termios orig;
tcgetattr(fd, &option);
cfsetospeed(&option, B9600); /* baud rate */
option.c_cflag &= ~PARENB; /* no parity */
option.c_cflag &= ~CSTOPB; /* 1 stop bit */
option.c_cflag &= ~CSIZE;
option.c_cflag |= CS8 | CLOCAL; /* 8 bits */
option.c_lflag = ICANON; /* canonical mode */
option.c_oflag &= ~OPOST; /* raw output */
tcsetattr(fd, TCSANOW, &option); /* apply the settings */
tcflush(fd, TCOFLUSH);
printf("SerialPort loaded fd %d\n", fd);
// Send buffer_to_send content to RS485
if (write(fd, buffer_to_send, sizeof(buffer_to_send)) != sizeof(buffer_to_send)) {
printf("ERROR! write() failed \r\n");
}
orig.c_cflag &= ~HUPCL; // This to release the RTS after close
tcsetattr(fd, TCSANOW, &orig); // Restore the previous serial config
if (ioctl (fd, TIOCSRS485, &rs485conf_orig) < 0) {
printf("SerialPort config reset failed.\n");
return -1;
}
close(fd);
//return fd;
}
Where i'm wrong ?
Thanks for your support.
Reg
Fabio