首页
统计
留言
投币
友链
关于
Search
1
抖音鸡汤(一)
15 阅读
2
扩展:268条PCB Layout设计规范!
7 阅读
3
新版Keilv5安装相关问题大全
7 阅读
4
Arduino库介绍——AccelStepper
6 阅读
5
Ubuntu系统——虚拟机ubuntu22.04没有网
3 阅读
基础
CPP语法
算法题
硬件设计
PCBLayout
电子设计
单片机
ESP32
STM32
STC51
Arduino
LuatOS
FreeRTOS
LVGL
Linux
QT
树莓派
T113S3
Linux系统
Linux应用开发
Linux驱动开发
IoT
MQTT
Lora
NB-IOT
米家
涂鸦
AI
OpenCV
项目
杂谈 | 日记
投资笔记
登录
Search
标签搜索
Arduino
ESP32
PCBLayout
鸡汤
ubuntu
步进电机
KEIL
CPP
QT
OTA
会焊工的程序猿
累计撰写
11
篇文章
累计收到
0
条评论
首页
栏目
基础
CPP语法
算法题
硬件设计
PCBLayout
电子设计
单片机
ESP32
STM32
STC51
Arduino
LuatOS
FreeRTOS
LVGL
Linux
QT
树莓派
T113S3
Linux系统
Linux应用开发
Linux驱动开发
IoT
MQTT
Lora
NB-IOT
米家
涂鸦
AI
OpenCV
项目
杂谈 | 日记
投资笔记
页面
统计
留言
投币
友链
关于
搜索到
11
篇与
的结果
2026-02-26
ubuntu虚拟机如何设置共享文件夹
ubuntu虚拟机如何设置共享文件夹Jtti_cc2025年11月17日 16:01在Ubuntu虚拟机中设置共享文件夹可以通过以下步骤完成,这里以VMware为例进行说明:创建共享文件夹在你的Windows主机上创建一个文件夹,这个文件夹将作为共享文件夹。在VMware虚拟机中,点击“编辑虚拟机设置”。选择“选项”标签页,然后选择“共享文件夹”。点击“添加”按钮,选择你在Windows主机上创建的文件夹。点击“下一步”,然后“完成”。安装VMware Tools在虚拟机中打开终端。安装VMware Tools。可以通过以下命令安装:sudo apt-get updatesudo apt-get install open-vm-tools安装完成后,重启虚拟机。挂载共享文件夹打开终端,输入以下命令挂载共享文件夹:sudo mkdir /mnt/hgfssudo /usr/bin/vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other -o uid=1000 -o gid=1000 -o umask=022如果挂载成功,你将在/mnt/hgfs目录下看到共享的文件夹。设置开机自动挂载使用文本编辑器打开/etc/fstab文件:sudo vim /etc/fstab在文件末尾添加以下行:.host:/ /mnt/hgfs fuse.vmhgfs-fuse allow_other,uid=1000,gid=1000,umask=022 0 0保存并退出编辑器,然后重启虚拟机。验证共享文件夹重启虚拟机后,打开终端并输入:vmhgfs-hgfsclient如果输出了共享文件夹的信息,说明挂载成功。注意事项确保在Windows主机和Ubuntu虚拟机中都没有中文和特殊字符命名的文件夹,以避免挂载问题。如果在挂载时遇到权限问题,可以尝试使用sudo umount /mnt/hgfs命令取消挂载,然后重新挂载。如果在/mnt/hgfs目录下没有看到共享文件夹,可能需要检查VMware Tools是否正确安装和配置。以上步骤可以帮助你在Ubuntu虚拟机中成功设置共享文件夹。如果在操作过程中遇到问题,可以参考相关的教程或向社区寻求帮助
2026年02月26日
1 阅读
0 评论
0 点赞
2026-02-02
QT开发入门笔记——北京迅为
1 QT工程1.1qt基础qt的移植性非常的强。一套代码我们不用改太多,直接通用所有的平台。不久的将来,qt会被用到MCU上,学习QT还是非常有意义的。1.2做一个简单的qt界面如何创建一个QT工程?步骤一:步骤二:不要有中文路径步骤三:工程文件分析:点击forms,然后双击ui文件,就可以进入ui编辑器。ui编辑器面板介绍:做一个简单的QQ登录界面,我们用到组件放图片,放文本,放gif图的组件就是 qlabel 放账号和密码的对话框我们用的组件是 qlinedit 按钮我们使用的组件是 qpushbutton1.3关联信号和槽自动关联:在ui界面里,右键点击对应的控件->转到槽自动关联会给我们的工程添加以下内容:槽函数只能声明到private slots或者public slots 下面。(QT特有)手动关联:使用connect这个函数。connect(ui->logoBt,SIGNAL(clicked()),this,SLOT(logoBt_clicked_slots())); connect(A,SIGNAL(B),C,SLOT(D));//当对象A发出B信号时候,就会触发对象C的槽函数D1.4添加图片图标下载网址: iconfont-阿里巴巴矢量图标库1、添加图片:右键项目名->添加新文件->Qt->Qt Resource FileResourrces文件夹下右键.qrc文件->Open with->资源编辑器-添加前缀(一般默认根文件)->Crtl+S 保存文件->添加文件 注意:记得保存!!!2、引用图片右击想要的控件->改变样式表->添加资源->border-image。可以添加多张照片。1.5添加新的页面右键项目名->添加新文件->Qt->Qt 设计师类界面->设置类名26、28行,创建类的对象。问题:在这个类下随意创建一个对象就是我们在编辑的ui界面void MainWindow::on_loginBt_clicked() { qDebug() << "loginBt_clicked"; QString ssid = ui->ssidEdit->text(); QString pwd = ui->pswdEdit->text(); if(ssid == "yyx" && pwd == "123")//判断密码 { ctrl* ct = new ctrl; ct->setGeometry(this->geometry());//读取窗口的高宽数据进行设置 ct->show();//显示跳转的页面 } } void ctrl::on_backBt_clicked() { this->close();//这句话就可以关闭本文件对应的界面 }2 QT三驾马车qt下的串口编程,网络编程(TCP UDP),操作GPIO3 串口编程3.1自制串口调试助手3.1.1串口调试助手界面设计做一个串口调试助手需要用到的组件如下接受框:属性选择:发送框:UI设计界面如下:3.1.2串口调试助手程序设计由于版本比较高,会出现字体大小不合适的情况,需要在吗main.cpp里添加一段代码#include "widget.h" #include <QApplication> #include <iconv.h> int main(int argc, char* argv[]) { if(QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))//判断QT版本 { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); } QApplication a(argc, argv); Widget w; w.setWindowTitle("阿轩串口调试助手 V1.0.0");//界面程序名称 w.show(); return a.exec(); }需要在xxx.pro文件里上serialport库,QT += core gui serialport界面操作代码#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QSerialPort> #include <QString> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget* parent = nullptr); ~Widget(); QSerialPort* serialPort = new QSerialPort(this); void serial_open_Bt_state();//串口打开时按钮盒选项的状态 void serial_close_Bt_state();//串口关闭时按钮盒选项的状态 private slots: void on_openBt_clicked(); void serialPortReadyRead_Slot(); void on_sendBt_clicked(); void on_clearBt_clicked(); void on_pushButton_1_clicked(); void on_pushButton_2_clicked(); void on_pushButton_3_clicked(); void on_pushButton_4_clicked(); void on_pushButton_5_clicked(); void on_pushButton_6_clicked(); void on_pushButton_7_clicked(); void on_pushButton_8_clicked(); void on_pushButton_9_clicked(); void on_pushButton_10_clicked(); void on_pushButton_11_clicked(); void on_pushButton_12_clicked(); void on_pushButton_13_clicked(); void on_pushButton_14_clicked(); void on_pushButton_15_clicked(); private: Ui::Widget* ui; }; #endif // WIDGET_H #include "widget.h" #include "ui_widget.h" #include <QSerialPortInfo> #include <QMessageBox> bool serial_state = false; Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); QStringList serialNamePort; foreach (const QSerialPortInfo& info, QSerialPortInfo::availablePorts())//自动检测端口 { serialNamePort << info.portName(); } ui->serialCb->addItems(serialNamePort);//自动检测到的端口输出给串口选择框 connect(serialPort, SIGNAL(readyRead()), this, SLOT(serialPortReadyRead_Slot()));//检测串口收到的数据 serial_close_Bt_state();//启动时默认是未打开 } Widget::~Widget() { delete ui; } //串口打开之后一些按钮状态需要改变 void Widget::serial_open_Bt_state() { ui->sendBt->setEnabled(true); ui->pushButton_1->setEnabled(true); ui->pushButton_2->setEnabled(true); ui->pushButton_3->setEnabled(true); ui->pushButton_4->setEnabled(true); ui->pushButton_5->setEnabled(true); ui->pushButton_6->setEnabled(true); ui->pushButton_7->setEnabled(true); ui->pushButton_8->setEnabled(true); ui->pushButton_9->setEnabled(true); ui->pushButton_10->setEnabled(true); ui->pushButton_11->setEnabled(true); ui->pushButton_12->setEnabled(true); ui->pushButton_13->setEnabled(true); ui->pushButton_14->setEnabled(true); ui->pushButton_15->setEnabled(true); ui->serialCb->setEnabled(false); ui->baundrateCb->setEnabled(false); ui->dataCb->setEnabled(false); ui->checkCb->setEnabled(false); ui->stopCb->setEnabled(false); } //串口关闭后一些按钮状态也需要改变 void Widget::serial_close_Bt_state() { ui->sendBt->setEnabled(false); ui->pushButton_1->setEnabled(false); ui->pushButton_2->setEnabled(false); ui->pushButton_3->setEnabled(false); ui->pushButton_4->setEnabled(false); ui->pushButton_5->setEnabled(false); ui->pushButton_6->setEnabled(false); ui->pushButton_7->setEnabled(false); ui->pushButton_8->setEnabled(false); ui->pushButton_9->setEnabled(false); ui->pushButton_10->setEnabled(false); ui->pushButton_11->setEnabled(false); ui->pushButton_12->setEnabled(false); ui->pushButton_13->setEnabled(false); ui->pushButton_14->setEnabled(false); ui->pushButton_15->setEnabled(false); ui->serialCb->setEnabled(true); ui->baundrateCb->setEnabled(true); ui->dataCb->setEnabled(true); ui->checkCb->setEnabled(true); ui->stopCb->setEnabled(true); } //读取串口发来的信息并显示 void Widget::serialPortReadyRead_Slot() { QString buf; buf = QString(serialPort->readAll()); ui->recvEdit->appendPlainText(buf); } //串口开关按钮 void Widget::on_openBt_clicked() { if(serial_state == false) { QSerialPort::BaudRate baudRate;//波特率 QSerialPort::DataBits dataBits;//数据位 QSerialPort::StopBits stopBits;//停止位 QSerialPort::Parity checkBits;//校验位 //读取选择的波特率 if(ui->baundrateCb->currentText() == "1200") { baudRate = QSerialPort::Baud1200; } else if(ui->baundrateCb->currentText() == "2400") { baudRate = QSerialPort::Baud2400; } else if(ui->baundrateCb->currentText() == "4800") { baudRate = QSerialPort::Baud4800; } else if(ui->baundrateCb->currentText() == "9600") { baudRate = QSerialPort::Baud9600; } else if(ui->baundrateCb->currentText() == "19200") { baudRate = QSerialPort::Baud19200; } else if(ui->baundrateCb->currentText() == "38400") { baudRate = QSerialPort::Baud38400; } else if(ui->baundrateCb->currentText() == "57600") { baudRate = QSerialPort::Baud57600; } else if(ui->baundrateCb->currentText() == "115200") { baudRate = QSerialPort::Baud115200; } //读取选择的数据位 if(ui->dataCb->currentText() == "5") { dataBits = QSerialPort::Data5; } else if(ui->dataCb->currentText() == "6") { dataBits = QSerialPort::Data6; } else if(ui->dataCb->currentText() == "7") { dataBits = QSerialPort::Data7; } else if(ui->dataCb->currentText() == "8") { dataBits = QSerialPort::Data8; } //读取选择的停止位 if(ui->stopCb->currentText() == "1") { stopBits = QSerialPort::OneStop; } else if(ui->stopCb->currentText() == "1.5") { stopBits = QSerialPort::OneAndHalfStop; } else if(ui->stopCb->currentText() == "2") { stopBits = QSerialPort::TwoStop; } //读取选择的效验位 if(ui->checkCb->currentText() == "none") { checkBits = QSerialPort::NoParity; } serialPort->setPortName(ui->serialCb->currentText());//设置串口号 serialPort->setBaudRate(baudRate);//设置波特率 serialPort->setDataBits(dataBits);//设置数据位 serialPort->setStopBits(stopBits);//设置停止位 serialPort->setParity(checkBits);//设置校验位 //打开并判断是否打开成功 if(serialPort->open(QIODevice::ReadWrite) == true) { //QMessageBox::information(this, "提示", "成功"); // ui->labelstate->setText("串口已打开");//弹窗 serial_state = true; serial_open_Bt_state(); ui->openBt->setText("关闭串口"); } else { QMessageBox::information(this, "提示", "失败"); } } else { serialPort->close(); // ui->labelstate->setText("串口关闭");//弹窗 serial_state = false; serial_close_Bt_state(); ui->openBt->setText("打开串口"); } } void Widget::on_sendBt_clicked() { serialPort->write(ui->sendEdit->text().toLocal8Bit().data());//转为QByteString类型字符串,并且再转换成char*发送,防止乱码 serialPort->write("\r\n"); } void Widget::on_clearBt_clicked() { ui->recvEdit->clear(); } void Widget::on_pushButton_1_clicked() { serialPort->write(ui->lineEdit_1->text().toLocal8Bit().data()); } void Widget::on_pushButton_2_clicked() { serialPort->write(ui->lineEdit_2->text().toLocal8Bit().data()); } void Widget::on_pushButton_3_clicked() { serialPort->write(ui->lineEdit_3->text().toLocal8Bit().data()); } void Widget::on_pushButton_4_clicked() { serialPort->write(ui->lineEdit_4->text().toLocal8Bit().data()); } void Widget::on_pushButton_5_clicked() { serialPort->write(ui->lineEdit_5->text().toLocal8Bit().data()); } void Widget::on_pushButton_6_clicked() { serialPort->write(ui->lineEdit_6->text().toLocal8Bit().data()); } void Widget::on_pushButton_7_clicked() { serialPort->write(ui->lineEdit_7->text().toLocal8Bit().data()); } void Widget::on_pushButton_8_clicked() { serialPort->write(ui->lineEdit_8->text().toLocal8Bit().data()); } void Widget::on_pushButton_9_clicked() { serialPort->write(ui->lineEdit_9->text().toLocal8Bit().data()); } void Widget::on_pushButton_10_clicked() { serialPort->write(ui->lineEdit_10->text().toLocal8Bit().data()); } void Widget::on_pushButton_11_clicked() { serialPort->write(ui->lineEdit_11->text().toLocal8Bit().data()); } void Widget::on_pushButton_12_clicked() { serialPort->write(ui->lineEdit_12->text().toLocal8Bit().data()); } void Widget::on_pushButton_13_clicked() { serialPort->write(ui->lineEdit_13->text().toLocal8Bit().data()); } void Widget::on_pushButton_14_clicked() { serialPort->write(ui->lineEdit_14->text().toLocal8Bit().data()); } void Widget::on_pushButton_15_clicked() { serialPort->write(ui->lineEdit_15->text().toLocal8Bit().data()); } 4 软件打包成windows可执行文件QT如何打包生成独立可执行.exe文件_qt打包成可执行程序-CSDN博客4.1我们把工厂切换到release模式,然后编译release模式:基本没有调试信息。debug模式:有很多调试信息。4.2改一下图标先把图标加到工程所在文件夹。然后在pro文件里面添加RC_ICONS=serial_iocn.ico注意:图标的格式必须为.ico这个格式的,其他格式不行。4.3封包操作4.3.1将QT程序使用Release编译**4.3.2新建一个文件夹,将Release编译生成的exe文件复制到新建文件夹中先找到Release编译生成的exe文件夹位置,与项目创建的文件夹有关: 临时文件夹 --》 release --》 xx .exe文件 比如我的这个就是在D:\QtPro\build-Serial-Desktop_Qt_5_12_9_MinGW_64_bit-Release\release 把exe文件拷贝出来 随便在哪创建一个空的文件夹,然后将.exe文件拷贝进去 比如我在E盘新建了QTtest文件夹 4.3.3使用命令终端添加程序所需的依赖库在开始菜单中找到Qt命令终端(版本可能不一样打开对应版本就行),进入刚才新建的文件夹目录,使用 windeployqt 对生成的exe 文件进行打配置动态库文件: 一般来说,打开命令行终端后默认是在QT的安装路径下,这样需要先把路径切过去到exe文件的路径下再使用 windeployqt 命令 + .exe文件名操作或者直接windeployqt + .exe文件绝对路径 这样就成功了,可以双击exe文件测试是否可以正常打开。 到这一步其实可以选择把整个文件夹打个压缩包,然后就可以发送到其他PC端使用了,只需解压缩即可。 如果还觉得麻烦,想只用一个exe文件就能独立工作,那就接着往下操作。4.4合并打包程序(下面的步骤只适用于Windows系统下)4.4.1安装Enigma virtual box工具Enigma Virtual Box是软件虚拟化工具,它可以将多个文件封装到应用程序主文件,从而制作成为单执行文件的绿色软件。它支持所有类型的文件格式,虚拟化后的软件不释放任何临时文件到您的硬盘,文件模拟过程仅在内存运行。Enigma virtual box官方链接:https://enigmaprotector.com/cn/downloads.html 进入官网后找到红框部分点击下载即可,不需要注册账号: 下载后点击安装,安装过程一直next就行,注意勾选创建桌面快捷方式,默认是不创建的。 安装好后打开可以设置中文语言: 4.4.2打开安装好的Enigma Virtual Box,点击浏览,找到第三步的目录下的exe文件4.4.3点击增加,选择递归添加文件,选中demo文件夹点击确定4.4.4选择目标文件夹后点击确定4.4.5点击文件选项,选中压缩文件,点击确定4.4.6最后点击执行封包,等待结束即可。4.4.7最终生成的文件名和路径,找到该文件双击打开测试是否正常至此整个打包过程结束5 网络编程(TCP UDP)QT的网络编程:网络编程有TCP和UDP。5.1TCP协议TCP编程需要用到俩个类:QTcpServer和QTcpSocket查找帮助可知都需要添加network5.1.1服务器设计#include "widget.h" #include "ui_widget.h" // 构造函数,初始化Widget对象 Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 设置UI tcpServer = new QTcpServer(this); // 创建一个新的QTcpServer对象 tcpSocket = new QTcpSocket(this); // 创建一个新的QTcpSocket对象 // 连接信号和槽,当有新的连接时调用newConnection_Slot槽函数 connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection_Slot())); } // 槽函数,当有新的连接时调用 void Widget::newConnection_Slot() { tcpSocket = tcpServer->nextPendingConnection(); // 获取下一个挂起的连接 // 连接信号和槽,当有数据可读时调用readyRead_Slot槽函数 connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); } // 槽函数,当有数据可读时调用 void Widget::readyRead_Slot() { // 将读取到的数据追加到recvTextEdit文本编辑器中 ui->recvTextEdit->appendPlainText(tcpSocket->readAll()); } // 析构函数,清理资源 Widget::~Widget() { delete ui; // 删除UI对象 } // 槽函数,当打开按钮被点击时调用 void Widget::on_openBt_clicked() { // 监听所有IP地址和端口,端口号从portEdit文本框中获取并转换为无符号整数 tcpServer->listen(QHostAddress::Any, ui->portEdit->text().toUInt()); } // 槽函数,当关闭按钮被点击时调用 void Widget::on_closeBt_clicked() { tcpServer->close(); // 关闭服务器 } // 槽函数,当发送按钮被点击时调用 void Widget::on_sendBt_clicked() { // 发送sendEdit文本框中的数据,数据转换为本地8位字节数组 // 发送前需要转换一下,转为QByteString类型字符串,并且再转换成char*发送,防止乱码 tcpSocket->write(ui->sendEdit->text().toLocal8Bit().data()); } 5.2.2客户端设计#include "widget.h" #include "ui_widget.h" // 构造函数,初始化Widget对象 Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 设置UI tcpSocket = new QTcpSocket(this); // 创建一个新的QTcpSocket对象 } // 析构函数,清理资源 Widget::~Widget() { delete ui; // 删除UI对象 } // 槽函数,当连接成功时调用 void Widget::connected_Slot() { // 连接信号和槽,当有数据可读时调用readyRead_Slot槽函数 connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); } // 槽函数,当有数据可读时调用 void Widget::readyRead_Slot() { // 将读取到的数据追加到recvTextEdit文本编辑器中 ui->recvTextEdit->appendPlainText(tcpSocket->readAll()); } // 槽函数,当打开按钮被点击时调用 void Widget::on_openBt_clicked() { // 连接到主机,IP地址和端口号分别从ipEdit和portEdit文本框中获取并转换 tcpSocket->connectToHost(ui->ipEdit->text(), ui->portEdit->text().toUInt()); // 连接信号和槽,当连接成功时调用connected_Slot槽函数 connect(tcpSocket, SIGNAL(connected()), this, SLOT(connected_Slot())); } // 槽函数,当关闭按钮被点击时调用 void Widget::on_closeBt_clicked() { tcpSocket->close(); // 关闭连接 } // 槽函数,当发送按钮被点击时调用 void Widget::on_sendBt_clicked() { // 发送sendEdit文本框中的数据,数据转换为本地8位字节数组 tcpSocket->write(ui->sendEdit->text().toLocal8Bit().data()); } 5.2UDP协议udp不分客户端和服务器,只需要使用一个类QUdpSocket#include "widget.h" #include "ui_widget.h" // 构造函数,初始化Widget对象 Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 设置UI udpSocket = new QUdpSocket(this); // 创建一个新的QUdpSocket对象 // 设置按钮的初始状态 ui->openBt->setEnabled(true); ui->closBt->setEnabled(false); ui->sendBt->setEnabled(false); } // 析构函数,清理资源 Widget::~Widget() { delete ui; // 删除UI对象 } // 槽函数,当有数据可读时调用 void Widget::readyRead_Slot() { while (udpSocket->hasPendingDatagrams()) // 当有挂起的数据报时 { QByteArray array; array.resize(udpSocket->pendingDatagramSize()); // 调整数组大小以适应数据报 udpSocket->readDatagram(array.data(), array.size()); // 读取数据报 QString buf = array.data(); // 将数据转换为QString ui->recvEdit->appendPlainText(buf); // 将数据追加到recvEdit文本编辑器中 } } // 槽函数,当打开按钮被点击时调用 void Widget::on_openBt_clicked() { // 绑定本地端口,成功则启用相关按钮 if(udpSocket->bind(ui->localPort->text().toUInt()) == true) { ui->openBt->setEnabled(false); ui->closBt->setEnabled(true); ui->sendBt->setEnabled(true); } // 连接信号和槽,当有数据可读时调用readyRead_Slot槽函数 connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readyRead_Slot())); } // 槽函数,当关闭按钮被点击时调用 void Widget::on_closBt_clicked() { udpSocket->close(); // 关闭UDP连接 // 重置按钮的状态 ui->openBt->setEnabled(true); ui->closBt->setEnabled(false); ui->sendBt->setEnabled(false); } // 槽函数,当发送按钮被点击时调用 void Widget::on_sendBt_clicked() { QHostAddress address; address.setAddress(ui->aimIp->text()); // 设置目标IP地址 quint16 port = ui->aimPort->text().toUInt(); // 获取目标端口号 QString sendbuff = ui->sendEdit->text(); // 获取发送数据 // 发送数据报 udpSocket->writeDatagram(sendbuff.toLocal8Bit().data(), sendbuff.length(), address, port); } 6 时间编程qtime:qt的时间类qtimer:qt的定时类#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); connect( & timer, SIGNAL(timeout()), this, SLOT(timeout_Slot())); time.setHMS(0, 0, 0, 0); ui->showTime->setText(time.toString("hh:mm:ss:zzz")); } Widget::~Widget() { delete ui; } void Widget::timeout_Slot() { //qDebug() << "timeout_Slot"; time = time.addMSecs(30); ui->showTime->setText(time.toString("hh:mm:ss:zzz")); } void Widget::on_starBt_clicked() { //timer.setSingleShot(true);//只计时一次 timer.start(30); } void Widget::on_closBt_clicked() { timer.stop(); } void Widget::on_resetBt_clicked() { timer.stop(); time.setHMS(0, 0, 0, 0); ui->showTime->setText(time.toString("hh:mm:ss:zzz")); } static int i = 0; void Widget::on_bitBt_clicked() { QString temp; i = i + 1; temp.sprintf("%d--->", i); ui->bitTime->append(temp); ui->bitTime->append(time.toString("hh:mm:ss:zzz")); } void Widget::on_clearBt_clicked() { ui->bitTime->clear(); i = 0; }
2026年02月02日
1 阅读
0 评论
0 点赞
2026-02-02
C++程序规范(一)—— 注释
1 代码文件头说明注释格式/** ********************************************************************** * @file Wiredevice.h * @author [作者名] * @version [版本号] * @date [编写或修改日期] * @brief [文件任务简介] * @license Copyright (c) 2020-2032, xxxx有限公司 ********************************************************************** * @attention * 修改历史 版本号 Author 修改内容 *-------------------------------------------------- * 2023.08.04 v01 [作者名] 创建文件 *-------------------------------------------------- * ********************************************************************** */2 函数说明注释格式/********************************************************************** * 函数名:LCD_GetFrameBuffer * 功能描述:获得LCD的Framebuffer * 输入参数:无 * 输出参数:pXres/pYres/pBpp - 用来保存分辨率、bpp * 返回值:Framebuffer首地址 * ----------------------------------------------- * 2023/08/31 V1.0 韦东山 创建 ***********************************************************************/
2026年02月02日
2 阅读
0 评论
0 点赞
2026-02-02
ESP32网络远程OTA升级
什么是OTA?OTA(Over-the-AirTechnology)即空中下载技术,是通过移动通信的空中接口实现对移动终端设备及SIM卡数据进行远程管理的技术。OTA升级是物联网(IOT)产品设计的一个非常重要的部分,能够实现智能设备系统漏洞修复、系统升级,通过固件和软件的升级,提供更好的服务。OTA固件升级功能不仅能够更新固件,而且还能重新配置芯片上硬件资源。同时,设备固件可通过OTA固件升级流程获得更新的补丁和更多安全算法防范病毒攻击。ESP32支持OTA,为什么要使用OTA?ESP32集成了2.4GHzWi-Fi和蓝牙双模,以其超高的射频性能、稳定性、通用性和可靠性,以及超低的功耗,满足不同的功耗需求,适用于各种物联网应用场景,受到低成本系统和制造商的欢迎。此外,使用ESP32 OTA还可以实现远程控制,即通过网络来远程控制设备。例如,我们可以通过网络将新的固件发送到设备,实现设备的远程升级。总之,使用OTA可以提高设备的维护效率,方便我们进行远程控制和升级。因此,ESP32支持OTA升级是非常有用的功能。如何在ESP32上实现OTA?通过http请求获取远程固件,实现升级,因此必须有一个固件的下载地址,本次示例是基于Arduino的 HTTPUpdate.h ,MQTT云平台使用的是巴法云的物联网平台服务。 该平台提供地址不变的最新版固件地址,且提供可追溯历史版本的固件地址,通过巴法物联网云平台示例源码示例源码主要分为 main.cpp和 dapensonOTA.hpp组成 ,使用到MQTT,因此添加 #include <PubSubClient.h>,github下载最新发行版即可。首先将示例代码烧录到开发板,串口打印消息记录版本号;下一步修改固件输出信息,并上传至巴法云OTA,从云端下发OTA升级指令触发升级操作。等待升级完成并串口打印比对修改过的固件输出信息,验证是否成功。/* Project: [巴法云mqtt灯控] Author: [Dapenson] Date: [2022-12-14] Description: [通过配置接入信息接入巴法云,并可通过巴法云的APP控制灯的开关和亮度,灯控使用pwm函数analogWrite()控制,输入on/off/on#亮度,] Revisions: [2022-12-14] - [添加on和off的判断,当打开on的时候,亮度默认为10%] [2022-12-14] - [新增OTA功能,需在wifi配置留下一个特定wifi,用于OTA升级,收到Dapenson-Update关键字后会自动升级,串口打印日志] ... */ #include <Arduino.h> #include <WiFi.h> #include <PubSubClient.h> #include "dapensonOTA.hpp" /***************** 函数声明 *************************/ void serialEvent(); void lightControl(int brightness); void mqttCallback(char *topic, byte *payload, unsigned int length); void connectWIFI(); void connectMQTT(); void setup(); void loop(); /***************** 全局变量 *************************/ #define LED_PIN 2 #define MQTT_SERVER "bemfa.com" // 定义MQTT服务器的地址 #define MQTT_PORT 9501 // 定义MQTT服务器的端口 #define MQTT_CLIENT_ID "f5c5108e75xxxxxxxx6ebbf2" // 定义客户端的ID=私钥 #define MQTT_USERNAME "myusername" // 定义用户名=任意 #define MQTT_PASSWORD "mypassword" // 定义密码= 任意 #define TOPIC_SUBSCRIBE "HLlight002" // 定义订阅的主题 // 定义多组Wi-Fi配置信息 const char *ssid[] = {"Hangxxxx", "cc", "c", "Dapenson"}; const char *password[] = {"1axxxx", "mmmmmxxxx", "187xxxx", "Dapenson"}; int brightness_tar = 0; // 定义目标亮度值,初始为灭 // 定义串口输入缓冲区大小 #define INPUT_BUFFER_SIZE 64 // 定义MQTT客户端对象 WiFiClient espClient; PubSubClient mqttClient(espClient); /***************** 函数定义 *************************/ // 定义灯控函数 void lightControl(int brightness) { // 限制频率和占空比在合理范围内 (1Hz - 10000Hz, 0% - 100%) // https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/peripherals/ledc.html#api brightness = constrain(brightness, 0, 100); int dutyCycle = map(brightness, 0, 100, 0, 255); analogWrite(LED_PIN, dutyCycle); Serial.printf("Set brightness to %d%%\n", brightness); } // 定义MQTT回调函数,用于处理从服务器接收到的消息 void mqttCallback(char *topic, byte *payload, unsigned int length) { // 将接收到的消息转换为字符串 char message[length + 1]; memcpy(message, payload, length); message[length + 1] = '\0'; Serial.printf("Message arrived [%s]%d: %s\n", topic, length, message); // 检测是否升级指令 if (strstr(message, "Dapenson-Update") != NULL) { updateBin(); // 执行升级函数,完成后直接重启 } brightness_tar = 0; if (strstr(message, "on") != NULL) { brightness_tar = 10; int dutyCycle = 0; // 如果成功解析出1个整数,则执行 if 语句中的代码。 if (sscanf(message, "on#%d", &dutyCycle) == 1) { // 将提取到的值赋值给目标值 brightness_tar = dutyCycle; } } // 调用灯控函数,设置灯的状态 lightControl(brightness_tar); } // 定义连接Wi-Fi函数 void connectWIFI() { // 连接Wi-Fi网络 bool connected = false; for (int i = 0; i < 3; i++) { int time_connect = 0; WiFi.begin(ssid[i], password[i]); while (WiFi.status() != WL_CONNECTED) { if (time_connect > 10) { time_connect = 0; break; } delay(1000); Serial.print("Connecting to WiFi..."); Serial.println(ssid[i]); time_connect++; } if (WiFi.status() == WL_CONNECTED) { connected = true; Serial.printf("Connected to %s , IP :%s\n", ssid[i], WiFi.localIP().toString().c_str()); break; } } // 如果没有连接到Wi-Fi网络,则输出错误信息 if (!connected) { Serial.println("Failed to connect to WiFi!"); delay(5000); ESP.restart(); } } // 连接MQTT服务器 void connectMQTT() { if (!mqttClient.connected()) { Serial.println("Connecting to MQTT server..."); if (mqttClient.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) { Serial.println("Connected to MQTT: " MQTT_SERVER); // 订阅主题 mqttClient.subscribe(TOPIC_SUBSCRIBE); Serial.println("subscribed to topic: " TOPIC_SUBSCRIBE); } } } void setup() { Serial.begin(115200); delay(100); getVersion(); // 获取版本号 // 初始化GPIO8引脚为输出模式 pinMode(LED_PIN, OUTPUT); // 将12、13引脚拉低 pinMode(12, OUTPUT); pinMode(13, OUTPUT); digitalWrite(12, LOW); digitalWrite(13, LOW); // 调用灯控函数,设置灯的状态 lightControl(brightness_tar); // 连接Wi-Fi connectWIFI(); // 设置MQTT服务器的地址和端口 mqttClient.setServer(MQTT_SERVER, MQTT_PORT); // 设置MQTT回调函数 mqttClient.setCallback(mqttCallback); } void loop() { delay(2); // 判断 WiFi 连接状态 if (WiFi.status() != WL_CONNECTED) { // 如果没有连接到 WiFi,则进行连接 connectWIFI(); } if (!mqttClient.connected()) { connectMQTT(); } // 处理MQTT消息 mqttClient.loop(); } // 串口0事件 void serialEvent() { // 检查串口是否有数据可读 if (Serial.available()) { // 定义串口输入缓冲区 char inputBuffer[INPUT_BUFFER_SIZE]; // 读取串口输入到缓冲区 Serial.readBytesUntil('\n', inputBuffer, INPUT_BUFFER_SIZE); // 提取占空比 int dutyCycle = 0; if (sscanf(inputBuffer, "on#%d", &dutyCycle) == 1) { // 将提取到的值赋值给目标值 brightness_tar = dutyCycle; // 发布消息到主题 mqttClient.publish(TOPIC_SUBSCRIBE, inputBuffer, sizeof(inputBuffer)); Serial.printf("Published message: %s\n", inputBuffer); } } }#ifndef DAPENSON_OTA_H #define DAPENSON_OTA_H #include <Arduino.h> #ifdef ESP8266 #include <ESP8266WiFi.h> #include <ESP8266httpUpdate.h> #elif defined(ESP32) #include <HTTPUpdate.h> #include <WiFi.h> #endif /***************** 函数声明 *************************/ void update_started(); void update_finished(); void update_progress(int cur, int total); void update_error(int err); void updateBin(); void getVersion(); /***************** 全局变量 *************************/ String upUrl = "http://bin.bemfa.com/b/1BcZjVjNTEwOGU3NTRkNjZkZmI3YTRjYzAwY2U2ZWJiZjI=otaTest.bin"; // 固件链接,在巴法云控制台复制、粘贴到这里即可 void getVersion() { Serial.println(F("=====================================")); Serial.println(F("Version: 1.1.0")); Serial.println(F("Author: Dapenson")); Serial.println(F("Date: 2022-12-14")); Serial.println(F("=====================================")); } // 当升级开始时,打印日志 void update_started() { Serial.println("CALLBACK: HTTP update process started"); } // 当升级结束时,打印日志 void update_finished() { Serial.println("CALLBACK: HTTP update process finished"); } // 当升级中,打印日志 void update_progress(int cur, int total) { Serial.printf("CALLBACK: HTTP update process at %d of %d bytes...\n", cur, total); } // 当升级失败时,打印日志 void update_error(int err) { Serial.printf("CALLBACK: HTTP update fatal error code %d\n", err); } /** * 固件升级函数 * 在需要升级的地方,加上这个函数即可,例如setup中加的updateBin(); * 原理:通过http请求获取远程固件,实现升级 */ void updateBin() { Serial.println("start update"); WiFiClient UpdateClient; #ifdef ESP8266 ESPhttpUpdate.onStart(update_started); // 当升级开始时 ESPhttpUpdate.onEnd(update_finished); // 当升级结束时 ESPhttpUpdate.onProgress(update_progress); // 当升级中 ESPhttpUpdate.onError(update_error); // 当升级失败时 t_httpUpdate_return ret = ESPhttpUpdate.update(UpdateClient, upUrl); #elif defined(ESP32) httpUpdate.onStart(update_started); // 当升级开始时 httpUpdate.onEnd(update_finished); // 当升级结束时 httpUpdate.onProgress(update_progress); // 当升级中 httpUpdate.onError(update_error); // 当升级失败时 t_httpUpdate_return ret = httpUpdate.update(UpdateClient, upUrl); #endif switch (ret) { case HTTP_UPDATE_FAILED: // 当升级失败 Serial.println("[update] Update failed."); break; case HTTP_UPDATE_NO_UPDATES: // 当无升级 Serial.println("[update] Update no Update."); break; case HTTP_UPDATE_OK: // 当升级成功 Serial.println("[update] Update ok."); break; } delay(10000); ESP.restart(); } #endif
2026年02月02日
2 阅读
0 评论
0 点赞
2026-02-02
新版Keilv5安装相关问题大全
1. 问题:新安装的Keil 不支持V5Compiler Version 5编译器在Keil 5.37以后就不再默认安装了。因此打开老的工程文件就会出现以下报错Build started: Project: stm32f10x_fwlib_template *** Target 'Target 1' uses ARM-Compiler 'Default Compiler Version 5' which is not available. *** Please review the installed ARM Compiler Versions: 'Manage Project Items - Folders/Extensions' to manage ARM Compiler Versions. 'Options for Target - Target' to select an ARM Compiler Version for the target. *** Build aborted. Build Time Elapsed: 00:00:00解决方法: 下载ARMCC并且解压到安装目录下的ARM 文件夹下,也可下载官方包,ARMCompiler_506_Windows_x86_b960 安装路径到ARM\ARMCC{cloud title=" ARMCC文件下载链接" type="bd" url="https://pan.baidu.com/s/1vrJCYOA7PqZ-UADagBIlog" password="2333"/}点击三块彩色积木图标 manage project items -> folder/extensions -> Use ARM Compiler 添加以上目录。此过程会修改TOOLS.INI 文件,必要时请管理员运行文件。然后在ARM Compiler 中就可以选择 V5.06版本了添加V5编译器:2. 问题:Keil ST-Link 下载程序或者点击 ST_Link settings 按钮闪退解决办法: 用旧版的 STLinkUSBDriver.dll 替换现有的 STLinkUSBDriver.dll,然后完美解决,这个应该是软件 Bug,如果没有旧版的 STLinkUSBDriver.dll,可以点击 STLinkUSBDriver下载 下载。注:我的 STLinkUSBDriver.dll 在 D:\Keil_v5\ARM\STLink 目录下
2026年02月02日
7 阅读
0 评论
0 点赞
1
2
3