Qt modbus使用详解

2023-11-05

不讲理论,只讲应用。看完这篇就能用起来,爽不爽!!!

具体内容目录如下,如需请订阅专栏后观看。

目录

一、Modbus协议通信过程

1.1 主机对从机写数据操作(0x06)

1.2 主机对从机读数据操作(0x03)

1.3 Modbus的CRC校验

二、在Qt中使用QModbus读写数据

2.1 部署准备——头文件中(.h)

2.2 部署准备——cpp文件中

2.3 modbus的使用——写函数

2.4 modbus的使用——读数据

2.5 额外——涉及的数据类型说明


一、Modbus协议通信过程

Modbus能实现的功能较多,理解了如下2个操作,基本算掌握了Modbus 80%的使用了。在此基础上,能很快扩展到其他功能使用上。

1.1 主机对从机写数据操作(0x06)

这个功能的目的是:实现主机对从机 寄存器 的写入操作。

注意:是  主机   对    从机

说明:假如从机地址是  1,那么单片机接收到这串数据,根据CRC16进行校验判断数据是否正确,如果数据无误,就改变自己寄存器的值。

然后从机原封不动返回这句话,告诉主机通讯成功!!!

*****下面用 串口调试助手XCOM V2.0作为主机,Modbus Slave软件作为从机 ,通过串口数据监视软件AccessPort 捕获通讯中的数据,过程如下:

如下图所示,发送数据01 06 00 04 00 07 89 C9,接收到从机返回数据01 06 00 04 00 07 89 C9。说明通讯成功。

从串口数据监视软件AccessPort里也可以看出,如下图中红色框中所示,

对主机而言,发送01 06 00 04 00 07 89 C9后,接收了01 06 00 04 00 07 89 C9;

对从机而言,接收01 06 00 04 00 07 89 C9后,发送了01 06 00 04 00 07 89 C9。

1.2 主机对从机读数据操作(0x03)

这个功能的目的是:实现主机对从机 寄存器 的值的读操作。

注意:是  主机   对    从机

说明:假如从机地址是  1,那么单片机接收到这串数据,根据CRC16进行校验判断数据是否正确,如果数据无误,就发送相应的寄存器的值给主机!!!

注意:这里的数据字节个数,在主机下发数据那里可以变更,单位是不同的——对主机端,一个数据个数对应从机端两个字节的数据。

*****下面用 串口调试助手XCOM V2.0作为主机,Modbus Slave软件作为从机 ,通过串口数据监视软件AccessPort 捕获通讯中的数据,过程如下:

如下图所示,串口调试助手作为主机发送01 03 00 00 00 0A C5 CD,Modbus Slave作为从机,接收到主机的读信息后,发送01 03 14 78 67 00 00 00 05 00 00 00 00 00 00 00 06 00 00 00 00 00 08 80 AC作为回应。

主机端要求从从机0x01的寄存器0x0000开始读取10个数据;从机端接收到命令后,从寄存器0x0000,读取10个数据共20个字节,发送给主机。

从串口数据监视软件AccessPort里也可以看出,如下图中红色框中所示,

对主机而言,发送01 03 00 00 00 0A C5 CD后,接收了01 03 14 78 67 00 00 00 05 00 00 00 00 00 00 00 06 00 00 00 00 00 08 80 AC;

对从机而言,接收01 03 00 00 00 0A C5 CD后,发送了01 03 14 78 67 00 00 00 05 00 00 00 00 00 00 00 06 00 00 00 00 00 08 80 AC。

1.3 Modbus的CRC校验

Modbus的CRC校验使用的是CRC16,输出两个字节校验结果。这个过程了解即可,Qt自带算CRC的算法。

     

CRC16校验的查表法  C++算法如下:

//CRC16校验算法 系数表
uchar auchCRCHi[]=
{
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40
};

uchar auchCRCLo[] =
{
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
    0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
    0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
    0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
    0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
    0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
    0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
    0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
    0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
    0x40
};

//查表法:Modbus的16位CRC校验
uint ModbusTool::N_CRC16(uchar *updata,uint len)
{
    uchar uchCRCHi=0xff;
    uchar uchCRCLo=0xff;
    uint  uindex;
    while(len--)
    {
        uindex=uchCRCHi^*updata++;
        uchCRCHi=uchCRCLo^auchCRCHi[uindex];
        uchCRCLo=auchCRCLo[uindex];
    }
    return (uchCRCHi<<8|uchCRCLo);
}

二、在Qt中使用QModbus读写数据

我的软件环境作为参考,win7,win10下都可以。

2.1 部署准备——头文件中(.h)

需要包含如下头文件和QModbus类,至于定义Modbus对象,可以在头文件中,也可以在cpp中。

#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QModbusDataUnit>

class QModbusClient;
class QModbusReply;


//类中定义,我的类名叫ModbusTool
private:
    QModbusClient *modbustoolDevice;//Modbus对象

private slots:
    void readReady();//读下位机寄存器数据回调函数

public:
    void write2client(unsigned int regStartAddr,unsigned int number);//上位机向下位机的某个寄存器写入数据
    void readfromclient(unsigned int startAddress,int number);//从指定下位机寄存器处读取数据

2.2 部署准备——cpp文件中

定义modbus串口的打开和关闭函数

//当然,相应的.cpp和.h文件需要对应起来哈,别傻傻的不同的.h和.cpp中写入代码了

//再包含一个头文件
#include <QModbusRtuSerialMaster>

//实例化Modbus对象
modbustoolDevice = new QModbusRtuSerialMaster(this);


//连接串口,这里是一个按钮
void ModbusTool::on_modbus_connect_clicked()
{
    //判断modbus是否已经定义,没有则直接返回
    if (!modbustoolDevice)
        return;

    //判断modbus是否已经连接
    if (modbustoolDevice->state() != QModbusDevice::ConnectedState) {
        //如果没有连接,则先设置串口的名称,串口奇偶校验位,串口波特率,串口数据位,串口停止位
        modbustoolDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
                                                 ui->modbus_searialport_name->currentText());
        modbustoolDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
                                                 QSerialPort::EvenParity);
        modbustoolDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
                                                 ui->modbus_searialport_btl->currentText().toInt());
        modbustoolDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
                                                 QSerialPort::Data8);
        modbustoolDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
                                                 QSerialPort::OneStop);

        //再设置从机无响应时的动作
        modbustoolDevice->setTimeout(1000);//从设备回复信息的超时时间
        modbustoolDevice->setNumberOfRetries(2);//重复发送次数

        //开始连接串口,并判断连接状态
        if (!modbustoolDevice->connectDevice()) {
            //如果连接失败,提示
            statusBar()->showMessage(tr("连接失败: ") + modbustoolDevice->errorString(), 5000);
            //FlagGetStatus=0;//连接失败,停止定时刷新
            //ui->Status_SerialConnect->setStyleSheet("font-size:100px;border-radius:30px;\nbackground-color: red");
        }else{
            //如果连接成功,设置下面按钮的状态,同时给出提示
            ui->modbus_connect->setEnabled(false);
            ui->modbus_disconnect->setEnabled(true);
            ui->send_commander->setEnabled(true);

            statusBar()->showMessage(tr("连接成功!"), 5000);
            //FlagGetStatus=1;//连接成功,定时刷新
            //ui->Status_SerialConnect->setStyleSheet("font-size:100px;border-radius:30px;\nbackground-color: green");
        }
    } else {
        //如果已经连接,则关闭串口
        modbustoolDevice->disconnectDevice();
        //ui->Status_SerialConnect->setStyleSheet("font-size:100px;border-radius:30px;\nbackground-color: rgb(205, 205, 205)");
    }
}

//断开串口连接
void ModbusTool::on_modbus_disconnect_clicked()
{
    //关闭串口
    modbustoolDevice->disconnectDevice();
    //设置下面按钮的状态,同时给出提示
    ui->modbus_connect->setEnabled(true);
    ui->modbus_disconnect->setEnabled(false);
    ui->send_commander->setEnabled(false);
    statusBar()->showMessage(tr("断开连接成功!"), 5000);
}

2.3 modbus的使用——写函数

只需要这一个函数就能完成写操作,明确写入寄存器的起始地址,以及写入的数据,调用就能完成写操作。

/*
 * @FuncName   上位机向下位机的某个寄存器写入数据
 *
 * @Function   向指定下位机寄存器写入数据
 *
 * @param 参数a 下位机寄存器起始地址
 * @param 参数b 写入值
 *
 * @return 返回值无
 */
void ModbusTool::write2client(unsigned int regStartAddr,unsigned int number)
{
    //如果没有定义modbus串口,直接返回
    if (!modbustoolDevice)
    {
        statusBar()->showMessage(tr("Modbus通讯失败,请检查串口连接!"),5000);
        return;
    }

    //清除状态栏显示
    statusBar()->clearMessage();

    //从页面的输入框获取设备地址
    unsigned int serverAddress=ui->modbus_addr->text().toInt();
    if(serverAddress==0)
    {
        statusBar()->showMessage(tr("设备地址为空,写入失败!"),5000);
        return;
    }

    //定义Modbus的基本数据单元,这里设置了modbus为0x06写模式,寄存器地址,以及传输数据的大小
    //QModbusDataUnit::QModbusDataUnit(RegisterType type, int address, quint16 size)
    QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters,regStartAddr,1);//06
    //QModbusDataUnit writeUnit(QModbusDataUnit::Coils,regStartAddr,1);//05

    //传输的数据为0,写入数据单元,这里还在做数据准备
    //number = 0x08;
    //void QModbusDataUnit::setValue(int index, quint16 value)
    writeUnit.setValue(0,number);

    //发送Modbus格式的数据到从机地址为serverAddress的从机
    //sendWriteRequest(const QModbusDataUnit &write, int serverAddress)
    if (auto *reply = modbustoolDevice->sendWriteRequest(writeUnit, serverAddress)) {
        if (!reply->isFinished()) {
            //如果接收到响应信息
            connect(reply, &QModbusReply::finished, this, [this, reply]() {
                if (reply->error() == QModbusDevice::ProtocolError) {
                    //接收到的响应信息有协议错误,则更新状态栏,错误码
                    statusBar()->showMessage(tr("写入数据错误: %1 (Mobus exception: 0x%2)")
                                             .arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
                                             5000);
                } else if (reply->error() != QModbusDevice::NoError) {
                    //接收到的响应信息有其他错误,则更新状态栏,错误码
                    statusBar()->showMessage(tr("写入数据错误: %1 (code: 0x%2)").
                                             arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
                }else{
                    //接收到的响应信息没有任何问题,更新状态栏
                    //注意,注意,注意,注意,注意,注意:这里解析了回应的信息,具体方法如下。一般没必要
                    //获取响应信息的数据到modbus基本数据QModbusDataUnit
                    const QModbusDataUnit unit = reply->result();

                    //统计响应信息中数据的个数
                    QString showdata=tr("总数:%1 值为:").arg(unit.valueCount());

                    //依次展示响应信息中的数据
                    for (uint i = 0; i < unit.valueCount(); i++) {
                        const QString entry=tr("%1 ").arg(unit.value(i));
                        showdata=showdata+entry;
                    }
                    //显示在界面中
                    ui->recv_area->setText(showdata);
                }
                reply->deleteLater();
            });
        } else {
            //发送多次后,没有响应数据,停止发送,更新状态栏信息
            // broadcast replies return immediately
            reply->deleteLater();
        }
    } else {
        //发送没有成功,更新状态栏信息
        statusBar()->showMessage(tr("写入数据错误: ") + modbustoolDevice->errorString(), 5000);
    }
}

2.4 modbus的使用——读数据

读操作包含两个函数。一个是发送读数据命令的函数,一个是处理读取的数据的函数。

/*
 * @FuncName   函数名:从指定下位机寄存器处读取数据
 *
 * @Function   功能:读取下位机数据
 *
 * @param 参数a 下位机寄存器起始地址
 *
 * @return 返回值无
 */
void ModbusTool::readfromclient(unsigned int startAddress,int number)
{
    //如果没有定义modbus串口,直接返回
    if (!modbustoolDevice)
        return;
    //    ui->readValue->clear();
    //清空状态栏的显示
    statusBar()->clearMessage();

    //定义Modbus的基本数据单元,这里设置了modbus为0x03读模式,寄存器地址,以及传输数据的大小
    //QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters,startAddress,num);
    QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters,startAddress,number);

    //发送Modbus格式的数据到从机地址为serverAddress的从机,读取相应的数据
    //if(auto* reply = Master->sendReadRequest(readUnit,ServerAddress))
    //获取设备地址
    unsigned int serverAddress=ui->modbus_addr->text().toInt();
    if (auto *reply = modbustoolDevice->sendReadRequest(readUnit, serverAddress)) {
        if (!reply->isFinished())
            //如果有响应信息了,进入readReady函数处理接收到的数据
            connect(reply, &QModbusReply::finished, this, &ModbusTool::readReady);
        else
            //如果多次发送后没有响应,结束
            delete reply; // broadcast replies return immediately
    } else {
        //如果发送失败,更新状态栏信息
        statusBar()->showMessage(tr("读取失败: ") + modbustoolDevice->errorString(), 5000);
    }
}

/*
 * @FuncName   函数名:读下位机寄存器数据回调函数
 *
 * @Function   功能:解析下位机上传的数据
 *
 * @param 参数无
 *
 * @return 返回值无
 */
void ModbusTool::readReady()
{
    auto reply = qobject_cast<QModbusReply *>(sender());
    //如果没有响应数据,直接返回
    if (!reply)
        return;

    if (reply->error() == QModbusDevice::NoError) {
        //如果响应数据校验后,没有错误。解析数据
        const QModbusDataUnit unit = reply->result();

        QString showdata=tr("总数:%1 值为:").arg(unit.valueCount());

        for (uint i = 0; i < unit.valueCount(); i++) {
            const QString entry=tr("%1 ").arg(unit.value(i));
            showdata=showdata+entry;
        }

        ui->recv_area->setText(showdata);

    } else if (reply->error() == QModbusDevice::ProtocolError) {
        //如果响应数据校验后,有协议错误,更新状态栏显示错误码
        statusBar()->showMessage(tr("读取回应错误: %1 (Mobus exception: 0x%2)").
                                 arg(reply->errorString()).
                                 arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
    } else {
        //如果响应数据校验后,有错误,更新状态栏显示错误码
        statusBar()->showMessage(tr("读取回应错误: %1 (code: 0x%2)").
                                 arg(reply->errorString()).
                                 arg(reply->error(), -1, 16), 5000);
    }

    //结束响应过程
    reply->deleteLater();
}

2.5 额外——涉及的数据类型说明

const QModbusDataUnit unit = reply->result();

这个代表接收到的响应信息的数据部分。

使用unit.value(i)依次读取就能得到各个数据。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt modbus使用详解 的相关文章

随机推荐

  • Linux服务器wget:unable to resolve host address解决方法

    Linux服务器wget unable to resolve host address解决方法 问题 今天使用虚拟机安装linux系统镜像使用的是CentOS 在一切都准备好的时候 想要去安装Redis时碰到了wget unable to
  • 自定义九宫格控件NineGridLayout ,实现微信朋友圈图片九宫格显示

    前言 很多时候我们都在刷微博或者微信朋友圈的时候都会看到很多图片 而这些图片的显示跟我们平时很多控件的显示方式都不一样 而且 当我们仔细去观察后就会发现 他加载的图片都是根据图片数量动态加载的 根据不同的图片数量来用不同的布局显示 如下图
  • 硬件防火墙和软件防火墙的区别有哪些?

    什么是防火墙 防火墙 指由软件和硬件设备组合而成 在内部网和外部网之间 局域网与外网之间的保护屏障 就像架起了一面墙 它能使网络之间建立起一个安全网关 从而保护内部网免受非法用户的侵入 熟悉互联网的朋友一定对防火墙不陌生 不管是电脑自带的防
  • OBJ格式简单用法

    参考 https www cnblogs com hont p 5239725 html https zhuanlan zhihu com p 342244212 http zwqxin com archives opengl obj mo
  • ceph-deploy命令应用

    记录 336 场景 在CentOS 7 9操作系统上 使用ceph deploy创建ceph集群 部署集群的mon mgr mds osd rgw等组件 版本 操作系统 CentOS 7 9 ceph版本 ceph 13 2 10 名词 c
  • Flask简单调用Redis、MySQL和生成token及token验证

    项目地址 https github com MasonYyp myflask 1 安装python基础环境 安装flask pip install flask 安装redis pip install redis 安装操作MySQL的包 pi
  • 如家酒店房价爬虫

    爬取地址 http m homeinns com hotels J10013 如家精选 北京中关村东路店 首先 从chrome浏览器打开F12审查元素 价格是用背景图片形式展现的 我们先获取背景图片 图片url 图片地址为 http m h
  • Java 基础入门篇(五):面向对象编程

    文章目录 一 面向对象的思想 二 类的定义与对象的创建 三 对象内存分配情况 3 1 两个对象的内存图 3 2 两个变量指向同一个对象内存图 四 构造器 4 1 构造器的格式与分类 4 2 构造器的调用 五 this 关键字 六 封装 七
  • springboot整合shiro(新手教程)

    咱们也就不多哔哔 直接开始 我先放我自己写的项目结构 第一步 想啥了 肯定是先创建一个springboot的项目 第二步 配置pom文件
  • vue3.0新增和删除的内容

    新增组件
  • 关于解决构建maven项目中报错:Failed to execute goal org.apache.maven.pluginsmaven-archetype-plugin

    1 首先进入仓库下面repositoryorgapachemavenplugins这个目录 2 删除目录下的maven archetype plugin文件夹 3 重新加载
  • Streamlit 讲解专栏(十):数据可视化-图表绘制详解(上)

    文章目录 1 前言 2 st line chart 绘制线状图 3 st area chart 绘制面积图 4 st bar chart 绘制柱状图 5 st pyplot 绘制自定义图表 6 结语 1 前言 在数据可视化的世界中 绘制清晰
  • 2022国赛15:Windows——文件共享

    试题内容 四 文件共享 任务描述 为了使局域网中的特定用户 能够访问共享文件夹内的 特定资源 请采用文件共享 实现共享资源的安全访问 1 在 windows1 创建用户主目录共享文件夹 本地目录为 D share home 共享名为 hom
  • React请求数据渲染页面

    1 使用react fetch数据发送请求 1 get方法 componentDidMount fetch url then res gt res json then json gt this setState list json 2 po
  • npm、pnpm、yarn的常用命令

    npm pnpm yarn的常用命令 文章目录 npm pnpm yarn的常用命令 一 常用命令 1 npm命令 2 pnpm命令 3 yarn命令 二 对比 一 常用命令 1 npm命令 npm init 初始化一个新的npm包 npm
  • 第12章 图形用户界面基础

    1 Swing和AWT的不同 AWT适合开发简单的图形用户界面 但不适合开发复杂的GUI项目 也容易发生于特定平台相关的故障 重量级组件 SWing更稳定 更通用 更灵活 不依赖于自己GUI 轻量级组件 SWing GUI组件类都以字母J为
  • EasyCHM编译的文件在点击节点时出现错误:确保Web地址//ieframe.dll/dnserrordiagoff.htm#正确

    EasyCHM编译后的文件打开时出现错误提示 解决方案 一 mht文件的文件名及路径中不能包含中文 二 修改节点的属性 检查路径是否正确
  • zookeeper

    1 zookeeper是什么 参考文献 Zookeeper可以干什么 zookeeper为分布式应用程序提供一致性协调服务 包括配置维护 域名服务 分布式锁 集群管理等 配置维护 同一个应用程序在不同服务器上的配置信息相同 将应用程序的配置
  • Android集成bilibili播放器以及弹幕

    考虑到开发直播和视频播放的必要性 网上了解到b站开源播放器 https github com bilibili ijkplayer 好用 集成下试试 运行后发现b站原生的只能播放没有其他选项 考虑到方便性 采用这个方案 https gith
  • Qt modbus使用详解

    不讲理论 只讲应用 看完这篇就能用起来 爽不爽 具体内容目录如下 如需请订阅专栏后观看 目录 一 Modbus协议通信过程 1 1 主机对从机写数据操作 0x06 1 2 主机对从机读数据操作 0x03 1 3 Modbus的CRC校验 二