@TO C

Modbus通讯开发随记1——LibModbus库的学习

1.Modbus简介

Modbus是一种串行通信协议,由Modicon公司(现在的施耐德电气 Schneider Electric)于1979年为使用可编程逻辑控制器(PLC)而发表。Modbus已经成为工业领域通信协议的业界标准(De facto),并且现在是工业电子设备之间常用的连接方式。

定义:Modbus是一个主从架构的协议。一个节点作为主节点,其他参与通信的节点是从节点。
通讯方式和版本:Modbus协议目前存在用于串口以太网以及其他支持互联网协议的网络的版本。串行连接存在两个变种,Modbus ASCII 模式Modbus RTU 模式。它们在数值数据表示协议细节上略有不同。

2.libmodbus简介

libmodbus是目前Modbus设备开发最流行的开源库,它提供RTU(串口)TCP(Ethernet以太网)支持,可在Linux、FreeBSD、Mac OS和Windows平台上运行。
官方网站:https://libmodbus.org/
开源地址:https://github.com/stephane/libmodbus/
使用方式可参考博客:https://blog.csdn.net/whik1194/article/details/119010616(该博客对本人学习LibModbus提供了非常大的帮助,在此感谢作者
whik1194的博客的分享)。

3.libmodbus常用函数

3.1创建Modbus对象

创建Modbus-rtu对象创建Modbus-tcp对象
*modbus_t *modbus_new_rtu(const char ‘device’, int ‘baud’, char ‘parity’, int ‘data_bit’, int ‘stop_bit’);*modbus_t *modbus_new_tcp(const char *‘ip’, int ‘port’)
device:指定串口号ip:指定IP地址
baud:波特率port:端口号
parity:校验位
data_bit:数据位
stop_bit:停止位

--------------modbus_new_rtu()函数说明------
该函数将分配和初始化一个“modbus_t(libmodbus库定义的结构体)”对象,以便在串口环路中进行RTU通讯。
串口号:指定操作系统处理的串行端口的名称。如Linux中的“/dev/ttyS1”和windows中的“COM1”。
波特率:衡量串口传输速率的参数。指的是信号被调制后单位时间的变化次数,可以理解为通讯信号的频率,如9600、19200、57600、115200等。
校验位:用于检测数据传输过程中是否发生错误的手段。校验方式选择,“N”为无校验,“E”为偶校验,“O”为奇校验。关于各种校验的实现可参考:https://zhuanlan.zhihu.com/p/29693940。
数据位:规定传输一个字符由几位组成。可选值为5、6、7和8。
停止位:用于表示单个包的最后一位。可选值为1和2。

函数返回值:如果对象分配成功,将返回一个modbus_t 指针,否则将返回一个NULL


--------------modbus_new_tcp()函数说明------
该函数将分配和初始化一个“modbus_t(libmodbus库定义的结构体)”对象,以便与一个Modbus TCP IPv4服务器通讯。
指定IP地址:指定客户机想要建立连接的服务器的IP地址。“空值”用来以服务器模式监听任意IP地址。
端口:设置将要使用的TCP端口。将端口设置为MODBUS_TCP_DEFAULT_PORT以使用默认端口502。

函数返回值:如果对象分配成功,将返回一个modbus_t 指针,否则将返回一个NULL


3.2设置从机号
int modbus_set_slave(modbus_t *‘ctx’, int ‘slave’)
该函数用于设置串口设备ctx从机号slave,具体的函数行为由网络和设备协议决定。
RTU:定义要在主模式下通话的远程设备的从机ID,或者从机模式下设置内部从机ID。根据协议,Modbus设备只能持有其从机地址或特殊广播地址来获得消息。
TCP:只有消息必须到达串口网络中的设备时,TCP才需要从机号。
特殊值 MODBUS_BROADCAST_ADDRESS(广播地址)用于希望网络中所有Modbus设备接受请求的情况。
函数返回值:设置从机号成功,将返回0,否则将返回-1

3.3进入Modbus监听
int modbus_tcp_listen(modbus_t *‘ctx’, int ‘nb_connection’)
该函数用于创建规定网址或端口的Modbus连接插座。若ctx的地址设为NULL或’0.0.0.0’,任意地址均会被监听。nb_connection为最大连接数。
函数返回值:成功将返回0,否则将返回-1

3.4建立Modbus连接
int modbus_connect(modbus_t *‘ctx’)
该函数用于建立串口设备ctx与Modbus主机的连接。
函数返回值:成功将返回0,否则将返回-1

3.5设置响应超时时间
int modbus_set_response_timeout(modbus_t *‘ctx’, uint32_t ‘to_sec’, uint32_t ‘to_usec’)
该函数用于设置串口设备ctx等待响应的超时时间。
to_sec:“秒”;
to_usec:“微秒”;
函数返回值:成功将返回0,否则将返回-1

3.6分配寄存器阵列
modbus_mapping_t* modbus_mapping_new_start_address(int ‘start_bits’, int ‘nb_bits’,
int ‘start_input_bits’, int ‘nb_input_bits’,
int ‘start_registers’, int ‘nb_registers’,
int ‘start_input_registers’, int ‘nb_input_registers’);
该函数用于为Modbus设备分配从起始地址开始的可访问的线圈和寄存器存储镜像空间,
start_bitsnb_bits对应线圈寄存器(类似于开关量,或继电器状态,每一位(bit)对应一个信号的开关状态。支持读与写);
start_input_bitsnb_input_bits对应离散输入状态寄存器(相当于只读模式的线圈状态寄存器,只能读取不能写);
start_registersnb_registers对应保存寄存器(用于存放设备状态和设备数据,支持读与写);
start_input_registersnb_input_registers对应输入寄存器(用于存放模拟量设备数据,仅支持读操作);
函数返回值:成功返回指向寄存器阵列的结构体指针,否则将返回NULL。

3.7接受指令请求
int modbus_receive(modbus_t *‘ctx’, uint8_t *‘req’)
该函数用于从机设备ctx接收的Modbus主机指令请求,接收到的指令保存在req所指的缓存区。
函数返回值:成功将返回请求指令的长度(包括无请求将返回0),否则将返回-1。

3.8返回请求
int modbus_reply(modbus_t *‘ctx’, const uint8_t *‘req’, int ‘req_length’, modbus_mapping_t *‘mb_mapping’)
该函数用于从机设备ctx对请求进行响应,req为请求指令,req_length为请求指令的长度,mb_mapping为从机设备ctx的存储镜像空间。如果请求指示读取或写入值,则操作将根据操作数据的类型在modbus映射_mb_mapping_中进行。
函数返回值:成功将返回响应指令的长度,否者将返回-1。

3.9读取寄存器数据
int modbus_read_registers(modbus_t *‘ctx’, int ‘addr’, int ‘nb’, uint16_t *‘dest’)
该函数用于读取串口设备ctx起始地址为addrnb个寄存器的数据,读取的数据保存在dest数组中。
注意:确保申请了足够长度的dest内存。
函数返回值:成功将返回读取的寄存器数量,否则将返回-1

3.10写单个寄存器
int modbus_write_register(modbus_t *‘ctx’, int ‘addr’, const uint16_t ‘value’)
该函数用于实现在串口设备ctx地址addr写入value值的操作。
函数返回值:成功将返回1,否则将返回-1

3.11写多个寄存器
int modbus_write_registers(modbus_t *‘ctx’, int ‘addr’, int ‘nb’, const uint16_t *‘src’)
该函数用于实现:从串口设备ctx的地址addr开始,连续写入nb个数据的操作,数据源来自src所指向的数组。
注意:确保src数组长度足够。
函数返回值:成功将返回写入的寄存器数量,否则将返回-1

3.12写单个线圈
int modbus_write_bit(modbus_t *‘ctx’, int ‘addr’, int ‘status’)
该函数用于将串口设备ctx的地址addr线圈的状态置为status,status值需被设为TRUE或FALSE。
函数返回值:成功将返回1,否则将返回-1

3.13查看错误信息
const char *modbus_strerror(int ‘errnum’);
该函数用来根据Modbus错误码errnum查询错误信息。
函数返回值:返回对应于错误信息的字符串指针。

3.14关闭Modbus连接
void modbus_close(modbus_t *‘ctx’)
该函数用于关闭ctx的Modbus连接。
函数返回值:无。

3.15释放Modbus对象
void modbus_free(modbus_t *‘ctx’)
该函数将释放ctx对象所占空间

4.libmodbus的使用流程图

4.1Modbus从机的构建
Modbus从机构建示意图

4.2Modbus主机的构建
Modbus主机构件示意图

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐