qt 串口程序

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QMessageBox>
#include <QDebug>
#include <QTimer>
/***********************************全局变量***********************************/
QDateTime current_date_time;   //获取当前时间
//串口助手
bool EnableTimeFlag;    //使能时间戳
bool HexSendFlag;       //使能Hex发送
bool HexRecvFlag;       //使能Hex接收
bool RnSendFlag;        //使能回车换行
bool SendDisplayFlag;   //发送回显
//网口助手

/****************************************************************************/

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("多功能调试助手");
    ui->lineEdit_STime->setText("1000");
    SerialSetInit();   //串口助手界面初始化
    NetworkInit();     //网口助手初始化

    ui->comboBox_ComType->addItem("UART");
    ui->comboBox_ComType->addItem("USB");
    ui->comboBox_ComType->addItem("TCP/IP");
}


// 串口设置界面初始化
void MainWindow::SerialSetInit()
{
     //使用foreach获取有效的串口信息
     foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
     {
         //这里相当于自动识别串口号之后添加到了cmb,如果要手动选择可以用下面列表的方式添加进去
         Serial.setPort(info);
         if(Serial.open(QIODevice::ReadWrite))
         {
             //将串口号添加到cmb
             ui->comboBox_Port->addItem(info.portName());
             //关闭串口等待人为(打开串口按钮)打开
             Serial.close();
         }
     }
    // 填充波特率
    QStringList Baud;
    Baud<<"1200"<<"2400"<<"4800"<<"9600"<<"19200"<<"38400"<<"115200";
    ui->comboBox_Baud->addItems(Baud);
    // 填充数据位
    QStringList DataBit;
    DataBit<<"5"<<"6"<<"7"<<"8";
    ui->comboBox_DataBit->addItems(DataBit);
    // 填充停止位
    QStringList StopBit;
    StopBit<<"1"<<"1.5"<<"2";
    ui->comboBox_StopBit->addItems(StopBit);
    // 填充效验位
    QStringList CheckBit;
    CheckBit<<"奇效验"<<"偶效验"<<"";
    ui->comboBox_CheckBit->addItems(CheckBit);

    //初始化默认参数
    ui->comboBox_Baud->setCurrentIndex(3); //默认9600
    ui->comboBox_DataBit->setCurrentIndex(3); //默认8bit Data
    ui->comboBox_StopBit->setCurrentIndex(0); //默认1bit Stop
    ui->comboBox_CheckBit->setCurrentIndex(2); //默认 无效验
}

// 网口助手界面初始化
void MainWindow::NetworkInit()
{

    ui->comboBox_StackType->addItem("UDP");
    ui->comboBox_StackType->addItem("TCP Server");
    ui->comboBox_StackType->addItem("TCP Client");

    ui->lineEdit_NetPort->setText("8080");


}

MainWindow::~MainWindow()
{
    delete ui;
}

//串口打开和关闭按钮
void MainWindow::on_pushButton_Open_clicked()
{
    //设置串口号;也就是说打开的是当前显示的串口
    if(ui->comboBox_Port->currentText().isEmpty())
    {
        QMessageBox::information(this,"提示","没有可用的串口");
        return;
    }
    Serial.setPortName(ui->comboBox_Port->currentText());
    if(ui->pushButton_Open->text() == "打开串口")
    {
           if(Serial.open(QIODevice::ReadWrite))//读写方式打开,成功后设置串口
           {
               //设置波特率
               Serial.setBaudRate(ui->comboBox_Baud->currentText().toInt());

               //设置数据位
               switch(ui->comboBox_DataBit->currentText().toInt())
               {
                     case 5:
                             Serial.setDataBits(QSerialPort::Data5);
                     break;
                     case 6:
                             Serial.setDataBits(QSerialPort::Data6);
                     break;
                     case 7:
                              Serial.setDataBits(QSerialPort::Data7);
                     break;
                     case 8:
                              Serial.setDataBits(QSerialPort::Data8);
                     break;
                     default:
                              QMessageBox::information(this,"提示","数据位配置出错");
                              return;
                     break;
               }

               //设置校验位
               if (ui->comboBox_CheckBit->currentText() == "奇效验")
               {
                   Serial.setParity(QSerialPort::OddParity);
               }
               else if (ui->comboBox_CheckBit->currentText() == "偶效验")
               {
                   Serial.setParity(QSerialPort::EvenParity);
               }
               else if (ui->comboBox_CheckBit->currentText() == "")
               {
                   Serial.setParity(QSerialPort::NoParity);
               }

               //设置停止位
               if (ui->comboBox_StopBit->currentText().toFloat() == 1)
               {
                   Serial.setStopBits(QSerialPort::OneStop);
               }
               else if(ui->comboBox_StopBit->currentText().toFloat() == 1.5)
               {
                   Serial.setStopBits(QSerialPort::OneAndHalfStop);
               }
               else if(ui->comboBox_StopBit->currentText().toFloat() == 2)
               {
                   Serial.setStopBits(QSerialPort::TwoStop);
               }

               //设置流控制
               Serial.setFlowControl(QSerialPort::NoFlowControl);
               ui->pushButton_Open->setText("关闭串口");


               //建立串口接收的槽函数
               connect(&Serial,&QSerialPort::readyRead ,this,&MainWindow::ReadRecData);

              // timer0->start(100);

            }
           else//串口打开失败
           {
               QMessageBox::about(NULL, "提示", "打开出错,串口被占用!");
               return ;
           }
    }
    else if(ui->pushButton_Open->text() == "关闭串口")
    {

        Serial.close();//关串口
        ui->checkBox->setChecked(false);
        on_checkBox_clicked(false);
        ui->pushButton_Open->setText("打开串口");
    }
}

void MainWindow::Delay_MSec(unsigned int msec)
{
    QTime _Timer = QTime::currentTime().addMSecs(msec);

    while( QTime::currentTime() < _Timer )

    QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

// 串口接收数据
void MainWindow::ReadRecData()
{
    Delay_MSec(100);
    QByteArray readData = Serial.readAll();//读取串口数据
    QByteArray NewData;
    QString current_date;

   if(!readData.isNull())//将读到的数据显示到数据接收区
   {
       if(HexRecvFlag)  //判断是否使用HEX
       {
           //判断是否使用时间戳
           if(EnableTimeFlag == 1)
           {
               current_date_time = QDateTime::currentDateTime();
               current_date += "[";
               current_date += current_date_time.toString("yyyy-MM-dd hh:mm:ss");
               current_date += "]收->";
               ui->textEdit_Recv->append(current_date.toUtf8() + readData.toHex());
           }
           else
           {
              ui->textEdit_Recv->append(readData.toHex());
           }

       }
       else
       {
           //判断是否使用时间戳
           if(EnableTimeFlag == 1)
           {
               current_date_time = QDateTime::currentDateTime();
               current_date += "[";
               current_date += current_date_time.toString("yyyy-MM-dd hh:mm:ss");
               current_date += "]收->";
               ui->textEdit_Recv->append(current_date.toUtf8() + readData);
           }
           else
           {
               ui->textEdit_Recv->append(readData);
           }
       }

   }
}

//清除接收窗口数据
void MainWindow::on_pushButton_ClearRecv_clicked()
{
   ui->textEdit_Recv->clear();
}

//清除发送窗口数据
void MainWindow::on_pushButton_2_clicked()
{
   ui->textEdit_Send->clear();
}


//将一个字符串转换成十六进制
QByteArray MainWindow::QString2Hex(QString str)
{
    QByteArray senddata;
    int hexdata,lowhexdata;
    int hexdatalen = 0;
    int len = str.length();
    senddata.resize(len/2);
    char lstr,hstr;
    for(int i=0; i<len; )
    {
        hstr=str[i].toLatin1();
        if(hstr == ' ')
        {
            i++;
            continue;
        }
        i++;
        if(i >= len)
        break;
        lstr = str[i].toLatin1();
        hexdata = ConvertHexChar(hstr);
        lowhexdata = ConvertHexChar(lstr);
        if((hexdata == 16) || (lowhexdata == 16))
            break;
        else
            hexdata = hexdata*16+lowhexdata;
        i++;
        senddata[hexdatalen] = (char)hexdata;
        hexdatalen++;
    }
    senddata.resize(hexdatalen);
    return senddata;
}


char MainWindow::ConvertHexChar(char ch)
{
    if((ch >= '0') && (ch <= '9'))
        return ch-0x30;
    else if((ch >= 'A') && (ch <= 'F'))
        return ch-'A'+10;
    else if((ch >= 'a') && (ch <= 'f'))
        return ch-'a'+10;
    else return (-1);
}

//发送数据
void MainWindow::on_pushButton_Send_clicked()
{
    QString DataStr;
    QString NewData;
    QString current_date;

    DataStr = ui->textEdit_Send->toPlainText();
    if(ui->pushButton_Open->text() == "打开串口")
    {
       QMessageBox::information(this,"提示","未打开串口");
       return;
    }
    qDebug() << "push button
";
    printf("push button 
");
    if(HexSendFlag)        //使能Hex发送时
    {
        QStringList strList = DataStr.split(" ", QString::SkipEmptyParts);  //
        QByteArray str_send;

        for(int i = 0;i < strList.size(); i++)
        {
            str_send += QString2Hex(strList[i]);
        }

       ui->checkBox_SendRN->setChecked(false);
       if(EnableTimeFlag)  //判断是否使能时间戳
       {
           current_date_time = QDateTime::currentDateTime();
           current_date += "[";
           current_date += current_date_time.toString("yyyy-MM-dd hh:mm:ss");
           current_date += "]发->";
           NewData = current_date + DataStr;
            if(SendDisplayFlag == 1)
           {
               ui->textEdit_Recv->append(NewData);
           }
       }
       else
       {
          NewData = DataStr;
          if(SendDisplayFlag == 1)
          {
              ui->textEdit_Recv->append(NewData);
          }
       }
       Serial.write(str_send);//写入缓冲区
    }
    else           //不使能Hex发送时
    {
        if(EnableTimeFlag)  //判断是否使能时间戳
        {
            current_date_time = QDateTime::currentDateTime();
            current_date += "[";
            current_date += current_date_time.toString("yyyy-MM-dd hh:mm:ss");
            current_date += "]发->";
            NewData = current_date + DataStr.toUtf8();
            if(SendDisplayFlag == 1)
            {
                ui->textEdit_Recv->append(NewData);
            }
        }
        else
        {
           NewData = DataStr;
           if(SendDisplayFlag == 1)
           {
               ui->textEdit_Recv->append(NewData);
           }
        }
        Serial.write(DataStr.toUtf8());//写入缓冲区
    }

}

//使能时间戳
void MainWindow::on_checkBox_EnableTime_clicked(bool checked)
{
     if(checked == true)
     {
         EnableTimeFlag = 1;
     }
     else
     {
         EnableTimeFlag = 0;
     }
}
//使能定时发送
void MainWindow::on_checkBox_clicked(bool checked)
{
    if(checked == true)
    {
        if(ui->pushButton_Open->text() == "打开串口")
        {
           QMessageBox::information(this,"提示","未打开串口");
           ui->checkBox->setChecked(false);
           return;
        }
        quint32 stime= ui->lineEdit_STime->text().toInt();
        timer_id1 = startTimer(stime);
        ui->lineEdit_STime->setEnabled(false);
    }
    else
    {
       killTimer(timer_id1);
       ui->lineEdit_STime->setEnabled(true);
    }
}

// HEX 接收 按钮
void MainWindow::on_checkBox_HexRecv_clicked(bool checked)
{
    if(checked)
    {
        HexRecvFlag = 1;
    }

    else
        HexRecvFlag = 0;
}
// HEX 发送 按钮
void MainWindow::on_checkBox_HexSend_clicked(bool checked)
{
    if(checked)
        HexSendFlag = 1;
    else
        HexSendFlag = 0;
}
//发送新行 按钮
void MainWindow::on_checkBox_SendRN_clicked(bool checked)
{
    if(checked)
        RnSendFlag = 1;
    else
        RnSendFlag = 0;
}

//发送回显 按钮
void MainWindow::on_checkBox_SendDisplay_clicked(bool checked)
{
    if(checked)
        SendDisplayFlag = 1;
    else
        SendDisplayFlag = 0;
}

//定时器中断
void MainWindow:: timerEvent(QTimerEvent *ev)
{
    if(ev->timerId() == timer_id1)
    {
       on_pushButton_Send_clicked();
    }
}


void MainWindow::on_pushButton_FlushPort_clicked()
{
    ui->comboBox_Port->clear();  //清除串口下拉列表内容
    //使用foreach获取有效的串口信息
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
       //将串口号添加到cmb
       ui->comboBox_Port->addItem(info.portName());
    }
}

github 地址  https://github.com/itachi1121/serial-qt.git

如果打不开串口,可能是权限不够

sudo chmod 666 /dev/ttyUSB0(串口名字)

再重新打开试试

想添加永久权限,方法如下:

1 查看串口信息

$ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 4, 64 Jun  2 18:39 /dev/ttyUSB0

2 查看当前用户名

$ whoami



3 当前用户加入到dialout用户组

sudo usermod -aG dialout username


4 最后重启系统即可

Talk is cheap, show me the code
原文地址:https://www.cnblogs.com/birdBull/p/14376950.html