Modbus是一种通信协议,通常用于工业自动化系统中的设备之间进行通信。它可以在不同的物理介质上运行,包括RS485接口。RS485是一种串行通信标准,常用于工业自动化系统中。它允许多个设备通过单个通信线路进行通信,并且可以实现远距离通信。因此,Modbus协议经常在RS485接口上实现,以便在工业自动化系统中进行设备之间的通信。
libmodbus是一个用于实现Modbus协议的开源C语言库,它提供了一组API,用于在不同的平台上进行Modbus通信。libmodbus库支持Modbus RTU、Modbus ASCII和Modbus TCP协议,并且可以在Linux、Unix、Windows等操作系统上使用。它可以用于编写Modbus主机和从机应用程序,并支持多个从机设备的读写操作。libmodbus库还提供了一些方便的工具,如modbus命令行工具和modbus服务器,用于测试和调试Modbus通信。由于其开源性质和跨平台支持,libmodbus成为了工业自动化领域中广泛使用的Modbus库之一。
i.MX9352开发板上已经设计了两个RS485接口且电磁兼容电路设计得很到位,还用了金升阳的芯片专门进行了隔离,很赞,我们这里通过移植libmodbus库到板子上,硬件上把两个485接口连起来,一主一从进行模拟实际工业上两个设备通过RS485走Modbus RTU协议进行通讯。
先从官网拉源码进行编译,这里我选择直接在板子编译,连接好网线后在板子上进行。
git clone https://github.com/stephane/libmodbus.git
cd libmodbus
./autogen.sh
./configure
make -j
sudo make install
这样我们libmodbus的环境就配好了,开始写代码测试板子的485接口,一个做主,一个做从。
host 主机
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "modbus/modbus.h"
#define SLAVE_NAME "/dev/ttyUSB3"
unsigned short dest[256] = {0x01, 0x02};
uint8_t m_bits = 0, m_input_bits = 0;
int main()
{
modbus_t *ctx = modbus_new_rtu(SLAVE_NAME, 9600, 'N', 8, 1);
if (ctx == NULL)
{
fprintf(stderr, "%s", SLAVE_NAME);
return -1;
}
modbus_set_debug(ctx, 1);
modbus_set_response_timeout(ctx, 0, 1000000);
modbus_set_slave(ctx, 1);
if (modbus_connect(ctx) == 1)
{
fprintf(stderr, "connection failed!\n");
}
modbus_mapping_t *map = modbus_mapping_new_start_address(0, 1, 0, 1, 0, 0x10, 0, 0); //
if (map == NULL)
{
fprintf(stderr, "Failed to allocate the mapping\n");
return -1;
}
map->tab_registers = dest;
map->tab_bits = &m_bits;
map->tab_input_bits = &m_input_bits;
while(1)
{
uint8_t query[256];
int rc = modbus_receive(ctx, query);
int header_length = modbus_get_header_length(ctx);
query[0] = modbus_get_slave(ctx);
if (rc > 0)
{
modbus_reply(ctx, query, rc, map);
}
else
{
modbus_flush(ctx);
fprintf(stderr, "ctx_host:Failed to modbus_receive\n");
}
usleep(50000);
}
return 0;
}
slave从机读取
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "modbus/modbus.h"
#define SLAVE_NAME "/dev/ttyUSB0"
unsigned short dest[256] = {0};
int main()
{
modbus_t *ctx = modbus_new_rtu(SLAVE_NAME, 9600, 'N', 8, 1);
if (ctx == NULL)
{
fprintf(stderr, "%s", SLAVE_NAME);
return -1;
}
modbus_set_debug(ctx, 1);
modbus_set_response_timeout(ctx, 0, 1000000);
modbus_set_slave(ctx, 1);
if (modbus_connect(ctx) == 1)
{
fprintf(stderr, "connection failed!\n");
}
while(1)
{
if (modbus_read_registers(ctx, 0x0001, 1, dest) == -1)
{
fprintf(stderr, "read error!\n");
}
else
{
modbus_flush(ctx);
}
usleep(300000);
}
return 0;
}
简单的Makefile
all:
gcc src/slave.c -o slave -lmodbus
gcc src/host.c -o host -lmodbus
编译后执行的效果
如果执行的时候提示没有找到库但已经安装好了,可以ldd查看一下执行程序缺少了哪个,似乎是因为板子没有配置LD_LIBRARY_PATH
的原因,可以参考一下这个进行配置
这个错误消息表明您的程序无法找到libmodbus.so.5共享库文件。这可能是由于该库未安装或未正确配置导致的。
要解决这个问题,您可以尝试以下步骤:
sudo find / -name libmodbus.so.5
如果该库已安装,则命令将返回库文件的路径。如果该库未安装,则您需要安装它。
export LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH
请将"/path/to/lib"替换为libmodbus.so.5所在的目录。
ldd /path/to/your/program
请将"/path/to/your/program"替换为您的程序的路径。
如果您还有其他问题,请提供更多详细信息,以便我能够更好地帮助您解决问题。
上一下硬件连接图,直接A1连A2,B1连B2即可。
好了,这篇就到这里了。
更多回帖