Qt+C++串口调试接收发送数据曲线图
程序示例精选
Qt+C++串口调试接收发送数据曲线图
如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助!
前言
这篇博客针对<<Qt+C++串口调试接收发送数据曲线图>>编写代码,代码整洁,规则,易读。 学习与应用推荐首选。
文章目录
一、所需工具软件
二、使用步骤
1. 引入库
2. 代码实现
3. 运行结果
三、在线协助
一、所需工具软件
1. VS, Qt
2. C++
二、使用步骤
1.引入库
#include <QAction>
#include <QCheckBox>
#include <QDragEnterEvent>
#include <QDebug>
#include <QLineEdit>
#include <QMenu>
#include <QMenuBar>
#include <QtSerialPort/QSerialPort>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QGroupBox>
#include <QTextBrowser>
#include <QtWidgets/QFileDialog>
#include <QTimer>
#include <QtCore/QSettings>
#include <QtCore/QProcess>
#include <QStatusBar>
#include <QSplitter>
#include <data/SerialReadWriter.h>
#include <data/TcpServerReadWriter.h>
#include <data/TcpClientReadWriter.h>
#include <QRadioButton>
#include <QButtonGroup>
#include <data/BridgeReadWriter.h>
#include <QMimeData>
#include <QtSerialPort/QSerialPortInfo>
#include <data/SerialBridgeReadWriter.h>
#include <utils/FileUtil.h>
#include <QTextCodec>
2. 代码实现
代码如下:
void MainWindow::openReadWriter() {if (_readWriter != nullptr) {_readWriter->close();delete _readWriter;_readWriter = nullptr;emit serialStateChanged(false);}bool result;if (readWriterButtonGroup->checkedButton() == serialRadioButton) {_serialType = SerialType::Normal;auto settings = new SerialSettings();settings->name = serialPortNameComboBox->currentText();settings->baudRate = serialPortBaudRateComboBox->currentText().toInt();settings->dataBits = (QSerialPort::DataBits) serialPortDataBitsComboBox->currentText().toInt();settings->stopBits = (QSerialPort::StopBits) serialPortStopBitsComboBox->currentData().toInt();settings->parity = (QSerialPort::Parity) serialPortParityComboBox->currentData().toInt();auto readWriter = new SerialReadWriter(this);readWriter->setSerialSettings(*settings);qDebug() << settings->name << settings->baudRate << settings->dataBits << settings->stopBits<< settings->parity;result = readWriter->open();if (!result) {showWarning(tr("消息"), tr("串口被占用或者不存在"));return;}_readWriter = readWriter;_serialType = SerialType::Normal;} else if (readWriterButtonGroup->checkedButton() == tcpServerRadioButton) {_serialType = SerialType::TcpServer;auto address = tcpAddressLineEdit->text();bool ok;auto port = tcpPortLineEdit->text().toInt(&ok);if (!ok) {showMessage("", tr("端口格式不正确"));return;}auto readWriter = new TcpServerReadWriter(this);readWriter->setAddress(address);readWriter->setPort(port);qDebug() << address << port;result = readWriter->open();if (!result) {showWarning("", tr("建立服务器失败"));return;}connect(readWriter, &TcpServerReadWriter::currentSocketChanged, this, &MainWindow::updateTcpClient);connect(readWriter, &TcpServerReadWriter::connectionClosed, this, &MainWindow::clearTcpClient);_readWriter = readWriter;} else if (readWriterButtonGroup->checkedButton() == tcpClientRadioButton) {_serialType = SerialType::TcpClient;auto address = tcpAddressLineEdit->text();bool ok;auto port = tcpPortLineEdit->text().toInt(&ok);if (!ok) {showMessage("", tr("端口格式不正确"));return;}auto readWriter = new TcpClientReadWriter(this);readWriter->setAddress(address);readWriter->setPort(port);qDebug() << address << port;result = readWriter->open();if (!result) {showError("", tr("连接服务器失败"));return;}_readWriter = readWriter;} else if (readWriterButtonGroup->checkedButton() == serialBridgeRadioButton) {_serialType = SerialType::SerialBridge;auto settings1 = new SerialSettings();settings1->name = serialPortNameComboBox->currentText();settings1->baudRate = serialPortBaudRateComboBox->currentText().toInt();settings1->dataBits = (QSerialPort::DataBits) serialPortDataBitsComboBox->currentText().toInt();settings1->stopBits = (QSerialPort::StopBits) serialPortStopBitsComboBox->currentData().toInt();settings1->parity = (QSerialPort::Parity) serialPortParityComboBox->currentData().toInt();auto settings2 = new SerialSettings();settings2->name = secondSerialPortNameComboBox->currentText();settings2->baudRate = secondSerialPortBaudRateComboBox->currentText().toInt();settings2->dataBits = (QSerialPort::DataBits) secondSerialPortDataBitsComboBox->currentText().toInt();settings2->stopBits = (QSerialPort::StopBits) secondSerialPortStopBitsComboBox->currentText().toInt();settings2->parity = (QSerialPort::Parity) secondSerialPortParityComboBox->currentText().toInt();auto readWriter = new SerialBridgeReadWriter(this);readWriter->setSettings(*settings1, *settings2);result = readWriter->open();if (!result) {showWarning(tr("消息"), QString(tr("串口被占用或者不存在,%1")).arg(readWriter->settingsText()));return;}connect(readWriter, &SerialBridgeReadWriter::serial1DataRead, [this](const QByteArray &data) {showSendData(data);});connect(readWriter, &SerialBridgeReadWriter::serial2DataRead, [this](const QByteArray &data) {showReadData(data);});_readWriter = readWriter;} else {_serialType = SerialType::Bridge;auto settings = new SerialSettings();settings->name = serialPortNameComboBox->currentText();settings->baudRate = serialPortBaudRateComboBox->currentText().toInt();settings->dataBits = (QSerialPort::DataBits) serialPortDataBitsComboBox->currentText().toInt();settings->stopBits = (QSerialPort::StopBits) serialPortStopBitsComboBox->currentData().toInt();settings->parity = (QSerialPort::Parity) serialPortParityComboBox->currentData().toInt();auto address = tcpAddressLineEdit->text();bool ok;auto port = tcpPortLineEdit->text().toInt(&ok);if (!ok) {showMessage("", tr("端口格式不正确"));return;}auto readWriter = new BridgeReadWriter(this);readWriter->setSettings(*settings, address, static_cast<qint16>(port));result = readWriter->open();if (!result) {showWarning(tr("消息"), tr("串口被占用或者不存在"));return;}connect(readWriter, &BridgeReadWriter::currentSocketChanged,this, &MainWindow::updateTcpClient);connect(readWriter, &BridgeReadWriter::connectionClosed,this, &MainWindow::clearTcpClient);connect(readWriter, &BridgeReadWriter::serialDataRead, [this](const QByteArray &data) {showSendData(data);});connect(readWriter, &BridgeReadWriter::tcpDataRead, [this](const QByteArray &data) {showReadData(data);});_readWriter = readWriter;}connect(_readWriter, &AbstractReadWriter::readyRead,this, &MainWindow::readData);emit serialStateChanged(result);
}void MainWindow::closeReadWriter() {stopAutoSend();if (_readWriter != nullptr) {_readWriter->close();delete _readWriter;_readWriter = nullptr;}emit serialStateChanged(false);
}void MainWindow::createConnect() {connect(readWriterButtonGroup, QOverload<QAbstractButton *, bool>::of(&QButtonGroup::buttonToggled),[=](QAbstractButton *button, bool checked) {if (checked && isReadWriterOpen()) {SerialType serialType;if (button == tcpServerRadioButton) {serialType = SerialType::TcpServer;} else if (button == tcpClientRadioButton) {serialType = SerialType::TcpClient;} else if (button == bridgeRadioButton) {serialType = SerialType::Bridge;} else {serialType = SerialType::Normal;}if (serialType != _serialType) {if (showWarning("", tr("串口配置已经改变,是否重新打开串口?"))) {openReadWriter();}}}});connect(this, &MainWindow::serialStateChanged, [this](bool isOpen) {setOpenButtonText(isOpen);QString stateText;if (isOpen) {stateText = QString(tr("串口打开成功,%1")).arg(_readWriter->settingsText());} else {stateText = QString(tr("串口关闭"));}skipSendCount = 0;updateStatusMessage(stateText);});connect(this, &MainWindow::readBytesChanged, this, &MainWindow::updateReadBytes);connect(this, &MainWindow::writeBytesChanged, this, &MainWindow::updateWriteBytes);connect(this, &MainWindow::currentWriteCountChanged, this, &MainWindow::updateCurrentWriteCount);connect(openSerialButton, &QPushButton::clicked, [=](bool value) {if (!isReadWriterOpen()) {openReadWriter();} else {closeReadWriter();}});connect(refreshSerialButton, &QPushButton::clicked, [=] {_dirty = true;updateSerialPortNames();});connect(saveReceiveDataButton, &QPushButton::clicked, this, &MainWindow::saveReceivedData);connect(clearReceiveDataButton, &QPushButton::clicked, this, &MainWindow::clearReceivedData);connect(saveSentDataButton, &QPushButton::clicked, this, &MainWindow::saveSentData);connect(clearSentDataButton, &QPushButton::clicked, this, &MainWindow::clearSentData);connect(autoSendCheckBox, &QCheckBox::clicked, [this] {autoSendTimer->stop();});connect(loopSendCheckBox, &QCheckBox::stateChanged, [this] {_loopSend = loopSendCheckBox->isChecked();});connect(resetLoopSendButton, &QPushButton::clicked, [this] {skipSendCount = 0;serialController->setCurrentCount(0);emit currentWriteCountChanged(0);});connect(currentSendCountLineEdit, &QLineEdit::editingFinished, [this] {bool ok;auto newCount = currentSendCountLineEdit->text().toInt(&ok);if (ok) {serialController->setCurrentCount(newCount);} else {currentSendCountLineEdit->setText(QString::number(serialController->getCurrentCount()));}});connect(sendLineButton, &QPushButton::clicked, [this] {if (!isReadWriterConnected()) {handlerSerialNotOpen();return;}if (autoSendState == AutoSendState::Sending) {stopAutoSend();} else {if (_dirty) {_dirty = false;_sendType = SendType::Line;updateSendData(hexCheckBox->isChecked(), sendTextEdit->toPlainText());updateSendType();}sendNextData();startAutoSendTimerIfNeed();}if (autoSendState == AutoSendState::Sending) {sendLineButton->setText(tr("停止"));} else {resetSendButtonText();}});connect(processTextButton, &QPushButton::clicked, [this] {openDataProcessDialog(sendTextEdit->toPlainText());});connect(clearTextButton, &QPushButton::clicked, [this]{sendTextEdit->clear();});connect(lineReturnButtonGroup, QOverload<QAbstractButton *, bool>::of(&QButtonGroup::buttonToggled),[=](QAbstractButton *button, bool checked) {if (checked) {if (button == sendRReturnLineButton) {lineReturn = QByteArray("\r");} else if (button == sendNReturnLineButton) {lineReturn = QByteArray("\n");} else {lineReturn = QByteArray("\r\n");}}});connect(autoSendTimer, &QTimer::timeout,[this] {sendNextData();});connect(hexCheckBox, &QCheckBox::stateChanged, [this] {this->_dirty = true;});connect(sendTextEdit, &QTextEdit::textChanged, [this] {this->_dirty = true;});
}void MainWindow::setOpenButtonText(bool isOpen) {if (isOpen) {openSerialButton->setText(tr("关闭"));} else {openSerialButton->setText("打开");}
}void MainWindow::createActions() {openAct = new QAction(tr("&打开(&O)"), this);openAct->setShortcut(QKeySequence::Open);openAct->setStatusTip(tr("打开一个文件"));connect(openAct, &QAction::triggered, this, &MainWindow::open);saveAct = new QAction(tr("&保存(&S)"), this);saveAct->setShortcut(QKeySequence::Save);saveAct->setStatusTip(tr("保存一个文件"));connect(saveAct, &QAction::triggered, this, &MainWindow::save);validateDataAct = new QAction(tr("计算校验(&E)"), this);validateDataAct->setShortcut(tr("Ctrl+E"));validateDataAct->setStatusTip(tr("计算数据校验值"));connect(validateDataAct, &QAction::triggered, this, &MainWindow::openDataValidator);convertDataAct = new QAction(tr("数据转换(&T)"));convertDataAct->setShortcut(tr("Ctrl+T"));convertDataAct->setStatusTip(tr("数据转换"));connect(convertDataAct, &QAction::triggered, this, &MainWindow::openConvertDataDialog);dataProcessAct = new QAction(tr("数据处理(&P)"));dataProcessAct->setShortcut(tr("Ctrl+P"));dataProcessAct->setStatusTip(tr("数据处理"));connect(dataProcessAct, &QAction::triggered, [this] {openDataProcessDialog("");});
}void MainWindow::createMenu() {fileMenu = menuBar()->addMenu(tr("文件(&F)"));fileMenu->addAction(openAct);fileMenu->addAction(saveAct);toolMenu = menuBar()->addMenu(tr("工具(&T)"));toolMenu->addAction(validateDataAct);toolMenu->addAction(convertDataAct);toolMenu->addAction(dataProcessAct);
}void MainWindow::open() {auto lastDir = runConfig->lastDir;QString fileName = QFileDialog::getOpenFileName(this, tr("打开数据文件"), lastDir, "");if (fileName.isEmpty()) {return;}QFile file(fileName);if (file.open(QIODevice::ReadOnly)) {runConfig->lastDir = getFileDir(fileName);auto data = file.readAll();sendTextEdit->setText(QString::fromLocal8Bit(data));}
}void MainWindow::save() {saveReceivedData();
}void MainWindow::openDataValidator() {CalculateCheckSumDialog dialog(this);dialog.setModal(true);dialog.exec();
}void MainWindow::openConvertDataDialog() {ConvertDataDialog dialog(this);dialog.setModal(true);dialog.exec();
}void MainWindow::openDataProcessDialog(const QString &text) {DataProcessDialog dialog(text, this);dialog.setModal(true);int result = dialog.exec();if (result == QDialog::Accepted) {sendTextEdit->setText(dialog.text());}
}void MainWindow::displayReceiveData(const QByteArray &data) {if (pauseReceiveCheckBox->isChecked()) {return;}static QString s;s.clear();if (addReceiveTimestampCheckBox->isChecked()) {s.append("[").append(getTimestamp()).append("] ");}if (!s.isEmpty()) {s.append(" ");}if (displayReceiveDataAsHexCheckBox->isChecked()) {s.append(dataToHex(data));} else {s.append(QString::fromLocal8Bit(data));}if (addLineReturnCheckBox->isChecked() || addReceiveTimestampCheckBox->isChecked()) {receiveDataBrowser->append(s);} else {auto text = receiveDataBrowser->toPlainText();text.append(s);receiveDataBrowser->setText(text);receiveDataBrowser->moveCursor(QTextCursor::End);}
}void MainWindow::displaySentData(const QByteArray &data) {if (displaySendDataAsHexCheckBox->isChecked()) {sendDataBrowser->append(dataToHex(data));} else {sendDataBrowser->append(QString::fromLocal8Bit(data));}
}void MainWindow::sendNextData() {if (isReadWriterConnected()) {if (skipSendCount > 0) {auto delay = skipSendCount * sendIntervalLineEdit->text().toInt();updateStatusMessage(QString("%1毫秒后发送下一行").arg(delay));skipSendCount--;return;}qDebug() << "sendNextData readEnd:" << serialController->readEnd() << "current:"<< serialController->getCurrentCount();if (!_loopSend && autoSendCheckBox->isChecked() && serialController->readEnd()) {serialController->setCurrentCount(0);stopAutoSend();return;}auto data = serialController->readNextFrame();if (data.isEmpty()) {updateStatusMessage(tr("空行,不发送"));if (autoSendCheckBox->isChecked()) {auto emptyDelay = emptyLineDelayLindEdit->text().toInt();auto sendInterval = sendIntervalLineEdit->text().toInt();if (emptyDelay > sendInterval) {skipSendCount = emptyDelay / sendInterval;if (emptyDelay % sendInterval != 0) {skipSendCount += 1;}skipSendCount--;updateStatusMessage(QString(tr("空行,%1毫秒后发送下一行")).arg(emptyDelay));}}emit currentWriteCountChanged(serialController->getCurrentCount());return;}writeData(data);if (sendLineReturnCheckBox->isChecked()) {writeData(lineReturn);}if (hexCheckBox->isChecked()) {updateStatusMessage(QString(tr("发送 %1")).arg(QString(dataToHex(data))));} else {updateStatusMessage(QString(tr("发送 %1")).arg(QString(data)));}emit currentWriteCountChanged(serialController->getCurrentCount());} else {handlerSerialNotOpen();}
}void MainWindow::updateSendData(bool isHex, const QString &text) {if (serialController != nullptr) {QStringList lines = getLines(text);QList<QByteArray> dataList;if (isHex) {for (auto &line :lines) {dataList << dataFromHex(line);}} else {for (auto &line:lines) {dataList << line.toLocal8Bit();}}serialController->setData(dataList);totalSendCount = serialController->getTotalCount();updateTotalSendCount(totalSendCount);}
}void MainWindow::readSettings() {qDebug() << "readSettings";updateSerialPortNames();QSettings settings("Zhou Jinlong", "Serial Wizard");settings.beginGroup("Basic");auto serialType = SerialType(settings.value("serial_type", static_cast<int >(SerialType::Normal)).toInt());if (serialType == SerialType::TcpServer) {tcpServerRadioButton->setChecked(true);} else if (serialType == SerialType::TcpClient) {tcpClientRadioButton->setChecked(true);} else if (serialType == SerialType::Bridge) {bridgeRadioButton->setChecked(true);} else if (serialType == SerialType::SerialBridge) {serialBridgeRadioButton->setChecked(true);} else {serialRadioButton->setChecked(true);}_serialType = serialType;settings.beginGroup("SerialSettings");auto nameIndex = settings.value("name", 0).toInt();auto baudRateIndex = settings.value("baud_rate", 5).toInt();auto dataBitsIndex = (QSerialPort::DataBits) settings.value("data_bits", 3).toInt();auto stopBitsIndex = (QSerialPort::StopBits) settings.value("stop_bits", 0).toInt();auto parityIndex = (QSerialPort::Parity) settings.value("parity", 0).toInt();auto sendText = settings.value("send_text", "").toString();auto maxCount = serialPortNameComboBox->maxCount();if (nameIndex > maxCount - 1) {nameIndex = 0;}serialPortNameComboBox->setCurrentIndex(nameIndex);serialPortBaudRateComboBox->setCurrentIndex(baudRateIndex);serialPortDataBitsComboBox->setCurrentIndex(dataBitsIndex);serialPortStopBitsComboBox->setCurrentIndex(stopBitsIndex);serialPortParityComboBox->setCurrentIndex(parityIndex);auto name2Index = settings.value("name2", 0).toInt();auto baudRate2Index = settings.value("baud_rate2", 5).toInt();auto dataBits2Index = (QSerialPort::DataBits) settings.value("data_bits2", 3).toInt();auto stopBits2Index = (QSerialPort::StopBits) settings.value("stop_bits2", 0).toInt();auto parity2Index = (QSerialPort::Parity) settings.value("parity2", 0).toInt();auto maxCount2 = serialPortNameComboBox->maxCount();if (name2Index > maxCount2 - 1) {name2Index = 0;}secondSerialPortNameComboBox->setCurrentIndex(name2Index);secondSerialPortBaudRateComboBox->setCurrentIndex(baudRate2Index);secondSerialPortDataBitsComboBox->setCurrentIndex(dataBits2Index);secondSerialPortStopBitsComboBox->setCurrentIndex(stopBits2Index);secondSerialPortParityComboBox->setCurrentIndex(parity2Index);settings.beginGroup("SerialReceiveSettings");auto addLineReturn = settings.value("add_line_return", true).toBool();auto displayReceiveDataAsHex = settings.value("display_receive_data_as_hex", false).toBool();auto addTimestamp = settings.value("add_timestamp", false).toBool();addLineReturnCheckBox->setChecked(addLineReturn);displayReceiveDataAsHexCheckBox->setChecked(displayReceiveDataAsHex);addReceiveTimestampCheckBox->setChecked(addTimestamp);settings.beginGroup("SerialSendSettings");auto sendAsHex = settings.value("send_as_hex", false).toBool();auto displaySendData = settings.value("display_send_data", false).toBool();auto displaySendDataAsHex = settings.value("display_send_data_as_hex", false).toBool();auto autoSend = settings.value("auto_send", false).toBool();auto autoSendInterval = settings.value("auto_send_interval", 100).toInt();auto emptyLineDelay = settings.value("empty_line_delay", 0).toInt();auto loopSend = settings.value("loop_send", false).toBool();hexCheckBox->setChecked(sendAsHex);displaySendDataCheckBox->setChecked(displaySendData);displaySendDataAsHexCheckBox->setChecked(displaySendDataAsHex);autoSendCheckBox->setChecked(autoSend);loopSendCheckBox->setChecked(loopSend);sendIntervalLineEdit->setText(QString::number(autoSendInterval));emptyLineDelayLindEdit->setText(QString::number(emptyLineDelay));auto sendLineReturn = settings.value("send_line_return", false).toBool();sendLineReturnCheckBox->setChecked(sendLineReturn);auto sendLineReturnType = LineReturn(settings.value("send_line_return_type", static_cast<int >(LineReturn::RN)).toInt());if (sendLineReturnType == LineReturn::R) {sendRReturnLineButton->setChecked(true);} else if (sendLineReturnType == LineReturn::N) {sendNReturnLineButton->setChecked(true);} else {sendRNLineReturnButton->setChecked(true);}settings.beginGroup("TcpSettings");auto ipList = getNetworkInterfaces();auto ipAddress = settings.value("tcp_address", "").toString();QString selectAddress = "";if (!ipAddress.isEmpty() && !ipList.isEmpty()) {auto found = false;for (const auto &ip:ipList) {if (getIpAddress(ip) == ipAddress) {selectAddress = ipAddress;found = true;break;}}if (!found) {selectAddress = getIpAddress(ipList.first());}}if (selectAddress.isEmpty()) {if (!ipList.isEmpty()) {do {for (const auto &ip:ipList) {if (ip.type() == QNetworkInterface::Wifi && !getIpAddress(ip).isEmpty()) {selectAddress = getIpAddress(ip);break;}}if (!selectAddress.isEmpty()) {break;}for (const auto &ip:ipList) {if (ip.type() == QNetworkInterface::Ethernet && !getIpAddress(ip).isEmpty()) {selectAddress = getIpAddress(ip);}}if (!selectAddress.isEmpty()) {break;}selectAddress = getIpAddress(ipList.first());} while (false);}}tcpAddressLineEdit->setText(selectAddress);auto tcpPort = settings.value("tcp_port").toInt();tcpPortLineEdit->setText(QString::number(tcpPort));sendTextEdit->setText(sendText);settings.beginGroup("RunConfig");auto lastDir = settings.value("last_dir", "").toString();auto lastFilePath = settings.value("last_file_path", "").toString();runConfig = new RunConfig;runConfig->lastDir = lastDir;runConfig->lastFilePath = lastFilePath;_loopSend = loopSend;serialController = new LineSerialController();updateSendType();
}
3. 运行结果

动画演示
三、在线协助:
如需安装运行环境或远程调试,见文章底部个人 QQ 名片,由专业技术人员远程协助!
1)远程安装运行环境,代码调试
2)Qt, C++, Python入门指导
3)界面美化
4)软件制作
当前文章连接:Python+Qt桌面端与网页端人工客服沟通工具_alicema1111的博客-CSDN博客
博主推荐文章:python人脸识别统计人数qt窗体-CSDN博客
博主推荐文章:Python Yolov5火焰烟雾识别源码分享-CSDN博客
Python OpenCV识别行人入口进出人数统计_python识别人数-CSDN博客
个人博客主页:alicema1111的博客_CSDN博客-Python,C++,网页领域博主
博主所有文章点这里:alicema1111的博客_CSDN博客-Python,C++,网页领域博主
相关文章:
Qt+C++串口调试接收发送数据曲线图
程序示例精选 QtC串口调试接收发送数据曲线图 如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助! 前言 这篇博客针对<<QtC串口调试接收发送数据曲线图>>编写代码,代码整洁,规则&…...
【从零学习python 】75. TCP协议:可靠的面向连接的传输层通信协议
文章目录 TCP协议TCP通信的三个步骤TCP特点TCP与UDP的区别TCP通信模型进阶案例 TCP协议 TCP协议,传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议…...
IPv4 基础概念
IPv4 基础概念 IPv4 广播地址 广播是一种通信方式,用于将数据包发送到同一网络中的所有设备。在广播中,数据包被发送到特殊的广播地址,例如在IPv4中,广播地址通常为特定子网的广播地址(例如,192.168.1.0/…...
stm32片内读写项目总结(多字节读写tongxindu)
1.flash操作驱动程序 a头文件 #ifndef FLASH_H #define FLASH_H #include “stm32f4xx.h” #define BOARD_NUM_ADDR 0x0800C000 #define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址 #define FLASH_WAITETIME 50000 //FLASH等待超时时间 //FLASH 扇区的起始地址…...
ECMAScript6 简介及拓展
ECMAScript简介 JavaScript是大家所了解的语言名称, 但它的正式名称叫做ECMAScript。 1996年11月, JavaScript的创造者网景公司将JavaScript提交给国际化组织 ECMA(欧洲计算机制造联合会), 希望这种语言能够成为国际标准。 随后 ECMA 发布…...
可视化构建包分析报告
一、webpack 使用 webpack-bundle-analyzer 插件即可。 安装:npm install webpack-bundle-analyzer -D 使用:new BundleAnalyzerPlugin(options?: object) Name Type Description analyzerMode One of: server, static, json, disabled Default: se…...
统一git使用方法,git状态变迁图,git commit提交规范
目录 说明 统一git使用方法 git状态变迁图 git commit 提交规范 说明 多次工作中多名员工不懂git多次技术分享,自行查资料学习git并使用,会出现使用各种偏僻的命令,异常问题无法解决;或出现带url的git合并提交。主要是学的不…...
react与vue的区别
React和Vue.js是两个流行的JavaScript库/框架,用于构建用户界面。以下是React和Vue之间的一些主要区别: 学习曲线:Vue.js对于新手来说比React更容易学习和上手。 构建方式:React强调组件的可重用性,而Vue.js更注重模板…...
成功解决SQL 错误 [22000]: 第3 行附近出现错误: 试图修改自增列[ID](达梦数据库)
当我们使用工具来手动修改自增列的自增ID时,可能会报如下异常 SQL 错误 [22000]: 第3 行附近出现错误:试图修改自增列[ID] 解决办法: 可以使用SQL语句来修改 ALTER TABLE "fdw"."SYSTEM_DICT_TYPE" DROP IDENTITY; UPDATE "f…...
【算法】活用双指针完成复写零操作
Problem: 1089. 复写零 文章目录 题目解析算法原理分析找到最后一个复写的位置从后往前进行复写操作 代码展示 题目解析 首先我们来分析一下本题的题目意思 可以看到题目中给到了一个数组,意思是让我们将数组中的零元素都复写一遍,然后将其余的元素向后平…...
【面试高频题】难度 3/5,字典树热门运用题
题目描述 这是 LeetCode 上的 「745. 前缀和后缀搜索」 ,难度为 「困难」。 Tag : 「字典树」 设计一个包含一些单词的特殊词典,并能够通过前缀和后缀来检索单词。 实现 WordFilter 类: WordFilter(string[] words) 使用词典中的单词 words 初…...
vue base64图片转file流 下载到本地 或者上传
<img :src"data:image/png;base64,form.img" style"max-width:280px;max-height: 280px;margin: auto;" />// base64 转file const base64ToFile()>{let byImg atob(form.img); // 解码base64let n byImg.lengthlet a new Uint8Array(n);while…...
无涯教程-PHP - 简介
PHP 7是最期待的,它是PHP编程语言的主要功能版本。 PHP 7于2015年12月3日发布。本教程将以简单直观的方式教您PHP 7的新功能及其用法。 无涯教程假设您已经了解旧版本的PHP,现在就可以开始学习PHP 7的新功能。 使用下面的示例- <html><head&…...
web基础+HTTP协议+httpd详细配置
目目录录 一、Web基础1.1 HTML概述1.1.1 HTML的文件结构1.1.2 HTML中的部分基本标签 1.3 MIME1.4 URI 和 URL1.4 定义1.4.2 URI 和 URL 的区别 二、静态资源和动态资源2.1 静态资源2.2 动态资源 三、HTTP协议3.1 HTTP协议简介3.2 HTTP协议版本3.2 HTTP方法3.3 HTTP请求访问的完…...
【sql】MongoDB的增删改查分页条件等
【sql】MongoDB的增删改查分页条件等 //增 //新增数据2种方式 db.msg.save({"name":"springboot😀"}); db.msg.insert({"name":"mango good"}); db.msg.save({"name":"springboot",type:"工具书&…...
我的动态归纳(便于搜索)
linux dns配置文件是“/etc/resolv.conf”,该配置文件用于配置DNS客户,它包含了主机的域名搜索顺序和DNS/服务器的地址,每一行包括一个关键字和一个或多个空格隔开的参数。 /etc/resolv.conf (不配置就不能域名解析) 可…...
langchain ChatGPT AI私有知识库
企业知识库 原理就是把文档变为向量数据库,然后搜索向量数据库,把相似的数据和问题作为prompt, 输入到大模型,再利用GPT强大的自然语言处理、推理和分析等方面的能力将答案返回给用户 什么是langchain? langchain是一个强大的…...
API接口常用数据格式Json,Json的定义和XML的区别
现在程序员还有谁不知道 JSON 吗?无论对于前端还是后端,JSON 都是一种常见的数据格式。那么 JSON 到底是什么呢? JSON 的定义 JSON (JavaScript Object Notation) ,是一种轻量级的数据交换格式。它的使用…...
密码学学习笔记(二十一):SHA-256与HMAC、NMAC、KMAC
SHA-256 SHA-2是广泛应用的哈希函数,并且有不同的版本,这篇博客主要介绍SHA-256。 SHA-256算法满足了哈希函数的三个安全属性: 抗第一原像性 - 无法根据哈希函数的输出恢复其对应的输入。抗第二原像性 - 给定一个输入和它的哈希值…...
操作系统-笔记-第四章-文件管理
目录 四、第四章——文件管理 1、文件管理——基础概念 (1)文件结构 (2)操作系统提供的接口 (3)总结 2、文件的逻辑结构 (1)有结构文件(类似SQL表文件)…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
