Qt上位机:与STM32串口通信,数据收发,按钮控制LED

2023-05-16

Qt学习了几周,做一个串口助手巩固一下最近学习的内容。

遇到的问题1: write函数只能发送一次数据,想要继续发送必须重新关闭打开串口,每次只能发送一次数据
解决办法:在网上找不到类似的问题,机缘巧合下发现别人Qt工程封装好的.exe文件可以正常多条发送,在自己电脑的Qt环境下编译就只能发送一条数据,怀疑是环境的问题,卸载后下载最新版本Qt,解决了该问题。

遇到的问题2:STM32只能发送数据给上位机,接收不到Qt上位机的数据
解决办法:原因是Qt发送的是字符串,不是16进制数据,而且单片机串口中断服务函数的机制是每条数据的帧尾必须是0x0d 0x0a,这条数据才为有效数据,才能够被STM32单片机接收。因此发送的每条数据除了需要把字符串转换为16进制以外,还需要在数据增加单片机标志帧尾。
需要注意的是不同的单片机串口协议可能是不同的,我使用的是正点原子STM32F1单片机。可以通过打开两个串口助手,向设置好的虚拟串口发送数据,点选hex接收,查看该单片机串口通讯协议的校验帧。

上位机图片:
在这里插入图片描述

下面放上Qt工程与单片机的源代码链接:
https://download.csdn.net/download/Uncle_Tan123/12238290

头文件:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QSerialPort>

QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

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

public:
    bool getSerialPortConfig(void);

private slots:  //槽函数,遇到相应信号就触发
    void on_btn_open_clicked();
    void on_btn_send_clicked();
    void on_SerialPort_readyRead();

    void StringToHex(QString str, QByteArray &senddata);
    char ConvertHexChar(char ch);
private:
    Ui::Dialog *ui;
    bool mIsOpen;  //串口按钮是否打开
     //串口对象指针及配置参数
    QSerialPort *mSerialPort;
    QString mPortName;
    QString mBaudRate;
    QString mParity;
    QString mDataBits;
    QString mStopBits;
};
#endif // DIALOG_H

CPP文件:

#include "dialog.h"
#include "ui_dialog.h"
#include <QSerialPortInfo>
#include <QSerialPort>
#include <QList>
#include <QDebug>
#include <QTextEdit>

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

    mSerialPort = new QSerialPort; //创建一个串口对象

    mIsOpen = false; //初始化按钮状态标志位
    ui->btn_send->setEnabled(mIsOpen);

    //识别系统的所有可用串口号,并添加到下拉列表中
    QList<QSerialPortInfo> serialPortInfo = QSerialPortInfo::availablePorts();
    int count = serialPortInfo.count();
    for(int i = 0;i < count;i++)
    {
        ui->Cboxport->addItem(serialPortInfo.at(i).portName());
    }

    //等待一个触发信号,接收串口数据
    connect(mSerialPort, SIGNAL(readyRead()), this, SLOT(on_SerialPort_readyRead()));
}

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

bool Dialog::getSerialPortConfig()  //配置串口
{
    //获取串口配置
    mPortName = ui->Cboxport->currentText();
    mBaudRate = ui->Cboxboudrate->currentText();
    mParity = ui->Cboxparity->currentText();
    mDataBits = ui->Cboxdatabits->currentText();
    mStopBits = ui->Cboxstopbits->currentText();

    //设置串口
    //串口号
    mSerialPort->setPortName(mPortName);
    //波特率
    if("115200" == mBaudRate)
    {
        mSerialPort->setBaudRate(QSerialPort::Baud115200);
    }
    else
    {
        mSerialPort->setBaudRate(QSerialPort::Baud9600);
    }
    //校验位
    if("EVEN" == mParity)
    {
        mSerialPort->setParity(QSerialPort::EvenParity);
    }
    else if("ODD" == mParity)
    {
        mSerialPort->setParity(QSerialPort::OddParity);
    }
    else
    {
        mSerialPort->setParity(QSerialPort::NoParity);
    }
    //数据位
    if("5" == mDataBits)
    {
        mSerialPort->setDataBits(QSerialPort::Data5);
    }
    else if("6" == mDataBits)
    {
        mSerialPort->setDataBits(QSerialPort::Data6);
    }
    else if("7" == mDataBits)
    {
        mSerialPort->setDataBits(QSerialPort::Data7);
    }
    else
    {
        mSerialPort->setDataBits(QSerialPort::Data8);
    }
    //停止位
    if("1.5" == mStopBits)
    {
        mSerialPort->setStopBits(QSerialPort::OneAndHalfStop);
    }
    if("2" == mStopBits)
    {
        mSerialPort->setStopBits(QSerialPort::TwoStop);
    }
    else
    {
        mSerialPort->setStopBits(QSerialPort::OneStop);
    }
    qDebug() << "配置";
    return mSerialPort->open(QSerialPort::ReadWrite);
}
void Dialog::on_btn_open_clicked()  //打开关闭按钮状态
{
    if(true == mIsOpen)
    {
        //当前已经打开了串口,点击后将按钮更新为关闭状态
        mSerialPort->close();
        ui->btn_open->setText("打开");
        mIsOpen = false;
        //此时可以配置串口
        ui->Cboxport->setEnabled(true);
        ui->Cboxboudrate->setEnabled(true);
        ui->Cboxparity->setEnabled(true);
        ui->Cboxdatabits->setEnabled(true);
        ui->Cboxstopbits->setEnabled(true);
        ui->btn_send->setEnabled(mIsOpen);
        qDebug() << "关闭";
    }
    else
    {
        //当前处于关闭串口状态,打开前需要配置串口
        //getSerialPortConfig();
        if(true == getSerialPortConfig())
        {
            mIsOpen = true;
            ui->btn_open->setText("关闭");
            qDebug() << "成功打开串口" << mPortName;
            ui->Cboxport->setEnabled(false);
            ui->Cboxboudrate->setEnabled(false);
            ui->Cboxparity->setEnabled(false);
            ui->Cboxdatabits->setEnabled(false);
            ui->Cboxstopbits->setEnabled(false);
            ui->btn_send->setEnabled(mIsOpen);
        }
//        else
//        {
//            mIsOpen = false;
//        }
    }
}

void Dialog::on_btn_send_clicked() //发送按钮
{
    if(true == mIsOpen)
    {
        //mSerialPort->write(ui->textEdit_send->toPlainText().toLatin1());// toPlainText(将文本编辑的文本转换为纯文本)
        //mSerialPort->write(ui->textEdit_send->toPlainText().toStdString().c_str());
        //注意:write函数的传递参数是QString,先转换为C++标准的string,再转为char型
        QString str = ui->textEdit_send->toPlainText();
        int len = str.length();
        if(len%2 == 1)
        {
            str = str.insert(len - 1, '0');
        }
        QByteArray senddata;  //写入编辑框的数据
        StringToHex(str,senddata);

        int length = senddata.length();  //在帧尾追加STM32的关键帧
        senddata[length + 1] = 0x0d;
        senddata[length + 2] = 0x0a;
        mSerialPort->write(senddata);
    }
}

void Dialog::on_SerialPort_readyRead()  //读取串口数据
{
    if(true == mIsOpen)
    {
        QByteArray recvData = mSerialPort->readAll();
        //ui->textEdit_Recv->setPlainText(QString(recvData)); //显示内容每次会被覆盖
        ui->textEdit_Recv->append(QString(recvData));
        qDebug() << "正在接收数据";
    }
}

void Dialog::StringToHex(QString str, QByteArray &senddata) //字符串转换为十六进制数据0-F
{
    int hexdata,lowhexdata;
    int hexdatalen = 0;
    int len = str.length();
    senddata.resize(len/2);
    char lstr,hstr;


    for(int i=0; i<len; )
    {
        //char lstr,
        hstr=str[i].toLatin1();
        if(hstr == ' ')
        {
            i++;
            continue;
        }
        i++;
        if(i >= len)
            break;
        lstr = str[i].toLatin1();
        hexdata = ConvertHexChar(hstr);
        lowhexdata = ConvertHexChar(lstr);
        if((hexdata == 16) || (lowhexdata == 16))
            break;
        else
            hexdata = hexdata*16+lowhexdata;
        i++;
        senddata[hexdatalen] = (char)hexdata;
        hexdatalen++;
    }
    senddata.resize(hexdatalen);
}


char Dialog::ConvertHexChar(char ch)
{
    if((ch >= '0') && (ch <= '9'))
        return ch-0x30;
    else if((ch >= 'A') && (ch <= 'F'))
        return ch-'A'+10;
    else if((ch >= 'a') && (ch <= 'f'))
        return ch-'a'+10;
    else return ch-ch;//不在0-f范围内的会发送成0
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt上位机:与STM32串口通信,数据收发,按钮控制LED 的相关文章

  • 138-基于stm32单片机汽车多功能仪表盘显示系统Proteus仿真+源程序

    资料编号 138 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 ds1302时钟 LED灯 蜂鸣器 电位器 制作一个基于stm32单片机汽车多功能仪表盘显示系统Proteus仿真 2 通过DHT1
  • 133-基于stm32单片机停车场车位管理系统Proteus仿真+源程序

    资料编号 133 一 功能介绍 1 采用stm32单片机 4位数码管 独立按键 制作一个基于stm32单片机停车场车位管理系统Proteus仿真 2 通过按键进行模拟车辆进出 并且通过程序计算出当前的剩余车位数量 3 将剩余的车位数量显示到
  • Push_back() 导致程序在进入 main() 之前停止

    我正在为我的 STM32F3 Discovery 板使用 C 进行开发 并使用 std deque 作为队列 在尝试调试我的代码 直接在带有 ST link 的设备上或在模拟器中 后 代码最终在 main 中输入我的代码之前在断点处停止 然
  • 查找到 LED 的距离

    想象一下 您有一个圣诞树风格的 LED 灯 距相机的距离为 D 了解了 LED 灯 例如形状和强度 和相机 例如焦距 的属性 是否可以使用快照计算从相机到 LED 灯的距离 如果是 测量的准确度如何 明亮的光源本身对此不利因为明亮的光线通常
  • STM32用一个定时器执行多任务写法

    文章目录 main c include stm32f4xx h uint32 t Power check times 电量检测周期 uint32 t RFID Init Check times RFID检测周期 int main Timer
  • [屏驱相关]【SWM166-SPI-Y1.28C1测评】+ 有点惊艳的开箱

    耳闻华芯微特许久了 看到论坛得评测活动赶紧上了末班车 毕竟对有屏幕得板子也是很喜欢得 京东快递小哥客客气气 微笑着把快递给了我 好评 直接拆了包 在此之前没看过视频号 所以这个圆盘盘得模具还是有点惊喜的 正面照如下 开机有灯光秀 还有动画
  • [MM32硬件]搭建灵动微MM32G0001A6T的简易开发环境

    作为学习单片机的经典 自然是通过GPIO点亮LED 或者是响应按钮的外部中断例程 这我们看看SOP8封装的芯片MM32G0001A6T得引脚 除了VDD和GND固定外 我们可以使用PA14 PA1 PA13 PA15 PA2 PA3这六个G
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • 在 Atollic TrueStudio、STM32CubeMX 中导入 C 库

    我目前正在开发 STM32F767ZI Nucleo 板和一个小安全芯片 microchip atecc508a 通过 i2c 连接进行连接 该芯片有一个可用的库加密验证库 https github com MicrochipTech cr
  • 跟着野火学FreeRTOS:第一段(任务定义,切换以及临界段)

    在裸机系统中 系统的主体就是 C P U CPU CP U 按照预先设定的程序逻辑在 m a i n
  • 1.69寸SPI接口240*280TFT液晶显示模块使用中碰到的问题

    1 69寸SPI接口240 280TFT液晶显示模块使用中碰到的问题说明并记录一下 在网上买了1 69寸液晶显示模块 使用spi接口 分辨率240 280 给的参考程序是GPIO模拟的SPI接口 打算先移植到FreeRtos测试 再慢慢使用
  • 毕设开题分享 单片机智能教室系统(智能照明+人数统计)

    1 简介 Hi 大家好 今天向大家介绍一个学长做的单片机项目 单片机智能教室系统 智能照明 人数统计 大家可用于 课程设计 或 毕业设计 项目分享 https gitee com feifei1122 simulation project
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • 将 Arduino RGB LED 从一种颜色渐变为另一种颜色?

    目前 我已成功让 LED 灯循环显示我选择的八种颜色 一切都工作正常 除了我想要一种更自然的感觉 并且想要从一种颜色褪色 过渡到下一种颜色 而不是让它们互相替换 到目前为止 这是我的代码 int redPin 11 int greenPin
  • systick定时器

    systick定时器 文章目录 前言 一 前期疑惑 二 解答 1 关于systick是阻塞的吗 2 非阻塞 三 软件编写 总结 前言 这边记录systick相关知识点 一 前期疑惑 在学习systick志气啊 其实对于systick还是一脸
  • STM32 Nucleo 上的上升沿中断多次触发

    我正在使用 STM32 NUCLEO F401RE 微控制器板 我有一个扬声器 经过编程 当向上 向下推操纵杆时 可以按设定的量改变频率 我的问题是 有时 通常 当向上 向下推动操纵杆时 频率会增加 减少多次 这意味着 ISR 正在执行多次
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • 使用 STM32F0 ADC 单独读取不同的输入

    STM32F072CBU 微控制器 我有多个 ADC 输入 并且希望单独读取它们 STMcubeMX 生成样板代码 假设我希望按顺序读取所有输入 但我无法弄清楚如何纠正这个问题 这篇博文 http blog koepi info 2015
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • Android 通知 LED 不使用我的颜色

    我正在尝试使用一个通知 该通知也使用我的 S3 上的通知 LED 但由于某种原因 颜色将始终为蓝色 我猜这是默认值 我尝试使用不同的颜色但没有任何变化 其他应用程序 例如 Whatsapp Gmail 和 Facebook 在显示不同颜色的

随机推荐

  • git push代码到远程新分支

    Git push 获取远程代码修改后 想要push到远端与原来不同的新分支 xff0c 可以使用下面的命令实现 xff1a git push origin 本地分支 远端希望创建的分支 例如git下来的分支为master span clas
  • 【numpy求和】numpy.sum()求和

    numpy sum a axis 61 None dtype 61 None out 61 None keepdims 61 initial 61 source 用于计算array元素的和 python中常用的numpy进行数学计算 xff
  • Nuttx romfs与启动脚本rcS

    ARM系统上电后 xff0c 系统将flash地址映射到零地址处 xff0c 处理器从零地址处开始运行第一条指令 而在零地址处 xff0c 一般是系统复位中断向量 xff0c 此处存放的是一条跳转指指令 xff0c 通过该条换指令 xff0
  • 在终端/命令行下打开文件浏览器窗口--Win cmd &Ubuntu terminal

    在命令行下想要可视化查看文件 xff0c 可以使用命令直接打开图形化窗口 1 Windows windows上可以使用explorer exe打开资源管理器 xff1a explorer exe span class token keywo
  • 127.0.0.0与0.0.0.0的区别

    1 IP地址分类 ref https tools ietf org html rfc1700 page 3 IP地址表示 IP地址由两个部分组成 xff0c net id和host id xff0c 即网络号和主机号 net id 表示ip
  • 【python】代码换行的几种方法

    代码太长怎么办 xff0c 反斜杠 引号 34 34 34 39 来帮忙 xff01 在写list或者较长的字符串时候 xff0c 或者多个循环造成IDE不够用时 xff0c 就需要代码换行了 主要的代码换行有通用的反斜杠 和针对字符串起作
  • 自己动手写C++迭代器

    综述 关于STL iterator和 iterator adapter 的部分我已在先前的博客 stl源码剖析笔记之iterator 中有所提及 xff0c 下面我们可以试着自己动手写一个简单的迭代器工具 step iterator xff
  • 【STM32F0】Keil 查看局部变量显示<not in scope>

    现象 xff1a 在进行STM32F0开发的时候出现了 调试代码 xff0c 添加变量Watch时 xff0c 显示not in scope 处理方式 xff1a 因为代码开了优化的处理 xff0c 把优化改到Level0 就可以解决问题
  • error: undefined reference to '__dso_handle'解决方案

    error undefined reference to 39 dso handle 39 解决方案 home NDK android ndk r9 sources cxx stl gnu libstdc 43 43 4 7 libs ar
  • ARM里的大端格式和小端格式分别是什么意思?

    当前的存储器 xff0c 多以byte为访问的最小单元 xff0c 当一个逻辑上的地址必须分割为物理上的若干单元时就存在了先放谁后放谁的问题 于是端 endian 的问题应运而生了 对于不同的存储方法 就有大端 big endian 和小端
  • STM32串口通信(基于缓冲区)编程及遇到的问题总结

    在写串口通信前阅读了STM32中文参考手册 xff0c 然后满心澎湃地写代码 在这个过程中遇一些让人郁闷的事情 xff0c 目前这些问题目前已经解决了 xff08 嘿嘿嘿 xff09 xff0c 特此来总结一番 串口的使用步骤大概如下 xf
  • 主板串口FIFO大小设置

    FIFO大小和芯片 驱动有关系 xff0c 可以在设备管理器里面调整大小 1 进入设备管理器 xff0c 右键选择串口属性 2 在端口设置里面选择高级 3 可以单独设定每一个串口的接收和发送区大小
  • mac终端 python scrapy爬虫 zsh: no matches found

    在学习Python爬虫时 xff0c 进行到scrapy板块 xff0c 执行genspider命令 输入scrapy genspider tongcheng https bj 58 com sou key 61 E5 89 8D E7 A
  • JSESSIONID的简单说明

    1 第一次访问服务器的时候 xff0c 会在响应头里面看到Set Cookie信息 只有在首次访问服务器的时候才会在响应头中出现该信息 上面的图JSESSIONID 61 ghco9xdnaco31gmafukxchph Path 61 a
  • 史上最全的常用开发工具类收集(持续更新中)

    外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img BtY85pbk 1577412535564 https img shields io badge QQ群 523167548 20 ff69b4 svg API
  • MFC学习之vc通过HTTP请求:Get或Post方式获取JSON信息(亲测可用)

    前段时间公司项目需要跟上一级平台对接一些采集回来的数据 xff0c 通过HTTP xff0c post方法上传JSON信息到指定的接口地址 本来呢 xff1f 我在入职时是面试的售后岗 xff0c 一家小公司 xff0c 当时公司软件方面一
  • mac安装虚拟机VMware fusion12 和ubantu系统

    一 基本安装 下载虚拟机VMware fusion12 我选择了不更新新版本并且允许访问辅助功能 选择 新建 接下来选择 从光盘或者映像安装 从下载目录把ubantu系统拖拽过去 点击安装完成 xff0c 将ubantu系统保存在虚拟机上即
  • VSCode常用命令---记录自己的常用命令

    一 nvm相关命令 node版本管理 查看已安装的版本 nvm list 使用版本 nvm use 版本号 安装版本 nvm install 版本号 卸载版本 nvm uninstall 版本号 常用命令 全局包安装 多用于gitee下载后
  • Ubuntu18.04 Realsense D435i驱动安装与配置

    InterRealSenseD435i SDK安装 一 命令行的安装方式安装 1 注册服务器的公钥 xff1a 打开终端输入 sudo apt key adv keyserver keys gnupg net recv key C8B3A5
  • Qt上位机:与STM32串口通信,数据收发,按钮控制LED

    Qt学习了几周 xff0c 做一个串口助手巩固一下最近学习的内容 遇到的问题1 xff1a write函数只能发送一次数据 xff0c 想要继续发送必须重新关闭打开串口 xff0c 每次只能发送一次数据 解决办法 xff1a 在网上找不到类