QT realiza el asistente de depuración del puerto serie (dos): realiza las funciones básicas del puerto serie

 

Código fuente del proyecto: https://github.com/zhangfls/QT_UartAnalysisTool

 

Anterior:

QT realiza el asistente de depuración en serie (1)

 

Uno, importa la biblioteca

1. Agregue puerto de serie al archivo .pro del proyecto

QT       += core gui
QT       += serialport

2. Introduzca los archivos de encabezado necesarios para la comunicación en serie en qt

#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

Dos, configurar la inicialización del puerto serie

1. Busque puertos serie disponibles.

Al crear un comobox, la lista de puertos serie disponibles se muestra y se utiliza para seleccionar el puerto serie que se conectará durante la configuración.

//查找可用串口,刷新串口信息
void MainWindow::GetAveriablePort()
{
     ui->uartReadPlain->insertPlainText("串口初始化:\r\n");

     //先清除所有串口列表
      ui->portBox->clear();

    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort serial;
        serial.setPort(info);

        if(serial.open(QIODevice::ReadWrite))
        {
            ui->uartReadPlain->insertPlainText("可用:"+serial.portName()+"\r\n");
            ui->portBox->addItem(serial.portName());
            serial.close();
        }
        else
        {
            ui->uartReadPlain->insertPlainText("不可用:"+serial.portName()+"\r\n");
        }
    }
}

 

2. Configure el puerto serie.

(1) La configuración del puerto en serie debe incluir al menos el número de puerto en serie, la velocidad en baudios, el bit de datos, el bit de parada, el bit de paridad y el control de flujo, todos los cuales se pueden configurar llamando a la función de la instancia del puerto en serie. Puede agregar varios comoboxes o cuadros de texto para elegir, o puede configurarlo cuando inicializa de forma predeterminada.

//配置串口初始化
void MainWindow::PortConfigureInit()
{
    //填入串口选项
    ui->rateBox->addItem("115200","115200");
    ui->rateBox->addItem("38400","38400");
    ui->rateBox->addItem("19200","19200");
    ui->rateBox->addItem("9600","9600");

    ui->dataBox->addItem("8",8);
    ui->dataBox->addItem("7",7);

    ui->checkBox->addItem("无校验",0);

    ui->stopBox->addItem("1位",1);
    ui->stopBox->addItem("2位",2);

}

(2) Agregue un botón para abrir y cerrar el puerto serie. Cuando el texto muestre "abrir puerto serie", haga clic para cerrar el puerto serie. La pantalla de texto "Cerrar puerto serie" es lo contrario.
(3) Al abrir el puerto serie, deshabilite todas las casillas de los elementos de configuración para que no se puedan modificar y restaure cuando estén cerrados

//串口开关按钮
void MainWindow::on_openSerialButton_clicked()
{
    //尝试打开串口
    if(ui->openSerialButton->text() == tr("打开串口"))
    {
        if(ui->portBox->currentText() == "" )
        {
            QMessageBox::warning(NULL, "警告", "无可开启串口!\r\n\r\n");
            return;
        }

        serial = new QSerialPort;
        //设置串口名
        serial->setPortName(ui->portBox->currentText());
        //打开串口
        serial->open(QIODevice::ReadWrite);
        //设置波特率
        serial->setBaudRate(ui->rateBox->currentText().toInt());
        //设置数据位
        switch (ui->dataBox->currentData().toInt())
        {
            case 8:
                serial->setDataBits(QSerialPort::Data8);
                break;
            case 7:
                serial->setDataBits(QSerialPort::Data7);
                break;
            default:
                break;
        }
        //设置校验位
        switch (ui->checkBox->currentIndex())
        {
            case 0:
                serial->setParity(QSerialPort::NoParity);
                break;
            default:
                break;
        }
        //设置停止位
        switch(ui->stopBox->currentIndex())
        {
            case 0:
                serial->setStopBits(QSerialPort::OneStop);
                break;
            case 1:
                serial->setStopBits(QSerialPort::TwoStop);
                break;
            default:
                break;
        }
        //设置流控制
        serial->setFlowControl(QSerialPort::NoFlowControl); //设置为无流控制

        //关闭设置菜单使能
        ui->portBox->setEnabled(false);
        ui->dataBox->setEnabled(false);
        ui->checkBox->setEnabled(false);
        ui->stopBox->setEnabled(false);
        ui->rateBox->setEnabled(false);
        ui->openSerialButton->setText("关闭串口");

        fTimeCounter.restart();  //计时器重新计数

        //连接信号和槽函数,串口有数据可读时,调用ReadData()函数读取数据并处理。
        QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
    }
    else
    {
        uartRecDataTimer->stop () ; //定时器停止

        if(serial->isOpen())       //原先串口打开,则关闭串口
        {
            serial->close();
        }

        //释放串口
        delete serial;
        serial = NULL;

        //恢复使能
        ui->portBox->setEnabled(true);
        ui->rateBox->setEnabled(true);
        ui->dataBox->setEnabled(true);
        ui->checkBox->setEnabled(true);
        ui->stopBox->setEnabled(true);
        ui->openSerialButton->setText("打开串口");
    }
}

Tres, lea los datos del puerto serie

1. Para leer datos, cree un temporizador y un temporizador. Debido a que hay dos problemas que deben resolverse, uno es que necesitamos un intervalo de tiempo de espera, que se usa para juzgar la finalización de una recepción cuando el puerto serie no recibe datos durante un cierto período de tiempo, procesa los datos y borra el beneficio. . En segundo lugar, necesitamos un recuento para contar cuánto tiempo se ha recibido continuamente el puerto serie. Incluso si los datos son continuos, debemos juzgar con fuerza la finalización de una recepción en un punto de tiempo fijo, procesar los datos y borrar el beneficio; de lo contrario, el Es posible que los datos nunca se procesen.

1. Inicializa el temporizador

    //设置uart接收缓冲超时定时器
    uartRecDataTimer = new QTimer(this);
    uartRecDataTimer->stop();
    uartRecDataTimer->setInterval(uartRecOvertimeCount*1000);                     //设置定时周期,单位:毫秒
    uartRecDataTimer->setSingleShot(true);                                        //设置为单次触发
    connect(uartRecDataTimer,SIGNAL(timeout()),this,SLOT(uartRec_timeout()));     //设置槽

2. Implemente ReadData. Después de que el temporizador excede un intervalo especificado, el búfer de mejora recibido se fuerza a ser procesado y los datos se colocan en el búfer por el resto del tiempo, y el temporizador se reinicia.

//读取串口接收消息
void MainWindow::ReadData()
{
    //串口可读数据长度
    int byteLen = serial->bytesAvailable();
    if(byteLen < 0)
    {
        return;
    }

    rec_buf_len += byteLen;
    uart_rec_ss.append(serial->readAll());  //读取数据

    //计时器超过最大间隔仍未填入数据,强制填入
    if(fTimeCounter.elapsed() >2000 && uart_rec_ss.size()>0)
    {
        ui->uartReadPlain->moveCursor(QTextCursor::End);        //光标移动到结尾
        ui->uartReadPlain->insertPlainText(uart_rec_ss);
        ui->uartReadPlain->moveCursor(QTextCursor::End);        //光标移动到结尾
        uart_rec_ss.clear();
    }

    //定时器开始工作、定时器重启
    uartRecDataTimer->start();
}

3. La recepción del temporizador se completa (no se reciben datos durante un período de tiempo, el temporizador expira)

Según si se selecciona la marca de tiempo, complete el contenido de los datos e insértelo en el cuadro de texto donde se almacenan los datos

//定时器触发打印串口数据
void MainWindow::uartRec_timeout()
{
    if(!uart_rec_ss.isEmpty())
    {
        curDateTime = QDateTime::currentDateTime();
        ui->uartReadPlain->moveCursor(QTextCursor::End);            //光标移动到结尾

        if(ui->timeZoneCheckBox->isChecked())
        {
            ui->uartReadPlain->insertPlainText("\r\n"+curDateTime.toString("[yyyy-MM-dd hh:mm:ss]")+"R:");
            ui->uartReadPlain->moveCursor(QTextCursor::End);        //光标移动到结尾
            ui->uartReadPlain->insertPlainText(uart_rec_ss);
        }
        else
        {
            ui->uartReadPlain->insertPlainText(uart_rec_ss);
        }
        ui->uartReadPlain->moveCursor(QTextCursor::End);            //光标移动到结尾
        uart_rec_ss.clear();
        fTimeCounter.restart();
        ui->RXLenLabel->setText(QString::number(rec_buf_len)+"bytes");
    }
}

4. Al mismo tiempo, necesitamos una opción para configurar el intervalo de tiempo de espera

(1) Agregar un cuadro de configuración durante la inicialización

    //设置时间输入框只允许使用数字
    ui->overTimeRecEdit->setValidator(new QRegExpValidator(QRegExp("^([0-9]{1,4}(.[0-9]{1,3})?)$")));
    ui->overTimeRecEdit->setText(QString::number(uartRecOvertimeCount));

(2) Configure el intervalo de tiempo de espera durante la operación

//超时间隔设置
void MainWindow::on_overTimeRecEdit_returnPressed()
{
    if(ui->overTimeRecEdit->text().toFloat()>60)
    {
        QMessageBox::warning(NULL,"警告","超时时间不要超过1分钟");
        ui->overTimeRecEdit->setText("0.1");
        return;
    }
    uartRecOvertimeCount = ui->overTimeRecEdit->text().toFloat();
    ui->uartReadPlain->insertPlainText("设置超时时间为:"+QString::number(uartRecOvertimeCount*1000)+"ms");
    uartRecDataTimer->setInterval(uartRecOvertimeCount*1000);                       //设置定时周期,单位:毫秒

    fTimeCounter.restart();
    uartRecDataTimer->start();
}

Cuatro, envía datos

Simplemente envíe datos sin ninguna configuración adicional, simplemente llame a la función de escritura, puede realizar algunos procesos de configuración o verificación de acuerdo con su situación real. Como agregar retorno de carro y salto de línea o algo así

//发送串口数据
void MainWindow::on_sendDataButton_clicked()
{
    //未打开串口则不准发送
    if(ui->openSerialButton->text() == "打开串口")
    {
        QMessageBox::warning(NULL, "警告", "未打开可用串口,无法发送数据!\r\n\r\n");
        return;
    }

    //获取发送的命令,并选择在结尾加上换行,AT的命令结尾必须有回车换行
    QString command = ui->uartWritePlain->toPlainText();
    if(ui->changeLineCheckBox->isChecked())
    {
        command += "\r\n";
    }

    if(ui->timeZoneCheckBox->isChecked())
    {
         curDateTime = QDateTime::currentDateTime();
         ui->uartReadPlain->insertPlainText("\r\n"+curDateTime.toString("[yyyy-MM-dd hh:mm:ss]")+"SEND:"+command);
    }

    send_buf_len += command.length();
    ui->TXLenLabel->setText(QString::number(send_buf_len)+"bytes");

    serial->write(command.toLatin1());
}

En este punto, se completa una herramienta de depuración de puerto serie más básica, lo siguiente es agregarle funciones y optimizaciones

 

Próximo:

QT realiza el asistente de depuración del puerto serie (3)

 

Supongo que te gusta

Origin blog.csdn.net/zhangfls/article/details/109593287
Recomendado
Clasificación