文章目录
- 原版代码工程
- 增加QCustomplot实时画图的源码工程
- 源码
原版代码工程
源码下载链接:
链接:https://pan.baidu.com/s/15pWzadPwOx_OfJGtvL-MjA
提取码:lief
–来自百度网盘超级会员V5的分享
增加QCustomplot实时画图的源码工程
源码:
链接:https://pan.baidu.com/s/1DJKV7RY3C_1nQ1K2iNP61w
提取码:lief
–来自百度网盘超级会员V5的分享
下位机arduino测试代码:
#include <Arduino.h>unsigned char data_to_send[100] = {0};int acc_data[3] = {0};
int gyro_data[3] = {0};/**********为了匿名四轴上位机的协议定义的变量****************************/
//cup为小端模式存储,也就是在存储的时候,低位被存在0字节,高位在1字节
#define BYTE0(dwTemp) (*(char *)(&dwTemp)) //取出int型变量的低字节
#define BYTE1(dwTemp) (*((char *)(&dwTemp) + 1)) // 取存储在此变量下一内存字节的内容,高字节
#define BYTE2(dwTemp) (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp) (*((char *)(&dwTemp) + 3))/*
发送给上位机的数据帧定义
@桢头--功能字--长度--数据(一个或多个,具体看协议说明)-校验
@前2个字节为帧头0xAAAA
@第3个字节为帧ID,应设置为0xF1~0xFA中的一个
@第4个字节为报文数据长度(dlc)
@第5个字节开始到第5+dlc-1个字节为要传输的数据内容段,每个数据场为高字节在前,地字节在后
@第5+dlc个字节为CheckSum,为第1个字节到第5+dlc-1个字节所有字节的值相加后,保留结果的低八位作为CheckSum
*/
void Data_Send_Senser(unsigned int pst) //按照协议的要求处理数据,pst为包含多个数据的数组,但这里为一个数据
{unsigned char _cnt=0;unsigned char i=0;unsigned int j=0,temp;unsigned char sum = 0;//char 类型为两个字节data_to_send[_cnt++]=0xAA; //桢头data_to_send[_cnt++]=0xAA;data_to_send[_cnt++]=0x02; //功能字data_to_send[_cnt++]=0; //需要发送数据的字节数,暂时给0,后面在赋值。data_to_send[_cnt++]=pst&0x00ff; //数据的低8位data_to_send[_cnt++]=pst>>8; //数据的高8位data_to_send[3] = _cnt-4; //长度for(i=0; i<_cnt; i++){sum = sum+ data_to_send[i]; //校验位}data_to_send[_cnt++] =sum; //计算校验位Serial.write(data_to_send,_cnt);
}/*
发送给上位机的数据帧定义
@桢头--功能字--长度--数据(一个或多个,具体看协议说明)-校验
@前2个字节为帧头0xAAAA
@第3个字节为帧ID,应设置为0xF1~0xFA中的一个
@第4个字节为报文数据长度(dlc)
@第5个字节开始到第5+dlc-1个字节为要传输的数据内容段,每个数据场为高字节在前,地字节在后
@第5+dlc个字节为CheckSum,为第1个字节到第5+dlc-1个字节所有字节的值相加后,保留结果的低八位作为CheckSum
*/
void data_to_computer(int* acc_data,int* gyro_data)
{unsigned char data_to_send[23] = {0};unsigned char i = 0;unsigned char cnt = 0;unsigned char sum = 0;data_to_send[cnt++]=0xAA; //帧头:AAAAdata_to_send[cnt++]=0xAA;data_to_send[cnt++]=0x02; //功能字:OXF2data_to_send[cnt++]=0; //需要发送数据的字节数,暂时给0,后面在赋值。data_to_send[cnt++] = BYTE1(acc_data[0]);//取data[0]数据的高字节,data_to_send[cnt++] = BYTE0(acc_data[0]);data_to_send[cnt++] = BYTE1(acc_data[1]);data_to_send[cnt++] = BYTE0(acc_data[1]);data_to_send[cnt++] = BYTE1(acc_data[2]);data_to_send[cnt++] = BYTE0(acc_data[2]);data_to_send[cnt++] = BYTE1(gyro_data[0]);//取data[0]数据的高字节,data_to_send[cnt++] = BYTE0(gyro_data[0]);data_to_send[cnt++] = BYTE1(gyro_data[1]);data_to_send[cnt++] = BYTE0(gyro_data[1]);data_to_send[cnt++] = BYTE1(gyro_data[2]);data_to_send[cnt++] = BYTE0(gyro_data[2]);data_to_send[cnt++]=0;data_to_send[cnt++]=0;data_to_send[cnt++]=0;data_to_send[cnt++]=0;data_to_send[cnt++]=0;data_to_send[cnt++]=0;data_to_send[3] = cnt-4;//计算总数据的字节数。for(i=0;i<cnt;i++) //对于for语句,当不写大括号的时候,只执行到下面第一个分号结束。{sum+=data_to_send[i];}data_to_send[cnt++] = sum; //计算校验位Serial.write(data_to_send,cnt);
}void setup() {// put your setup code here, to run once:Serial.begin(115200);randomSeed(analogRead(0));pinMode(8,OUTPUT);
}void loop() {// unsigned char buff[6];// unsigned char i;// for(i = 0;i<6;i++)// {// buff[i] = random(65535);// }// acc_data[0] = (buff[0] << 8) | buff[1];//x轴高8位左移8位或上低8位// acc_data[1] = (buff[2] << 8) | buff[3];// acc_data[2] = (buff[4] << 8) | buff[5];// for(i = 0;i<6;i++)// {// buff[i] = random(65535);// }// gyro_data[0] = (buff[0] << 8) | buff[1];//x轴高8位左移8位或上低8位// gyro_data[1] = (buff[2] << 8) | buff[3];// gyro_data[2] = (buff[4] << 8) | buff[5];// data_to_computer(acc_data, gyro_data);digitalWrite(8,HIGH);// unsigned int num = random(100);
// Data_Send_Senser(num);for(int i = 0; i < 255; i++){Data_Send_Senser(i);delay(2); // ms }digitalWrite(8,LOW);//delayMicroseconds(1500); // us
}
源码
mainwindows.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug() <<"main" <<QThread::currentThread();qRegisterMetaType<serialportplus::Settings>("serialportplus::Settings");initUI();initSerialPort();
}MainWindow::~MainWindow()
{delete ui;
}/** 函数功能:完成对串口助手界面的初始化*/
void MainWindow::initUI()
{//增加端口号选择项for (int i = 1; i <= 15; i++){ui->cboPortName->addItem(QString("COM%1").arg(i));}//设置端口号波特率ui->cboBaudrate->addItem(QString("1200"),QSerialPort::Baud1200);ui->cboBaudrate->addItem(QString("2400"),QSerialPort::Baud2400);ui->cboBaudrate->addItem(QString("4800"),QSerialPort::Baud4800);ui->cboBaudrate->addItem(QString("9600"),QSerialPort::Baud9600);ui->cboBaudrate->addItem(QString("19200"),QSerialPort::Baud19200);ui->cboBaudrate->addItem(QString("38400"),QSerialPort::Baud38400);ui->cboBaudrate->addItem(QString("57600"),QSerialPort::Baud57600);ui->cboBaudrate->addItem(QString("115200"),QSerialPort::Baud115200);//设置端口数据位数ui->cboDataBit->addItem("8",QSerialPort::Data8);ui->cboDataBit->addItem("7",QSerialPort::Data7);ui->cboDataBit->addItem("6",QSerialPort::Data6);ui->cboDataBit->addItem("5",QSerialPort::Data5);//设置端口校验方式ui->cboParity->addItem("Odd",QSerialPort::OddParity);ui->cboParity->addItem("Even",QSerialPort::EvenParity);ui->cboParity->addItem("None",QSerialPort::NoParity);//设置端口停止位ui->cboStopBit->addItem("1",QSerialPort::OneStop);ui->cboStopBit->addItem("1.5",QSerialPort::OneAndHalfStop);ui->cboStopBit->addItem("2",QSerialPort::TwoStop);//设置端口流控制ui->cboFlowContral->addItem("None",QSerialPort::NoFlowControl);ui->cboFlowContral->addItem("RTS/CTS",QSerialPort::HardwareControl);ui->cboFlowContral->addItem("XON/XOFF",QSerialPort::SoftwareControl);//设置定时重发时间,单位msui->lineEdit->setText("1000");//定时时间到,则执行timeup函数connect(&m_timer, &QTimer::timeout, this,&MainWindow::timeUp);
}/** 函数功能:完成对串口的初始化,设置串口子线程*/
void MainWindow::initSerialPort()
{//将串口对象的相关操作,放入子线程m_serial.moveToThread(&m_thread);//子线程启动m_thread.start();/*分别是界面对串口发出的启动、停止和发送数据的信号*/connect(this, &MainWindow::sigStart,&m_serial, &serialportplus::startPort);connect(this, &MainWindow::sigStop,&m_serial, &serialportplus::stopPort);connect(this, &MainWindow::sigSend,&m_serial, &serialportplus::sendData);/*分别是串口对界面发出的启动、停止和接收数据的信号*/connect(&m_serial, &serialportplus::sigStarted,this, &MainWindow::started);connect(&m_serial, &serialportplus::sigStop,this, &MainWindow::stoped);connect(&m_serial, &serialportplus::sigReceived,this, &MainWindow::receiveData);
}/** 函数功能:当界面关闭时,子线程也要进行关闭*/
void MainWindow::closeEvent(QCloseEvent *event)
{Q_UNUSED(event);//打印界面主线程地址qDebug() <<"main" <<QThread::currentThread();//向发送串口发送串口停止的信号emit sigStop();//串口子线程关闭m_thread.quit();//等待串口子线程完全关闭m_thread.wait();}/** 函数功能:根据串口打开按钮判断是否打开串口,* 当串口打开时,对串口参数进行设置,并向串口子线程发出串口打开信号,否则发出关闭信号*/
void MainWindow::on_btnOpenPort_clicked()
{//获取串口打开按钮的文本QString text= ui->btnOpenPort->text();//当按钮关闭时,打开串口,并设置相关参数,向串口子线程发送串口打开信号if(text == QString::fromLocal8Bit("打开串口")){serialportplus::Settings s;s.name= ui->cboPortName->currentText();s.baudRate= (QSerialPort::BaudRate)ui->cboBaudrate->currentData().toInt();s.dataBits = (QSerialPort::DataBits)ui->cboDataBit->currentData().toInt();s.stopBits= (QSerialPort::StopBits)ui->cboStopBit->currentData().toInt();s.parity= (QSerialPort::Parity)ui->cboParity->currentData().toInt();s.flowControl = (QSerialPort::FlowControl)ui->cboFlowContral->currentData().toInt();emit sigStart(s);}//当按钮打开时,关闭串口,向串口子线程发送串口关闭信号else{emit sigStop();}}/** 函数功能:点击发送按钮时,执行串口发送*/
void MainWindow::on_btnSend_clicked()
{//获取所要发送的文本QString strSend = ui->SendplainTextEdit->toPlainText();//将所要发送的文本存入arr变量QByteArray arr = strSend.toUtf8();//将arr变量通过信号发给串口子线程emit sigSend(arr);
}/** 函数功能:接收串口子线程发出启动的信号,对串口的按钮和参数设置的界面进行管理*/
void MainWindow::started()
{//串口打开按钮文本切换,切换为“关闭串口”ui->btnOpenPort->setText(QString::fromLocal8Bit("关闭串口"));//串口参数处于不可更改的状态ui->groupBox->setEnabled(false);
}/** 函数功能:接收串口子线程发出停止的信号,对串口的按钮和参数设置的界面进行管理*/
void MainWindow::stoped(int status)
{Q_UNUSED(status);//串口打开按钮文本切换,切换为“打开串口”ui->btnOpenPort->setText(QString::fromLocal8Bit("打开串口"));//串口参数处于可更改的状态ui->groupBox->setEnabled(true);
}/** 函数功能:接收串口子线程发出数据接收的信号,界面接收串口子线程发送的数据,并将其显示到界面上*/
void MainWindow::receiveData(QByteArray data)
{//将接收的数据进行转换QString strText = QString(data);//获取当前接收数据的时间QDateTime current_date_time = QDateTime::currentDateTime();//显示当前接收数据的时间QString t = current_date_time.toString("yyyy-MM-dd hh:mm:ss.zzz : ");//显示当前接收的数据ui->RecveeiveplainTextEdit->appendPlainText( t + strText + "\n" );
}/** 函数功能:定时发送状态改变响应函数*/
void MainWindow::on_checkBox_stateChanged(int arg1)
{//当定时发送被勾选时if(arg1){//定时器启动m_timer.start(ui->lineEdit->text().toInt());}//当定时发送未被勾选时else{//定时器停止m_timer.stop();}
}/** 函数功能:定时时间到时,执行串口发送函数*/
void MainWindow::timeUp()
{qDebug() << "timeup";//串口发送函数on_btnSend_clicked();
}
mainwindows.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>#include<QSerialPort>
#include<QDateTime>
#include<QTimer>
#include<QDebug>
#include<QThread>#include"serialportplus.h"QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();//界面初始化函数void initUI();//端口初始化函数void initSerialPort();//界面关闭事件void closeEvent(QCloseEvent *event);private:Ui::MainWindow *ui;//创建一个自定义的串口类对象serialportplus m_serial;//创建一个线程对象QThread m_thread;//创建一个定时器对象QTimer m_timer;signals:// 分别是界面对串口发出的启动、停止和发送数据的信号void sigStart(serialportplus::Settings s);void sigStop();void sigSend(QByteArray data);public slots:// 分别是串口对界面发出的启动、停止和接收数据的信号时,所要执行的操作void started();void stoped(int status);void receiveData(QByteArray data);private slots:void timeUp();void on_btnOpenPort_clicked();void on_btnSend_clicked();void on_checkBox_stateChanged(int arg1);
};
#endif // MAINWINDOW_H
serialportplus.cpp
#include "serialportplus.h"/** 函数功能:对串口接收到数据的信号进行响应,并向界面主线程发送接收到的数据*/
serialportplus::serialportplus()
{//当串口子线程接收到数据时,向界面主线程发出数据接收的信号connect(this, &QSerialPort::readyRead, [this](){qDebug() << QString::fromLocal8Bit ("接收") << QThread::currentThread();//读取串口接收的数据QByteArray arr = readAll();//将数据通过信号发给界面主线程emit sigReceived(arr);});
}/** 函数功能:接收界面主线程发出开始信号,接收串口参数并对设置,* 同时根据串口状态发出启动或停止信号。*/
void serialportplus::startPort(serialportplus::Settings sets)
{/*设置串口参数*/setPortName(sets.name);setParity(sets.parity);setBaudRate(sets.baudRate);setDataBits(sets.dataBits);setStopBits(sets.stopBits);setFlowControl(sets.flowControl);qDebug() << QString::fromLocal8Bit ("启动") <<QThread::currentThread();//判断串口是否处于可读写状态if(open(QIODevice::ReadWrite)){//串口处于可读写状态,发出向界面主线程启动信号emit sigStarted();}else{//串口不处于可读写状态,发出向界面主线程停止信号emit sigStop(1);}
}/** 函数功能:接收界面主线程发送的停止信号,串口关闭*/
void serialportplus::stopPort()
{qDebug() << QString::fromLocal8Bit ("停止") <<QThread::currentThread();//判断串口是否关闭if(isOpen()){//关闭串口close();}//向界面主线程发出停止信号emit sigStop(0);
}/** 函数功能:接收界面主线程发出的数据发送信号,串口进行数据发送*/
void serialportplus::sendData(QByteArray arr)
{qDebug() << QString::fromLocal8Bit ("发送") <<QThread::currentThread();//判断串口是否关闭if(isOpen()){//发送数据write(arr);}
}
serialportplus.h
#ifndef SERIALPORTPLUS_H
#define SERIALPORTPLUS_H#include <QSerialPort>
#include<QThread>
#include<QDebug>class serialportplus : public QSerialPort
{Q_OBJECT
public://串口接收数据的函数serialportplus();//串口设置struct Settings{QString name;//端口名称COM1、COM2BaudRate baudRate;//波特率DataBits dataBits;//数据位Parity parity;//奇偶校验StopBits stopBits;//停止位FlowControl flowControl;//流控制};public slots:// 分别是界面对串口发出的启动、停止和发送数据的信号时,所要执行的操作void startPort(Settings sets);void stopPort();void sendData(QByteArray arr);signals:// 分别是串口对界面发出的启动、停止和接收数据的信号void sigStarted();void sigStop(int status);void sigReceived(QByteArray data);
};#endif // SERIALPORTPLUS_H