特点
libmodbus是一个快速、跨平台的Modbus库。
描述
libmodbus是一个与使用Modbus协议的设备进行数据发送/接收的库。该库包含各种后端(backends)通过不同网络进行通信(例如,RTU模式下的串口或TCP / IPv6中的以太网)。
http://www.modbus.org网站提供了协议规范文档http://www.modbus.org/specs.php。
libmodbus提供了较低通信层的抽象,并在所有支持的平台上提供相同的API。
本文档介绍了了libmodbus概念,介绍了libmodbus如何从在不同的硬件和平台中实现Modbus通信,并为libmodbus库提供的函数提供了参考手册。
环境(contexts)
RTU后端(远程终端单元)用于串口通信,并使用用于协议通信的数据的紧凑的二进制表示形式。RTU格式遵循命令/数据,和CRC(cyclic redundancy check循环冗余校验)作为错误检查机制,以确保数据的可靠性。Modbus RTU是可用于Modbus的最常用的实现方式。Modbus RTU消息必须连续发送,不能有字符间隔(摘自Wikipedia,Modbus, http://en.wikipedia.org/wiki/Modbus 截至2011年3月13日,格林尼治时间20:51)。
Modbus RTU框架调用一个从站,一个处理Modbus请求的设备/服务器,以及一个发送请求的客户端(主站)。通信始终由主站服务端发起。
许多Modbus设备可以在同一个的物理链路上连接在一起(总线结构),因此在发送消息之前,必须使用modbus_set_slave设置从站(接收设备 )ID。如果您正在运行一个从站,则其从站号将用于过滤接收的消息。
创建modbus RTU 环境
初试化RTU环境指针 modbus_t *modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit)
modbus_t *modbus_new_rtu(const char *device, int baud, char parity, int data_bit, int stop_bit);
//参考代码:
modbus_t *ctx;
ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
if (ctx == NULL) {
fprintf(stderr, "Unable to create the libmodbus context\n");
return -1;
}
这个 modbus_new_rtu()函数会生成并初始化一个modbus的结构体来在串行线路中使用RTU模式进行通讯。
device 指定OS处理的串行端口的名称,比如 /dev/ttyS0 or /dev/ttyUSB0,在windows系统上,如果COM编号大于9,必须要在COM前加上\.\ ,比如 \\.\COM10.,参照http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx
baud :指定连接的波特率,比如9600, 19200, 57600, 115200等。
parity :代表奇偶检验位,有如下值:
N 无奇偶校验
E 偶数校验
O 奇数校验
data_bit :指定数据的位数,允许值有: 5, 6, 7 ,8.
stop_bit :指定停止位位数,允许值有1和2.
返回:如果建立成功,modbus_new_rtu()函数将返回指向modbus_t结构的指针。 否则它将返回NULL并将errno设置为An invalid argument was given.。
设置串口模式
获取当前串口模式 int modbus_rtu_get_serial_mode(modbus_t *ctx);
int modbus_rtu_get_serial_mode (modbus_t *ctx);
返回:如果成功, 函数应返回 MODBUS_RTU_RS232
或 MODBUS_RTU_RS485
。否则, 它将返回-1并将errno设为The current libmodbus backend is not RTU.
只用于RTU环境。
设置串口模式 int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);
int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);
mode: 填入 MODBUS_RTU_RS232 或 MODBUS_RTU_RS485
返回值:如果成功, 函数应返回0。否则, 它将返回-1 并将 errno 设置为下面定义的值之一。
EINVAL The current libmodbus backend is not RTU.
ENOTSUP The function is not supported on your platform.。
如果对 ioctl () 的调用失败, 将返回 ioctl 的错误代码。
在 RTU环境下 中获取当前RTS模式 int modbus_rtu_get_rts(modbus_t *ctx)(3.1.4版本补充)
int modbus_rtu_get_rts (modbus_t *ctx);
可以获得在当前ctx环境下发送请求的的模式。
返回值:
MODBUS_RTU_RTS_NONE MODBUS_RTU_RTS_UP MODBUS_RTU_RTS_DOWN -1,即调用失败,并设置EINVAL为The libmodbus backend is not RTU.
在RTU环境下获取设置RTS模式 int modbus_rtu_set_rts(modbus_t *ctx, int mode)(3.1.4版本补充)
int modbus_rtu_set_rts(modbus_t *ctx, int mode);
//例子:启动有正极性的RTS模式
modbus_t *ctx;
uint16_t tab_reg[10];
ctx = modbus_new_rtu("/dev/ttyS0", 115200, 'N', 8, 1);
modbus_set_slave(ctx, 1);
modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
modbus_rtu_set_rts(ctx, MODBUS_RTU_RTS_UP);
if (modbus_connect(ctx) == -1) {
fprintf(stderr, "Connexion failed: %s\n", modbus_strerror(errno));
modbus_free(ctx);
return -1;
}
rc = modbus_read_registers(ctx, 0, 7, tab_reg);
if (rc == -1) {
fprintf(stderr, "%s\n", modbus_strerror(errno));
return -1;
}
modbus_close(ctx);
modbus_free(ctx);
设置发送请求模式用于在RS485串行总线上进行通讯,默认模式为MODBUS_RTU_RTS_NONE,在把数据写入线路之前不会有信号发出。
要启用RTS 模式, 必须使用 MODBUS_RTU_RTS_UP或MODBUS_RTU_RTS_DOWN, 这些模式启用 RTS 模式并同时设置极性。使用MODBUS_RTU_RTS_UP时, 将RTS 标志位置为使能并进行 ioctl 调用, 然后在1毫秒的延迟后在总线上写入数据, 然后将 RTS 标志位置为非使能进行另一个 ioctl 调用, 并再次延迟1毫秒。MODBUS_RTU_RTS_DOWN模式与之类似, 但使用相反的 RTS 标志位。
如果成功, 函数应返回0。否则, 它将返回-1 并将 errno 设置为The libmodbus backend isn’t RTU or the mode given in argument is invalid.。
自定义RTS实现 int modbus_rtu_set_custom_rts(modbus_t *ctx, void (set_rts) (modbus_t ctx, int on))(3.1.4版本补充)
int modbus_rtu_set_custom_rts(modbus_t *ctx, void (set_rts) (modbus_t ctx, int on));
设置传输前后设置RST PIN要调用的自定义函数,默认情况下,默认情况下,设置为使用IOCTL调用切换RTS PIN的内部函数。
注意,该函数遵循RTS模式,必须使用值MODBUS_RTU_RTS_UP或MODBUS_RTU_RTS_DOWN来调用该函数。
返回:如果成功, modbus_rtu_set_custom_rts ()函数应返回0。否则, 它将返回-1 并将 errno 设置为The libmodbus backend is not RTU.