一、前言

开发环境:Qt5.12.10 + MinGW

  • 串口数据的发送
  • ascii字符与hex字符的相互转换
  • 自动追加回车换行符(\r\n)
  • 发送数据的统计与显示
  • 发送清零
  • 定时发送
  • QSerialPort类的使用
  • 数据格式的转换
  • QTimer类的使用
  • 控件QPlainTextEditQCheckBoxQPushButtonQLabel的使用

QT串口助手(四):数据发送-LMLPHP

二、功能实现

《QT串口助手(三):数据接收》实现了接收模块的功能,本章讲解发送模块的各个功能。

2.1、字符判断

若勾选了HEX格式发送,那么需要对发送框的字符进行合法判断。这里使用到QPlainTextEdittextChanged信号来监测发送框数据的改变,在槽函数中对数据进行判别:

/*发送文本框信号槽*/
connect(ui->Send_TextEdit, &QPlainTextEdit::textChanged, this, [=](){
    //获取发送框字符
    SendTextEditStr = ui->Send_TextEdit->document()->toPlainText();
    if (SendTextEditStr.isEmpty())
    {
        return;
    }
    //勾选hex发送则判断是否有非法hex字符
    if (ui->HexSend_checkBox->isChecked())
    {
        char ch;
        bool flag = false;
        uint32_t i, len;
        //去掉无用符号
        SendTextEditStr = SendTextEditStr.replace(' ',"");
        SendTextEditStr = SendTextEditStr.replace(',',"");
        SendTextEditStr = SendTextEditStr.replace('\r',"");
        SendTextEditStr = SendTextEditStr.replace('\n',"");
        SendTextEditStr = SendTextEditStr.replace('\t',"");
        SendTextEditStr = SendTextEditStr.replace("0x","");
        SendTextEditStr = SendTextEditStr.replace("0X","");
        //判断数据合法性
        for(i = 0, len = SendTextEditStr.length(); i < len; i++)
        {
            ch = SendTextEditStr.at(i).toLatin1();
            if (ch >= '0' && ch <= '9') {
                flag = false;
            } else if (ch >= 'a' && ch <= 'f') {
                flag = false;
            } else if (ch >= 'A' && ch <= 'F') {
                flag = false;
            } else {
                flag = true;
            }
        }
        if(flag) QMessageBox::warning(this,"警告","输入内容包含非法16进制字符");
    }
    //QString转QByteArray
    SendTextEditBa = SendTextEditStr.toUtf8();
});

这样我们在进行输入时,如果包含非法字符就会有弹框提示(我这里对','、"0x"、"0X"等字符过滤是为了方便有时从代码中直接复制数组数据发送):

QT串口助手(四):数据发送-LMLPHP

2.2、数据转换

通过是否勾选HEX发送判断使用ascii格式还是hex格式发送数据,使用QCheckBoxstateChanged信号对勾选状态进行检测,然后在对应的槽函数中进行数据格式的转换。

/*HEX发送chexkBox信号槽*/
connect(ui->HexSend_checkBox,&QCheckBox::stateChanged,this,[=](int state){
    if (SendTextEditStr.isEmpty())
    {
        return;
    }
    //asccii与hex转换
    if (state == Qt::Checked)
    {
        //转换成QByteArray -> 转换成16进制数,按空格分开 -> 转换为大写
        SendTextEditBa = SendTextEditBa.toHex(' ').toUpper();
        ui->Send_TextEdit->document()->setPlainText(SendTextEditBa);
    }
    else
    {
        //从QByteArray转换为QString
        SendTextEditStr = SendTextEditBa.fromHex(SendTextEditBa);
        ui->Send_TextEdit->document()->setPlainText(SendTextEditStr);
    }
});

QT串口助手(四):数据发送-LMLPHP

2.3、手动发送

当点击发送按钮时触发QPushButton的点击信号,在对应的槽函数中将发送框的数据按照选定格式发送出去,程序主体如下:

/*
    函   数:on_Send_Bt_clicked
    描   述:发送按键点击槽函数
    输   入:无
    输   出:无
*/
void Widget::on_Send_Bt_clicked()
{
    if (isSerialOpen != false)
    {
        /*将发送框数据发送*/
        SerialSendData(SendTextEditBa);
    }
    else
    {
        QMessageBox::information(this, "提示", "串口未打开");
    }
}
/*
    函   数:SendData
    描   述:串口发送数据
    输   入:无
    输   出:无
*/
void Widget::SerialSendData(QByteArray baData)
{
    if (baData.isEmpty() != true)
    {
        /*是否加回车换行*/
        if (ui->AddNewLine_Box->isChecked())
        {
            baData.append("\r\n");
        }

        if (ui->HexSend_checkBox->isChecked())  // hex发送
        {
            /*获取hex格式的数据*/
            baData = baData.fromHex(baData);
            /*发送hex数据*/
            serial->write(baData);
            /*是否显示时间戳*/
            if (ui->TimeDisp_checkBox->isChecked())
            {
                QString strdata = baData.toHex(' ').trimmed().toUpper();
                ui->Receive_TextEdit->setTextColor(QColor("blue"));
                ui->Receive_TextEdit->append(QString("[%1]TX -> ").arg(QTime::currentTime().toString("HH:mm:ss:zzz")));
                ui->Receive_TextEdit->setTextColor(QColor("black"));
                ui->Receive_TextEdit->insertPlainText(strdata);
            }
        }
        else     //ascii发送
        {
            /*发送ascii数据*/
            serial->write(baData);
            /*是否显示时间戳*/
            if (ui->TimeDisp_checkBox->isChecked())
            {
                QString strdata = QString(baData);
                ui->Receive_TextEdit->setTextColor(QColor("red"));
                ui->Receive_TextEdit->append(QString("[%1]TX -> ").arg(QTime::currentTime().toString("HH:mm:ss:zzz")));
                ui->Receive_TextEdit->setTextColor(QColor("black"));
                ui->Receive_TextEdit->insertPlainText(strdata);
            }
        }
        //移动光标到末尾
        ui->Receive_TextEdit->moveCursor(QTextCursor::End);
        //更新发送计数
        serialDataTotalTxCnt += baData.length();
        ui->TxCnt_label->setText(QString::number(serialDataTotalTxCnt));
    }
    else
    {
        QMessageBox::warning(this, "警告", "数据为空");
    }
}

如果勾选了显示时间戳则在每次数据发送后将数据填充到接收框进行显示;代码中对发送的不同格式数据进行了不同颜色的标记;发送后对发送计数框进行更新。

QT串口助手(四):数据发送-LMLPHP

2.4、定时发送

使用QT中的定时器QTimer按照设定的时间对发送框数据进行自动发送。调用定时器的超时信号来触发槽函数中的发送操作:

/*定时发送定时器*/
TimerSend = new QTimer(this);
/*定时器超时信号槽*/
connect(TimerSend, &QTimer::timeout, this, [=](){
    SerialSendData(SendTextEditBa);
});

定时发送被勾选后,会触发QCheckBoxstateChanged信号来设定时间、开启定时器:

/*
    函   数:on_TimeSend_checkBox_stateChanged
    描   述:定时发送框勾选信号对应槽函数
    输   入:无
    输   出:无
*/
void Widget::on_TimeSend_checkBox_stateChanged(int arg1)
{
    int time;

    /*判断串口是否打开*/
    if (false == isSerialOpen)
    {
        if (ui->TimeSend_checkBox->isChecked())
        {
            QMessageBox::information(this, "提示", "串口未打开");
        }
        return;
    }
    /*判断是否有数据*/
    if (ui->Send_TextEdit->document()->isEmpty() == true)
    {
        if (ui->TimeSend_checkBox->isChecked())
        {
            QMessageBox::warning(this, "警告", "数据为空");
        }
        return;
    }
	/*判断勾选状态*/
    if (arg1 == Qt::Checked)
    {
        /*获取设定时间*/
        time = ui->TimeSend_lineEdit->text().toInt();
        if (time > 0) {
            TimerSend->start(time);
        } else {
            QMessageBox::warning(this, "警告", "时间必须大于0");
        }
        ui->TimeSend_lineEdit->setEnabled(false);
    }
    else
    {
        /*停止发送*/
        TimerSend->stop();
        ui->TimeSend_lineEdit->setEnabled(true);
    }
}

QT串口助手(四):数据发送-LMLPHP

三、总结

本章主要讲解数据的发送与格式转换。除了要知道各控件的信号槽应用之外,还应该对QT中数据类型的一些操作方法有所了解。比如上面的代码中使用到的一些QStringQByteArray的常用数据操作方法:QString::replaceQString::atQString::toUtf8QByteArray::toHexQByteArray::fromHex等。

01-31 03:56
查看更多