Modbus协议简介:
在工业自动化领域,Modbus协议是一个应用层通讯协议,它为电子设备之间的通信提供了一个常用的标准方法。Modbus协议最初由Modicon公司(现为施耐德电气的一部分)在1979年发明用于其可编程逻辑控制器(PLC),如今这个协议已经成为在各种工业电子设备中进行数据通讯的行业标准之一。
Modbus是一种简单、稳固并且成本效益高的协议,它支持可靠的数据传输,并且易于与不同类型的硬件和软件集成。该协议可以通过不同的物理层来实现通信,包括串行通讯(如RS-232、RS-485)和以太网TCP/IP。
Modbus协议主要包括两种模式:Modbus ASCII 和 Modbus RTU。这两种模式都是用于串行通讯,但在数据包的编码格式上有所不同。还有一个较新的变种被称为Modbus TCP/IP,它是专门为以太网通讯设计的。
使用Modbus协议时,通信是在一个主设备和多个从设备之间进行的。主设备负责发起请求,而从设备则响应这些请求。这些请求和响应包含了访问或修改从设备上的寄存器和线圈的指令。
Modbus协议以其开放性、简单性以及广泛的应用而著称,它在很多工业领域内扮演着关键的角色,特别是在监控和控制系统中。
本文主要实现Modbus协议的第2个模式: Modbus RTU。
先看这篇文章,写得很详细:
QT应用篇 四、window编译LibModbus库并用QT编写一个Modbus主机 手把手教学
编译好的LibModbus库可以在上面文章里下载,
1.以编译好的modbus链接如下:libmodbus-3.1.4-源码与已编译好的
文件目录如下:
2.也可以在我的链接里下载已配置好的文件:Qt-libmodus
Qt-libmodus文件目录如下:
3.为了在Qt Creator中创建新项目并嵌入C++代码,请执行以下步骤:
打开Qt Creator。
新建项目:
在菜单栏中选择 File > New File or Project…。
在弹出窗口中,选择 Non-Qt Project。
选择 Plain C++ Application 然后点击“选择…”。
输入项目名称和位置,然后点击“下一步”。
选择编译器套件,比如GCC或MSVC,然后点击“下一步”。
确认项目摘要信息,点击“完成”创建项目。
大家看完上面的那篇文章后,正确的目录如下:
.Pro工程的信息如下:
这三处信息如上图所示。
main.cpp完整代码如下:
#include <iostream>
#include <libmodbus/config.h>
#include <unistd.h>
#include<libmodbus/modbus.h>
// 配置参数
const int TIMER = 1; // 读取间隔时间(秒)
const int SERVER_ADDRESS = 1;
const int START_ADDRESS = 101;
const int START_ADDRESS_2 = 1;
const int QUANTITY = 100;
const int QUANTITY_2 = 4;
//const char *COM_PORT = "/dev/ttyS0"; // 示例的Linux串口设备文件
const char *COM_PORT = "COM8";
const int BAUD_RATE = 9600;
void modbus_master_rtu() {
// 创建Modbus RTU连接
modbus_t *ctx = modbus_new_rtu(COM_PORT, BAUD_RATE, 'N', 8, 1);
if (ctx == NULL) {
std::cerr << "Unable to create the libmodbus context" << std::endl;
return;
}
// 设置从站地址
modbus_set_slave(ctx, SERVER_ADDRESS);
// 建立连接
if (modbus_connect(ctx) == -1) {
std::cerr << "Connection failed: " << modbus_strerror(errno) << std::endl;
modbus_free(ctx);
return;
}
uint16_t tab_reg[QUANTITY];
uint16_t tab_reg_2[QUANTITY_2];
// 无限循环读取数据
while (true) {
// 读取第一组保持寄存器
int rc = modbus_read_registers(ctx, START_ADDRESS, QUANTITY, tab_reg);
// 读取第二组保持寄存器
int rc2 = modbus_read_registers(ctx, START_ADDRESS_2, QUANTITY_2, tab_reg_2);
// 处理读取结果
if (rc == QUANTITY) {
for (int i = 0; i < rc; i++) {
std::cout << tab_reg[i];
if (i < rc - 1) {
std::cout << ", ";
}
}
std::cout << std::endl;
} else {
std::cerr << "Error reading registers: " << modbus_strerror(errno) << std::endl;
}
if (rc2 == QUANTITY_2) {
for (int i = 0; i < rc2; i++) {
std::cout << tab_reg_2[i];
if (i < rc2 - 1) {
std::cout << ", ";
}
}
std::cout << std::endl;
} else {
std::cerr << "Error reading registers: " << modbus_strerror(errno) << std::endl;
}
// 暂停执行,等待下一轮读取
sleep(TIMER);
}
modbus_close(ctx);
modbus_free(ctx);
}
int main() {
modbus_master_rtu();
return 0;
}
上面的代码中的串口COM_PORT ,地址要根据自己的modbus协议要求进行修改。
最后提供我的源码工程,修改上述参数,可直接运行,省去配置modbus环境过程:链接源码工程文件-libmodbus-test
1.当串口线未连接电脑时,串口连接失败,运行结果如下:
2.当串口线连接电脑时,串口数据每秒输出到缓存,运行结果如下: