一个改写Modebus心跳值的小程序

在某项目中,因为没有设置实际线边仓,我们在调试小车的时候添加了一个虚拟线边仓来模拟上下料,但是当小车到达线边仓上料或下料的时候,要手动给Modebus心跳的信号,非常麻烦。为了解决这个问题,郑工手写了一个程序,来控制虚拟线边仓的心跳,实现自动化操作。

下边给出代码:
mainwindow.h部分的代码:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>
#include <QModbusTcpClient>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void connectModbus(QString ip, int port);


public slots:
    void timeToPing();

private:
    Ui::MainWindow *ui;

    QTimer *timer;  //此处可以使用指针,也可以使用变量
    QModbusTcpClient *client;  //此处可以使用指针,也可以使用变量
    bool ping = false;
};
#endif // MAINWINDOW_H

下面是mainwindow.cpp部分的代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //
    timer = new QTimer;
    connect(timer, &QTimer::timeout, this, &MainWindow::timeToPing);  //用连接函数将定时器与timetoping改写心跳值函数连接起来
    timer->start(500);  //将定时器的间隔设置为500ms
    client = new QModbusTcpClient();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::connectModbus(QString ip, int port) //创建连接目标modbus的函数
{
    client->setConnectionParameter(QModbusDevice::NetworkPortParameter, port); //获取port
    client->setConnectionParameter(QModbusDevice::NetworkAddressParameter, ip);//获取IP
    client->connectDevice();//连接modbus
}

void MainWindow::timeToPing()
{
    //qDebug() << "time out!";
    connectModbus("127.0.0.1", 5502);//先连接目标modbus
    QVector<quint16> data;
    data << ping;
    QModbusDataUnit dataUnit(QModbusDataUnit::Coils, 1958, data);//此处控制目标盒子心跳的ID是1958
    client->sendWriteRequest(dataUnit, 1); //函数第二参数指的是读写coil的Slave ID,此处的ID是1
    ping = !ping;  //心跳的值不停地变为0或1
}

将该小程序打包:
找到运行该程序后的编译文件路径:
C:\Users\Maker\Documents\Qt Creator\build-autoPing-Desktop_Qt_5_14_2_MinGW_64_bit-Debug(这个是我电脑上的路径)

进入/debug可以看到有以下文件:
在这里插入图片描述
在这里新建一个文件夹/pack(我们将小程序打包到这个文件夹里面),将autoPing.exe文件拷贝进去,然后运行Qt 5.14.2(MinGW 7.3.0 64bit)在命令行中输入上面的pack文件夹所在的路径:
在这里插入图片描述
再输入windeployqt autoPing.exe:
在这里插入图片描述
到这里可以看到命令提示符窗口中有许多输出提示:
在这里插入图片描述
在这里插入图片描述
现在可以看到pack文件夹里已经有autoPing.exe的配置文件和相关库了。将autoPing.exe发送至桌面快捷方式,点击该快捷方式即可以运行程序。

以下是一个简单的 Modbus RTU 程序示例,使用 C 语言编写: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <termios.h> #include <unistd.h> // Modbus RTU 读保持寄存器指令 int modbus_read_holding_registers(int fd, int slave_addr, int start_addr, int count, unsigned char *buf) { unsigned char request[8]; unsigned char response[255]; int i, n, len; // 构造 Modbus RTU 读保持寄存器指令 request[0] = slave_addr; request[1] = 0x03; request[2] = (start_addr >> 8) & 0xFF; request[3] = start_addr & 0xFF; request[4] = (count >> 8) & 0xFF; request[5] = count & 0xFF; len = 6; // 计算 CRC 校验码 unsigned short crc = 0xFFFF; for (i = 0; i < len; i++) { crc ^= request[i]; for (n = 0; n < 8; n++) { if (crc & 0x0001) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } request[len++] = crc & 0xFF; request[len++] = (crc >> 8) & 0xFF; // 发送指令并接收响应 int ret = write(fd, request, len); if (ret != len) { perror("write failed"); return -1; } usleep(100000); ret = read(fd, response, 255); if (ret < 0) { perror("read failed"); return -1; } // 检查响应是否正确 if (response[0] != slave_addr || response[1] != 0x03 || response[2] != count * 2) { perror("response error"); return -1; } // 处理响应数据 memcpy(buf, response + 3, count * 2); return 0; } int main(int argc, char **argv) { int fd; struct termios options; // 打开串口 fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY); if (fd < 0) { perror("open failed"); return -1; } // 配置串口 tcgetattr(fd, &options); cfsetispeed(&options, B9600); cfsetospeed(&options, B9600); options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_cflag &= ~CRTSCTS; tcsetattr(fd, TCSANOW, &options); // 读保持寄存器 unsigned char buf[32]; int ret = modbus_read_holding_registers(fd, 1, 0, 16, buf); if (ret != 0) { perror("modbus read failed"); return -1; } // 打印读取结果 int i; for (i = 0; i < 16; i++) { printf("register %d: %d\n", i, buf[i]); } // 关闭串口 close(fd); return 0; } ``` 以上程序示例是一个简单的 Modbus RTU 读保持寄存器指令的实现,使用了 Linux 的串口编程接口。如果需要实现其他 Modbus RTU 指令,可以参考 Modbus RTU 协议文档进行编写。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值