首页 > 热点

QT开发-串口设备调试工具

河南广播电视台 2023-04-01 06:07:56

这里首先说明一下,这个为什么叫串口设备调试工具而不是串口调试工具,是因为这个工具比网络上的串口调试工具多出了一些真实需要的用来调试设备的功能,首先一点就是大部分的串口调试工具收到数据都是立即返回,这样的数据都是连着的,头一条数据和后一条数据头尾相连,对于调试着来说要看数据非常麻烦,而且在不断有数据过来时,要停下来看数据除非关闭串口,而不能在打开串口的时候看数据,因为不断有数据过来冲掉前面的数据显示,甚至有些还不能最大化等等情况,这个工具是根据将近四年的与硬件通信这块开发工具的切身实际需求量身定做的,还能模拟设备立即回复数据。之前很多QT开发的版本源码分成两套,一套在windows下编译,一套在linux下编译,甚至麻烦,虽然QT5.1之后的版本自带了串口通信类,本人测试过,貌似还有小问题,在快速收发数据时容易卡住,这次带来的源码不用做任何改动即可在多个平台编译。

项目名称:串口设备调试工具


【资料图】

开发环境:WIN7+QT4.7+QT CREATOR2.8+MINGW

已编译通过测试平台:XP、Win7、ubuntu、tiny210

技术实现:通过第三方串口通信类,解析协议并作出处理

基本功能:

1:支持16进制数据发送与接收。

2:支持windows下COM9以上的串口通信。

3:自动加载对应操作系统串口号。

4:实时显示收发数据字节大小以及串口状态。

高级功能:

1:可自由管理需要发送的数据,每次只要从下拉框中选择数据即可,无需重新输入数据。

2:可模拟设备回复数据,需要在主界面开启模拟设备回复数据。当接收到设置好的指令时,立即回复设置的回复指令。例如指定收到0x16 0x00 0xFF 0x01需要回复0x16 0x00 0xFE 0x01,则只需要在SendData.txt中添加一条数据16 00 FF 01:16 00 FE 01即可。

3:可定时发送数据和保存数据到文本文件:,默认间隔5秒钟,可更改间隔时间。

4:在不断接收到大量数据时,可以暂停显示数据来查看具体数据,后台依然接收数据但不处理,无需关闭串口来查看已接收到的数据。

5:每次收到的数据都是完整的一条数据,而不是脱节的,做了延时处理。

6:一套源码随处编译,无需更改串口通信类,已在XP/WIN7/UBUNTU/ARMLINUX系统下成功编译并运行。

如果有更好的建议或者意见,请Q我(517216493),谢谢!

运行截图:

粗略步骤:

第一步:布局好界面,控件命名好,建议用pascal命名法。

第二步:准备unix和windows串口通信第三方类qextserialport.h、qextserialport.cpp、qextserialport_global.h、qextserialport_p.h、qextserialport_unix.cpp、qextserialport_win.cpp。

导入到工程,在pro文件中这样写:

QT       += core gui TARGET = mySerialPortToolsTEMPLATE = app  SOURCES += main.cpp\        qextserialport.cpp\        frmmain.cpp HEADERS += frmmain.h \        qextserialport_global.h \        qextserialport.h \        myhelper.h win32 { SOURCES += qextserialport_win.cpp }unix { SOURCES += qextserialport_unix.cpp } FORMS += frmmain.ui RESOURCES += \    main.qrc MOC_DIR=temp/mocRCC_DIR=temp/rccUI_DIR=temp/uiOBJECTS_DIR=temp/objDESTDIR=bin win32:RC_FILE=main.rc CONFIG += warn_off      #关闭警告

这样的话在不同平台下会自动加载对应平台的cpp实现文件来编译。

第三步:初始化主界面,自动加载对应串口号波特率等信息。

void frmMain::InitForm(){       ReceiveCount=0;    SendCount=0;    IsShow=true;    IsAutoClear=false;    IsHexSend=true;    IsHexReceive=true;    IsDebug=false;     QStringList comList;//串口号    QStringList baudList;//波特率    QStringList parityList;//校验位    QStringList dataBitsList;//数据位    QStringList stopBitsList;//停止位 #ifdef Q_OS_WIN//如果是windows系统    comList<<\"COM1\"<<\"COM2\"<<\"COM3\"<<\"COM4\"<<\"COM5\"<<\"COM6\"          <<\"COM7\"<<\"COM8\"<<\"COM9\"<<\"COM10\"<<\"COM11\"<<\"COM12\"         <<\"COM13\"<<\"COM14\"<<\"COM15\";#else//如果是unix或者其他系统    comList<<\"ttyUSB0\"<<\"ttyUSB1\"<<\"ttyUSB2\"<<\"ttyUSB3\"<<\"ttyUSB4\"<<\"ttyUSB5\"          <<\"ttyS0\"<<\"ttyS1\"<<\"ttyS2\"<<\"ttyS3\"<<\"ttyS4\"<<\"ttyS5\"<<\"ttyS6\"         <<\"ttyS7\"<<\"ttyS8\"<<\"ttyS9\";#endif     ui->cboxPortName->addItems(comList);    ui->cboxPortName->setCurrentIndex(0);     baudList<<\"50\"<<\"75\"<<\"100\"<<\"134\"<<\"150\"<<\"200\"<<\"300\"           <<\"600\"<<\"1200\"<<\"1800\"<<\"2400\"<<\"4800\"<<\"9600\"          <<\"14400\"<<\"19200\"<<\"38400\"<<\"56000\"<<\"57600\"         <<\"76800\"<<\"115200\"<<\"128000\"<<\"256000\";     ui->cboxBaudRate->addItems(baudList);    ui->cboxBaudRate->setCurrentIndex(12);     parityList<<\"无\"<<\"奇\"<<\"偶\"; #ifdef Q_OS_WIN//如果是windows系统    parityList<<\"标志\";#endif     parityList<<\"空格\";     ui->cboxParity->addItems(parityList);    ui->cboxParity->setCurrentIndex(0);     dataBitsList<<\"5\"<<\"6\"<<\"7\"<<\"8\";    ui->cboxDataBit->addItems(dataBitsList);    ui->cboxDataBit->setCurrentIndex(3);     stopBitsList<<\"1\"; #ifdef Q_OS_WIN//如果是windows系统    stopBitsList<<\"1.5\";#endif     stopBitsList<<\"2\";     ui->cboxStopBit->addItems(stopBitsList);    ui->cboxStopBit->setCurrentIndex(0);     //读取数据(采用定时器读取数据,不采用事件,方便移植到linux)    myReadTimer=new QTimer(this);    myReadTimer->setInterval(300);    connect(myReadTimer,SIGNAL(timeout()),this,SLOT(ReadMyCom()));     //发送数据    mySendTimer=new QTimer(this);    mySendTimer->setInterval(5000);    connect(mySendTimer,SIGNAL(timeout()),this,SLOT(WriteMyCom()));     //保存数据    mySaveTimer=new QTimer(this);    mySaveTimer->setInterval(5000);    connect(mySaveTimer,SIGNAL(timeout()),this,SLOT(SaveMyCom()));     //显示日期时间    myTimer=new QTimer(this);    myTimer->start(1000);    connect(myTimer,SIGNAL(timeout()),this,SLOT(SetTime()));     QDate dateNow=QDate::currentDate();    ui->labDate->setText(QString(\"日期:%1\").arg(dateNow.toString(\"yyyy年MM月dd日 dddd\")));     for (int i=1;i<=60;i++)    {        ui->cboxSend->addItem(QString::number(i)+\"秒\");        ui->cboxSave->addItem(QString::number(i)+\"秒\");    }     ui->cboxSave->setCurrentIndex(4);    ui->cboxSend->setCurrentIndex(4);     ui->cboxSend->setEnabled(false);    ui->cboxSave->setEnabled(false);     this->ChangeEnable(false);    this->ReadConfigData();//读取发送数据加载到下拉框    this->ReadSendData();//读取数据转发文件     ui->txtSend->installEventFilter(this);//安装监听器监听发送数据框回车响应}

第四步:采用定时器读取串口数据,其实也可以采用事件机制,在几大平台也测试通过事件来收数据也可以,但是在windows下在快速收发大量数据时候居然会卡住,同样的代码在linux表现很好,不明原因,后面采用定时器读取机制,问题就没有了。

void frmMain::ReadMyCom(){    //这个判断尤为重要,否则的话直接延时再接收数据,空闲时和会出现高内存占用    if (myCom->bytesAvailable()<=0){return;}     myHelper::Sleep(100);//延时100毫秒保证接收到的是一条完整的数据,而不是脱节的    QByteArray buffer=myCom->readAll();     if (IsShow)    {        if (IsHexReceive)        {            QString tempDataHex=myHelper::ByteArrayToHexStr(buffer);            ui->txtDataHex->append(QString(\"接收:%1 时间:%2\")                                   .arg(tempDataHex)                                   .arg(QTime::currentTime().toString(\"HH:mm:ss\")));             if (IsDebug)//2013-8-6增加接收数据后转发数据,模拟设备            {                foreach(QString tempData,SendDataList)                {                    QStringList temp=tempData.split(";");                    if (tempDataHex==temp[0])                    {                        //这里没有跳出循环,有可能一条数据会对应多条数据需要转发                        myCom->write(myHelper::HexStrToByteArray(temp[1]));                    }                }            }        }        else        {            QString tempDataNormal=QString(buffer);            ui->txtDataHex->append(QString(\"接收:%1 时间:%2\")                                   .arg(tempDataNormal)                                   .arg(QTime::currentTime().toString(\"HH:mm:ss\")));             if (IsDebug)//2013-8-6增加接收数据后转发数据,模拟设备            {                foreach(QString tempData,SendDataList)                {                    QStringList temp=tempData.split(";");                    if (tempDataNormal==temp[0])                    {                        //这里没有跳出循环,有可能一条数据会对应多条数据需要转发                        myCom->write(temp[1].toAscii());                    }                }            }        }         ReceiveCount=ReceiveCount+buffer.size();        ui->labReceive->setText(QString(\"接收:%1 字节\").arg(ReceiveCount));    }}void frmMain::WriteMyCom(){    QString str=ui->txtSend->currentText();    if (str==\"\"){ui->txtSend->setFocus();return;}//发送数据为空    if (!myCom->isOpen()) { return; }//串口没有打开     QByteArray outData=str.toAscii();    int size=outData.size();     if (IsHexSend)//转化为16进制发送    {        outData=myHelper::HexStrToByteArray(str);        size=outData.size();        myCom->write(outData);    }    else    {        size=outData.size();        myCom->write(outData);    }     ui->txtDataHex->append(QString(\"发送:%1 时间:%2\")                           .arg(str)                           .arg(QTime::currentTime().toString(\"HH:mm:ss\")));     SendCount=SendCount+size;    ui->labSend->setText(QString(\"发送:%1 字节\").arg(SendCount));     if (IsAutoClear)    {        ui->txtSend->setCurrentIndex(-1);        ui->txtSend->setFocus();    }} void frmMain::SaveMyCom(){    QString tempData=ui->txtDataHex->toPlainText();    if (tempData==\"\"){return;}//如果没有内容则不保存     QDateTime now=QDateTime::currentDateTime();    QString name=now.toString(\"yyyyMMddHHmmss\");    QString fileName=name+\".txt\";     QFile file(fileName);    file.open(QFile::WriteOnly | QIODevice::Text);    QTextStream out(&file);    out<

这里有个细节说下,就是在接收数据函数里面,增加了一个判断if (myCom->bytesAvailable()<=0){return;}如果不这样的话,每次定时读取都会延时,内存占用很高,当然,如果采用事件机制的话,这里不需要任何延时或者判断。

【领 QT开发教程 学习资料, 点击下方链接莬费领取↓↓ ,先码住不迷路~】

点击这里:

QT开发-串口设备调试工具

2023-04-01

安阳市中鼎商砼有限公司|今日看点

2023-04-01

描写战争的文学作品好_描写战争的文学作品?

2023-03-31

北京提升绿色出行比例 推进通勤公交等向环京地区延伸中新社北京分社 世界观焦点

2023-03-31

海带吃多了有什么坏处_吃海带的好处和坏处 世界快播报

2023-03-31

东方财富:子公司东方财富证券收到行政监管措施决定书

2023-03-31

焦点信息:难度堪比“载人登月” 弹匣电池2.0将电池安全提升至全新高度

2023-03-31

宫颈肿瘤是怎么回事?_宫颈肿瘤的症状有哪些|全球短讯

2023-03-31

拓山重工:公司专注于工程机械零部件的研发、生产及销售,可用于挖掘机、推土机等履带式行走机构的机械主机

2023-03-31

洗衣机哪个牌子好tcl(洗衣机哪个牌子好又实惠)

2023-03-31

美国警察工会行政主任,涉从海外运毒入美贩售 当前简讯

2023-03-31

巴萨正在夺冠道路上前进——访巴塞罗那俱乐部主席拉波尔塔 天天时快讯

2023-03-31

全球速读:黄酒是越久的越好吗(黄酒是年数越久越好吗)

2023-03-31

【天天新视野】朱晞颜职级_朱晞颜

2023-03-31

中信金属:中签号出炉 共约70.16万个

2023-03-31

热消息:力星股份:截至2023年3月20日,公司股东人数为16087

2023-03-31

环球观热点:记者专访丨德国记者:“北溪”被炸事件显然是美国人干的

2023-03-31

焦点简讯:衣服有哪些种类(服装分类有哪些)

2023-03-31

千城胜景|河北灵寿:千鸟栖滹沱 碧水映晚霞

2023-03-31

宁夏滩羊火了!从代购到网店销售过亿,这个西北小伙有何秘诀

2023-03-31