返回列表 发新帖我要提问本帖赏金: 10.00元(功能说明)

[程序源码] 开源的Qt 串口助手 一学就会

[复制链接]
4057|8
 楼主| 一路向北lm 发表于 2021-1-21 18:36 | 显示全部楼层 |阅读模式
本帖最后由 一路向北lm 于 2021-1-22 10:50 编辑

#申请原创#         

      串口调试助手是一款用于串口调试的工具,目前网上存在很多个版本,功能都差不多,但稳定性有好有坏,如果只用于一般的串口调试,这些工具够用了,如果想开发一款适于自己的串口调试助手,本文也许可以帮你。本文中的调试助手用QT开发,QT的开发环境不在这里详述了,不会安装的可以在网上找找类似的博文吧,以下仅供参考。


第一部分:代码托管:
此部分可能存在一些未知的bug,欢迎广大网友指出,为了方便管理和学习,所有代码均托管到gitee,链接地址:https://gitee.com/lumengcode/my-qt

第二部分:效果展示:

实现的功能:

1.自动获取计算机的端口号;
2.串口参数可更改:包括 波特率、数据位、停止位、校验和等............
3.串口数据的发送和接收
4.支持十六进制数据的发送和接收
5.支持时间戳功能,方便文件的存储查看
6.发送从窗口和接收窗口的清理
7.定时发送功能
............

简单设置一下背景色,好看多了!

第二部分:代码部分:


1.当我们的计算机的端口号发生改变时,串口助手要具备实时扫面本机的端口号的功能,具有实时获取有效的串口信息,并将其刷新到下拉框中供我们选择。
有些自己编写的串口助手是没有这个功能的,这里我给大家补充上去。
  1. //使用foreach获取有效的串口信息
  2.      foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
  3.      {
  4.          //这里相当于自动识别串口号之后添加到了cmb,如果要手动选择可以用下面列表的方式添加进去
  5.          Serial.setPort(info);
  6.          if(Serial.open(QIODevice::ReadWrite))
  7.          {
  8.              //将串口号添加到cmb
  9.              ui->comboBox_Port->addItem(info.portName());
  10.              //关闭串口等待人为(打开串口按钮)打开
  11.              Serial.close();
  12.          }
  13.      }
2.填充下拉框的波特率、数据位、停止位、效验位….,初始化下拉框默认参数,这个参数设置大部分的串口助手都会具备,因此不足为奇。
该有的功能个咱还是得有的。
  1. // 填充波特率
  2.     QStringList Baud;
  3.     Baud<<"1200"<<"2400"<<"4800"<<"9600"<<"38400"<<"115200";
  4.     ui->comboBox_Baud->addItems(Baud);
  5.     // 填充数据位
  6.     QStringList DataBit;
  7.     DataBit<<"5"<<"6"<<"7"<<"8";
  8.     ui->comboBox_DataBit->addItems(DataBit);
  9.     // 填充停止位
  10.     QStringList StopBit;
  11.     StopBit<<"1"<<"1.5"<<"2";
  12.     ui->comboBox_StopBit->addItems(StopBit);
  13.     // 填充效验位
  14.     QStringList CheckBit;
  15.     CheckBit<<"奇效验"<<"偶效验"<<"无";
  16.     ui->comboBox_CheckBit->addItems(CheckBit);

  17.     //初始化默认参数
  18.     ui->comboBox_Baud->setCurrentIndex(3); //默认9600
  19.     ui->comboBox_DataBit->setCurrentIndex(3); //默认8bit Data
  20.     ui->comboBox_StopBit->setCurrentIndex(0); //默认1bit Stop
  21.     ui->comboBox_CheckBit->setCurrentIndex(2); //默认 无效验
3.串口打开和关闭按钮操作,这个就是打开串口按钮和关闭按钮的逻辑操作,成功打开串口后,相应的参数将会被设置。串口即可以用于
数据的发送和接收了,这里也处理,打开失败时的逻辑操作,可谓是“疏而不漏也!”。
  1. //串口打开和关闭按钮
  2. void MainWindow::on_pushButton_Open_clicked()
  3. {
  4.     //设置串口号;也就是说打开的是当前显示的串口
  5.     if(ui->comboBox_Port->currentText().isEmpty())
  6.     {
  7.         QMessageBox::information(this,"提示","没有可用的串口");
  8.         return;
  9.     }
  10.     Serial.setPortName(ui->comboBox_Port->currentText());
  11.     if(ui->pushButton_Open->text() == "打开串口")
  12.     {
  13.            if(Serial.open(QIODevice::ReadWrite))//读写方式打开,成功后设置串口
  14.            {
  15.                //设置波特率
  16.                Serial.setBaudRate(ui->comboBox_Baud->currentText().toInt());

  17.                //设置数据位
  18.                switch(ui->comboBox_DataBit->currentText().toInt())
  19.                {
  20.                      case 5:
  21.                              Serial.setDataBits(QSerialPort::Data5);
  22.                      break;
  23.                      case 6:
  24.                              Serial.setDataBits(QSerialPort::Data6);
  25.                      break;
  26.                      case 7:
  27.                               Serial.setDataBits(QSerialPort::Data7);
  28.                      break;
  29.                      case 8:
  30.                               Serial.setDataBits(QSerialPort::Data8);
  31.                      break;
  32.                      default:
  33.                               QMessageBox::information(this,"提示","数据位配置出错");
  34.                               return;
  35.                      break;
  36.                }

  37.                //设置校验位
  38.                if (ui->comboBox_CheckBit->currentText() == "奇效验")
  39.                {
  40.                    Serial.setParity(QSerialPort::OddParity);
  41.                }
  42.                else if (ui->comboBox_CheckBit->currentText() == "偶效验")
  43.                {
  44.                    Serial.setParity(QSerialPort::EvenParity);
  45.                }
  46.                else if (ui->comboBox_CheckBit->currentText() == "无")
  47.                {
  48.                    Serial.setParity(QSerialPort::NoParity);
  49.                }

  50.                //设置停止位
  51.                if (ui->comboBox_StopBit->currentText().toFloat() == 1)
  52.                {
  53.                    Serial.setStopBits(QSerialPort::OneStop);
  54.                }
  55.                else if(ui->comboBox_StopBit->currentText().toFloat() == 1.5)
  56.                {
  57.                    Serial.setStopBits(QSerialPort::OneAndHalfStop);
  58.                }
  59.                else if(ui->comboBox_StopBit->currentText().toFloat() == 2)
  60.                {
  61.                    Serial.setStopBits(QSerialPort::TwoStop);
  62.                }

  63.                //设置流控制
  64.                Serial.setFlowControl(QSerialPort::NoFlowControl);
  65.                ui->pushButton_Open->setText("关闭串口");


  66.                //建立串口接收的槽函数
  67.                connect(&Serial,&QSerialPort::readyRead ,this,&MainWindow::ReadRecData);

  68.               // timer0->start(100);

  69.             }
  70.            else//串口打开失败
  71.            {
  72.                QMessageBox::about(NULL, "提示", "打开出错,串口被占用!");
  73.                return ;
  74.            }
  75.     }
  76.     else if(ui->pushButton_Open->text() == "关闭串口")
  77.     {
  78.         Serial.close();//关串口
  79.         //timer0->stop();
  80.         ui->pushButton_Open->setText("打开串口");
  81.     }
  82. }
4. 串口接收数据函数(支持时间戳、HEX接收) 这个是很关键的地方了,要保证数据接收的完整性和实时性,可采用两种
接收数据的模式:定时器触发和槽触发,定时器触发我这里采用的是100ms的中断接收,大家还可以调的更小一点。
  1. void MainWindow::ReadRecData()
  2. {
  3.     QByteArray readData = Serial.readAll();//读取串口数据
  4.     QByteArray NewData;
  5.     QString current_date;

  6.    if(readData != NULL)//将读到的数据显示到数据接收区
  7.    {
  8.        if(HexRecvFlag)  //判断是否使用HEX
  9.        {
  10.            //判断是否使用时间戳
  11.            if(EnableTimeFlag == 1)
  12.            {
  13.                current_date_time = QDateTime::currentDateTime();
  14.                current_date += "[";
  15.                current_date += current_date_time.toString("yyyy-MM-dd hh:mm:ss");
  16.                current_date += "]收->";
  17.                ui->textEdit_Recv->append(current_date.toUtf8() + readData.toHex());
  18.            }
  19.            else
  20.            {
  21.               ui->textEdit_Recv->append(readData.toHex());
  22.            }

  23.        }
  24.        else
  25.        {
  26.            //判断是否使用时间戳
  27.            if(EnableTimeFlag == 1)
  28.            {
  29.                current_date_time = QDateTime::currentDateTime();
  30.                current_date += "[";
  31.                current_date += current_date_time.toString("yyyy-MM-dd hh:mm:ss");
  32.                current_date += "]收->";
  33.                ui->textEdit_Recv->append(current_date.toUtf8() + readData);
  34.            }
  35.            else
  36.            {
  37.               ui->textEdit_Recv->append(readData);
  38.            }
  39.        }

  40.    }
  41. }
5. 串口发送数据函数(支持时间戳、HEX接收) 这个是很关键的地方了,串口发送数据的方式就比较简单了,直接将数据送入缓冲区
  1. //发送数据
  2. void MainWindow::on_pushButton_Send_clicked()
  3. {
  4.     QString DataStr;
  5.     QString NewData;
  6.     QString current_date;

  7.     DataStr = ui->textEdit_Send->toPlainText();
  8.     if(ui->pushButton_Open->text() == "打开串口")
  9.     {
  10.        QMessageBox::information(this,"提示","未打开串口");
  11.        return;
  12.     }

  13.     if(EnableTimeFlag == 1)
  14.     {
  15.         current_date_time = QDateTime::currentDateTime();
  16.         current_date += "[";
  17.         current_date += current_date_time.toString("yyyy-MM-dd hh:mm:ss");
  18.         current_date += "]发->";
  19.         NewData = current_date + DataStr;
  20.     }
  21.     else
  22.     {
  23.       NewData = DataStr;
  24.     }

  25.     if(HexSendFlag)
  26.     {
  27.        Serial.write(DataStr.toUtf8().toHex());//写入缓冲区
  28.     }
  29.     else
  30.     {

  31.       ui->textEdit_Recv->append(NewData.toUtf8());
  32.     }
  33. }
6.清除接收和发送窗口数据函数,为了方便调试和观察,这里添加了清除接收和发送窗口数据函数的操作。
  1. //清除接收窗口数据
  2. void MainWindow::on_pushButton_ClearRecv_clicked()
  3. {
  4.    ui->textEdit_Recv->clear();
  5. }

  6. //清除发送窗口数据
  7. void MainWindow::on_pushButton_2_clicked()
  8. {
  9.    ui->textEdit_Send->clear();
  10. }

7.使能时间戳,时间戳的主要目的在于通过一定的技术手段,对数据产生的时间进行认证,从而验证这段数据在产生后是否经过篡改。所以时间戳服务的提供者必须证明服务中使用的时间源是可信的,所提供的时间戳服务是安全的。
  1. void MainWindow::on_checkBox_EnableTime_clicked(bool checked)
  2. {
  3.      if(checked == true)
  4.      {
  5.          EnableTimeFlag = 1;
  6.      }
  7.      else
  8.      {
  9.          EnableTimeFlag = 0;
  10.      }
  11. }

8. 使能定时发送,定时发送很香了,必须得有啊!
  1. void MainWindow::on_checkBox_clicked(bool checked)
  2. {
  3.     if(checked == true)
  4.     {
  5.         if(ui->pushButton_Open->text() == "打开串口")
  6.         {
  7.            QMessageBox::information(this,"提示","未打开串口");
  8.            ui->checkBox->setChecked(false);
  9.            return;
  10.         }
  11.         quint32 stime= ui->lineEdit_STime->text().toInt();
  12.         timer_id1 = startTimer(stime);
  13.         ui->lineEdit_STime->setEnabled(false);
  14.     }
  15.     else
  16.     {
  17.        killTimer(timer_id1);
  18.        ui->lineEdit_STime->setEnabled(true);
  19.     }
  20. }
9. 使能HEX 发送和接收按钮,HEX那是标配,我只希望不要出bug,慢慢完善吧!
  1. void MainWindow::on_checkBox_HexRecv_clicked(bool checked)
  2. {
  3.     if(checked)
  4.     {
  5.         HexRecvFlag = 1;
  6.     }

  7.     else
  8.         HexRecvFlag = 0;
  9. }

  10. void MainWindow::on_checkBox_HexSend_clicked(bool checked)
  11. {
  12.     if(checked)
  13.         HexSendFlag = 1;
  14.     else
  15.         HexSendFlag = 0;
  16. }
10. 定时器中断函数 触发接收串口数据的核心,没它啥也干不了。
  1. void MainWindow:: timerEvent(QTimerEvent *ev)
  2. {
  3.     if(ev->timerId() == timer_id1)
  4.     {
  5.        on_pushButton_Send_clicked();
  6.     }
  7. }
串口助手部分最后的展示效果


@21小跑堂   @21小跑堂    @21小跑堂   








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

打赏榜单

21小跑堂 打赏了 10.00 元 2021-01-22
理由:恭喜通过原创文章审核!请多多加油哦!

海洋无限 发表于 2021-1-26 12:25 | 显示全部楼层
nvjwiciw659 发表于 2021-1-29 15:34 | 显示全部楼层
给师兄顶
 楼主| 一路向北lm 发表于 2021-1-30 18:22 | 显示全部楼层
sch_l 发表于 2021-2-1 08:56 | 显示全部楼层
高手!
catvevs 发表于 2021-4-1 09:43 | 显示全部楼层
谢谢分享
qqq_147258 发表于 2021-9-10 10:33 | 显示全部楼层
貌似缺少“res/res.qrc”文件。
qin552011373 发表于 2021-10-15 10:55 | 显示全部楼层
收藏备用
qjp1988113 发表于 2021-10-15 15:27 | 显示全部楼层
赞一个,楼主有没有后续完善和美化?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

293

主题

3837

帖子

81

粉丝
快速回复 在线客服 返回列表 返回顶部