Lado de Windows, prueba de PC libmodbus + Qt

Lado de Windows, prueba de PC libmodbus + Qt

Este artículo se basa en la realización de la comunicación Modbus en VS, y se han realizado algunas modificaciones simples en Qt para realizar la comunicación Modbus en Qt. (Se puede considerar una curva para salvar el país)

Pensamiento claro

Durante mucho tiempo, estoy un poco enredado en la comunicación entre Modbus-Master (lado maestro) y Modbus-Slave (lado esclavo) en cuanto a qué extremo se asigna al registro.
razón principal:

  • 1. Es porque no tengo claro el concepto de comunicación, tanto el lado del host como el lado del esclavo pueden transmitir datos, y ambos pueden asignar valores a los registros;
  • 2. En referencia a la información en Internet, la mayoría de las conexiones entre Master y Slave se establecen en el lado Qt, y la asignación se realiza en la herramienta Modbus Slave, lo que provoca malentendidos.

Notas de estudio de STM32 incrustado (8) -libmodbus + Qt prueba de computadora host
La función que se muestra en el texto es asignar valores a los registros en la herramienta Modbus Slave. Una vez que la conexión es exitosa, puede ver la transferencia de valor en la ventana de comando.
Pero en mi situación actual, Qt, como computadora host, debe pasar valores al extremo esclavo para lograr el efecto de enviar instrucciones. Así que necesito hacer algunos cambios en el código para que funcione para mí.

Idea de verificación

Antes de escribir el código, debe verificar la idea para ver si es razonable.Primero, use las herramientas auxiliares de Modbus.

Prueba de herramienta auxiliar Modbus

Tome prestadas herramientas auxiliares para establecer conexiones Modbus Poll y Modbus Slave, y luego use Modbus Poll para transmitir datos a Modbus Slave, y luego use Modbus Slave para transmitir datos a Modbus Poll.
1. Pase valores 0-9 de Modbus Poll a Modbus Slave, como se muestra en la Figura 1 a continuación.
Figura 1

Tx significa enviar, Rx significa recibir.
Modbus Poll envía primero 03 00 00 00 0A C5 CD
Modbus Slave recibe esta cadena de códigos,
Modbus Slave envía
03 14 00 00 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 CD 51
Modbus Recibido en la encuesta

Estoy un poco confundido acerca de este proceso, ¿por qué?
Hay un error en este software auxiliar. Envía directamente el valor a Modbus Slave durante el proceso de asignación de Modbus Poll. Esta prueba no explicó el problema.
2. Pase el valor 10-1 del extremo Modbus esclavo al extremo Modbus Poll, como se muestra en la Figura 2 a continuación.
Figura 2

De manera similar, Tx significa enviar y Rx significa recibir.
Modbus Poll envía primero 03 00 00 00 0A C5 CD
Modbus Slave recibe 03 00 00 00 0A C5 CD
Modbus Slave envía
03 14 00 0A 00 09 00 08 00 07 00 06 00 05 00 04 00 03 00 02 00 01 Se
recibió AD B5 Modbus Poll end

Ordenador host Qt como Modbus-Master

El Qt de la computadora superior se usa como Modbus-Master (lado del host), y en el lado del host, el registro se asigna mediante el método de asignación de muestreo aleatorio.
Pegue el código primero:
1.mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include <libmodbus/modbus.h>

#define ADDRESS_START 0
#define ADDRESS_END 9
#define LOOP  1

QT_BEGIN_NAMESPACE
namespace Ui {
    
     class myWidget; }
QT_END_NAMESPACE

class myWidget : public QWidget
{
    
    
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();

private:
    Ui::myWidget *ui;
    modbus_t *ctx;
    uint16_t *tab_reg;
    uint16_t *send_tab_reg;
    int nb;
    int addr;
    modbus_mapping_t *mb_mapping;
    int nb_fail;
    int nb_loop;
};
#endif // MYWIDGET_H

2.mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"

#include "libmodbus/modbus.h"
#include "QThread"
#include <QtDebug>
#include <errno.h>
#include <stdlib.h>
#include <malloc.h>


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

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


void myWidget::on_pushButton_clicked()
{
    
    
    int rc;
    int i;

    ctx = modbus_new_rtu("COM3", 115200, 'N', 8, 1);
    modbus_set_slave(ctx,1);

    modbus_set_debug(ctx,TRUE);

    if (modbus_connect(ctx)==-1)
        {
    
    
            fprintf(stderr, "Connection failed: %s\n",modbus_strerror(errno));
            modbus_free(ctx);
        }


        /*
        uint32_t old_response_to_sec;//秒
        uint32_t old_response_to_usec;//微秒,1秒=1,000,000微秒

        modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);//获取当前设置的超时

        modbus_set_response_timeout(ctx,0,50000);//设定超时,默认50ms(50,000us)
        qDebug()<<"get timeout sec:"<<old_response_to_sec;
        qDebug()<<"get timeout usec:"<<old_response_to_usec;



        printf("\n----------------\n");*/
        nb=ADDRESS_END-ADDRESS_START;

        tab_reg=(uint16_t *)malloc(nb * sizeof(uint16_t));
        memset(tab_reg,0,nb * sizeof(uint16_t));

        /*写入保持寄存器数值*/
        nb_loop=nb_fail=0;
        while(nb_loop++<LOOP)
        {
    
    
            for(addr=ADDRESS_START;addr<ADDRESS_END;addr++)
            {
    
    
                int i;
                for(i=0;i<nb;i++)
                {
    
    
                    tab_reg[i]=(uint16_t)(65535*rand()/(RAND_MAX+1.0));
                }
                nb=ADDRESS_END-addr;

                rc=modbus_write_register(ctx,addr,tab_reg[0]);
                if(rc !=1)
                {
    
    
                    printf("ERROR modbus_write_register(%d)\n",rc);
                    nb_fail++;
                }
                else
                {
    
    
                    rc = modbus_read_registers(ctx,addr,1, tab_reg); //03#读取保持寄存器的值,(对象,起始地址,读取数量,存储读取到的值)
                    if (rc != 1)
                    {
    
    
                        fprintf(stderr,"%s\n", modbus_strerror(errno));
                        qDebug()<<"rc错误"<<modbus_strerror(errno);
                        nb_fail++;
                    }
                    else
                    {
    
    
                        qDebug()<<"链接成功";
                        for (i=0; i<10; i++)
                        {
    
    
                            printf("reg[%d] = %d(0x%x)\n", i, tab_reg[i], tab_reg[i]);
                            qDebug()<<"rc收到:"<<tab_reg[i];
                        }
                     }

                 }

               }
        }
        modbus_close(ctx);  //关闭modbus连接
        modbus_free(ctx);   //释放modbus资源,使用完libmodbus需要释放掉
}




El efecto después de la ejecución es como se muestra en la figura siguiente:
imagen 3
puede ver que el valor asignado al registro se ha transferido a Modbus Slave, lo que indica que este código es válido en el extremo Modbus Master.
Además, al hacer esta prueba, espero utilizar la referencia de mis dos últimos artículos, incluida la edición de la biblioteca libmodbus y la simulación de comunicación modbus.
Referencia 1: Precauciones para usar libmodbus en Qt 5 en Windows
Referencia 2: Simulación de comunicación en modo modbus RTU basada en la biblioteca libmodbus en Visual Studio
Referencia 3: Notas de aprendizaje de STM32 integradas (8) -libmodbus + Qt PC test

Supongo que te gusta

Origin blog.csdn.net/qq_43552324/article/details/108714390
Recomendado
Clasificación