课程设计总结之Qt(3)

串口连接:

要写上位机,必不可少的就是串口的监听,接收到的一定格式的数据,然后读取、写入数据库。本次课程设计的用到的发送格式为"ID=xxx;T=xx.x;H=xx;"接收数据最麻烦就是接收的不完整的数据,导致读取数据库失败,所以发送格式就显得比较重要。只要学会串口的连接,写个串口调试助手也是非常的简单,本次课程设计我就是在程序中嵌入了Qt写的串口调试助手:

串口连接:

新建一个类为serialPort,包含一个QSerialPort的实例serial,头文件和代码:

#include<QtSerialPort/QSerialPort>

serial是QSerialPort的一个实例化

    if("开启串口"==ui->openorclose->text())
    {
        serial.setPortName(ui->port->currentText()); //设置端口
        //设置波特率
        switch (ui->setBaudRate->currentIndex()) {
        case 0:
            serial.setBaudRate(QSerialPort::Baud115200);
            break;
        case 1:
            serial.setBaudRate(QSerialPort::Baud19200);
            break;
        case 2:
            serial.setBaudRate(QSerialPort::Baud9600);
            break;
        case 3:
            serial.setBaudRate(QSerialPort::Baud4800);
            break;
        default:
            break;
        }
        //设置校验位
        switch (ui->setParity->currentIndex()) {
        case 0:
            serial.setParity(QSerialPort::NoParity);
            break;
        case 1:
            serial.setParity(QSerialPort::OddParity);
            break;
        case 2:
            serial.setParity(QSerialPort::EvenParity);
            break;
        default:
            break;
        }
        //设置数据位数
        switch (ui->bit->currentIndex()) {
        case 0:
            serial.setDataBits(QSerialPort::Data8);
            break;
        case 1:
            serial.setDataBits(QSerialPort::Data7);
            break;
        case 2:
            serial.setDataBits(QSerialPort::Data6);
            break;
        default:
            break;
        }
        //设置停止位
        switch (ui->stop->currentIndex()) {
        case 0:
            serial.setStopBits(QSerialPort::OneStop);
            break;
        case 1:
            serial.setStopBits(QSerialPort::TwoStop);
            break;
        default:
            break;
        }
        if(serial.open(QIODevice::ReadWrite)) //打开串口
        {
            serial.setFlowControl(QSerialPort::NoFlowControl); //设置无流控制
            ui->openorclose->setText("关闭串口");
            QMessageBox *tip=new QMessageBox;
            tip->setAttribute(Qt::WA_DeleteOnClose);
            tip->question(this,"提示","串口开启成功",QMessageBox::Ok);
        }
        else
        {
            QMessageBox *tip=new QMessageBox;
            tip->setAttribute(Qt::WA_DeleteOnClose);
            tip->question(this,"警告","串口打开失败",QMessageBox::Ok);
            return;
        }

    }
    else  //关闭串口
    {
        serial.clear();
        serial.close();
        ui->openorclose->setText("开启串口");
    }

接收数据:

可以接收数据时,QSerialPort的实例会产生一个readyRead信号,所以我们需要处理这个信号,才能知道什么时候开始接收数据。

处理QSerialPort实例的信号:

connect(&serial,&QSerialPort::readyRead,this,[=](){
        RecvData();
    });//RecvData是this对象的一个成员函数

RecvData函数实体:

需要在头文件包含#include<QByteArray>

void serialPort::RecvData() //接收数据
{
    static QByteArray buf;
    buf+=serial.readAll();
    if(buf.startsWith("\"")&&buf.endsWith("\"")) //判断数据是否完整
    {
        QString str;
        //str.prepend(buf); //转为Qstring
        str=QString::fromLocal8Bit(buf); //utf-8
        ui->recv_data->clear();//这是一个textEdit
        ui->recv_data->append(str);
    }
    else //不完整数据结束
        return;
    buf.clear();
}

startsWith()是判断字节数组中的开始是否是其参数,是返回true,endsWith()同理。我是判断数据的开头和结束是否和格式一致,一致的则读取,若不一致就抛弃,这仅是适用于该次课程设计,若要通用的串口助手,可以考虑判断结束符"\n\r"是否存在。fromLocal8Bit()可以支持中文的转换,不会出现乱码。

发送数据:

QSerialPort的实例有一个write()方法是用于发送数据的。

void serialPort::SendData()  //发送数据
{
    serial.write(ui->send_data->text().toLocal8Bit()); //转化为utf-8编码
}

自动发送:

Qt有一个QTimer的类,这是一个定时器,当时间溢出时,会产生超时信号,处理这个信号就可以达到自动发送功能。

实例化一个QTimer:

QTimer Timer; //定时器

在serialPort的构造函数中绑定事件:

connect(&Timer,QTimer::timeout,this,SendData); //绑定定时器的超时事件

当然,只有用户选择自动发送时,我们才自动发送。在ui设计器中添加一个复选框CheckBox和一个时间周期输入框LineEdit,当用户勾选时,再自动发送。所以我们需要判断CheckBox的状态,通过他的状态改变再做出相应操作:

    //绑定复选框事件
    connect(ui->checkBox,&QCheckBox::stateChanged,this,[=](){
        if(ui->checkBox->isChecked())
        {
            std::string time_str=ui->time->text().toStdString();//获取输入时间
            const char *time=time_str.c_str(); //转为char*
            while(*time!='\0') //判断输入的时间周期是否为合法的
            {
                if(*time>='0'&&*time<='9')
                    time++;
                else
                {
                    [=](){
                        QMessageBox *tip=new QMessageBox;
                        tip->setAttribute(Qt::WA_DeleteOnClose);
                        tip->question(this,"错误","非法时间",QMessageBox::Ok);
                    }();
                    return;
                }
            }
            ui->send->setEnabled(false); //停止功能
            Timer.start(ui->time->text().toInt()); //开启定时器
        }
        else
        {
            ui->send->setEnabled(true); //恢复功能
            Timer.stop();
        }
    });

至此,一个简单的串口调试助手就可以完成了,建立虚拟串口进行测试:

接收数据:

发送格式为:"xxxxxx"

发送数据:

猜你喜欢

转载自blog.csdn.net/weixin_40850689/article/details/84964129