QT实现串口通信(附源码下载)

1 Qextserialport类介绍
     在Qt5之前的版本中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport类,本文章主要是讲解怎样利用此类实现串口通信。

     注意:Qt5发布之前,Qt实现串口通信一般是采用第三方类库qextserialport。Qt5发布后自带了QtSerialPort 能够支持串口通信。

2  文件下载地址

http://blog.csdn.net/wangzhen209/article/details/52605514 

文件内容:

http://blog.csdn.net/wangzhen209/article/details/52605514 

        (实在懒得贴图了,哈哈)

4 串口通信的实现

4.1  声明串口对象 :

Win_QextSerialPort  *myCom;      //Windows系统内
Posix_QextSerialPort *myCom;      //Linux系统内


4.2 串口定义:


//Windows中有两种查询模式,一种polling模式,一种EventDriven模式
myCom = new Win_QextSerialPort("COM1",QextSerialBase::Polling);                 //设置为查询模式
myCom = new Win_QextSerialPort("COM1",QextSerialBase::EventDriven);      //设置为事件模式
//Linux中只有Polling模式
myCom = new Posix_QextSerialPort("/dev/ttyS0",QextSerialBase::Polling);


    事件驱动方式EventDriven就是使用事件处理串口的读取,一旦有数据到来,就会发出readyRead()信号,我们可以关联该信号来读取串口的数据。在事件驱动的方式下,串口的读写是异步的,调用读写函数会立即返回,它们不会冻结调用线程。
    查询方式Polling则不同,读写函数是同步执行的,信号不能工作在这种模式下,而且有些功能也无法实现。但是这种模式下的开销较小。我们需要自己建立定时器来读取串口的数据。
    在Windows下支持以上两种模式,而在Linux下只支持Polling模式。

 4.3 串口打开模式

myCom ->open(QIODevice::ReadWrite);    //打开模式  表示以可读可写的方式打开串口
QIODevice::Unbuffered    0x0020 描述
QIODevice::NotOpen       0x0000  
QIODevice::ReadOnly      0x0001  
QIODevice::WriteOnly     0x0002  
QIODevice::ReadWrite     ReadOnly | WriteOnly  
QIODevice::Append        0x0004  
QIODevice::Truncate      0x0008  
QIODevice::Text          0x0010


4.4 串口的配置函数

myCom->setBaudRate(BAUD9600);          //波特率设置,我们设置为9600
myCom->setDataBits(DATA_8);            //数据位设置,我们设置为8位数据位
myCom->setParity(PAR_NONE);           //奇偶校验设置,我们设置为无校验
myCom->setStopBits(STOP_1);            //停止位设置,我们设置为1位停止位
myCom->setFlowControl(FLOW_OFF);      //控制流
myCom->setTimeout(long);              //设置时间间隔

setTimeout(long)参数决定了Polling查询模式的读取串口的速度。


4.5 串口工作

connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom()));    //EventDriven模式下才能触发readyRead()信号
connect(readTimer,SIGNAL(timeout()),this,SLOT(readMyCom()));  //Polling模式定时器触发timeout()信号
4.6 串口读取数据
QByteArray temp = myCom->readAll();    //返回读取的字节
int byteLen = myCom->bytesAvailable(); //返回串口缓冲区字节数


4.7 串口写数据
myCom -> Write(const char * data, qint64 maxSize );          //
myCom -> Write(const char * data );                          //
myCom -> Write(const QByteArray & byteArray);                //
int byteLen = myCom->bytesToWrite();                        //输出写数据的字节数
//bytesWritten()信号函数来获取已经发送的数据的大小。

5 实际编程

界面如下


  可以看到,我在界面上放了两LlinEedit,用来显示收发的数据,几个PushButton,用来发送数据,清空收发送区,两个Check Box,用来选择是否是HEX发送或HEX接收


MainWindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    static QByteArray QString2Hex(QString str); //转换为16进制函数
    static char ConvertHexChar(char ch);
private slots:
    void ReadMycom();  //读取串口中的数据
    void on_SendButton_clicked();

    void on_Close_clicked();

    void on_ClearReceive_clicked();

    void on_ClearSend_clicked();

private:
    Ui::MainWindow *ui;
    Win_QextSerialPort *myCom;
    QTimer *timer;  //用于声明定时器
};
  私有地几个槽函数我相信看函数的名字也能猜到他们实现什么功能,因此就不赘述。

MainWindow.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    timer=new QTimer(this);
    myCom = new Win_QextSerialPort("COM5",QextSerialBase::Polling); //设置串口的查询模式

    myCom->open(QIODevice::ReadWrite);  //以可读可写的方式打开串口
    if(!myCom->isOpen())
    {
        qDebug("no com open\n");
    }
    //串口参数设置
    myCom->setBaudRate(BAUD115200);
    myCom->setDataBits(DATA_8);
    myCom->setParity(PAR_NONE);
    myCom->setStopBits(STOP_1);
    myCom->setFlowControl(FLOW_OFF);
    //this->ui->SendNumber->setDecMode();
    //设置时间间隔
    myCom->setTimeout(100);
    timer->start(300);


    QObject::connect(timer,SIGNAL(timeout()),
                     this,SLOT(ReadMycom()));

    ui->setupUi(this);
}
  我们的程序是以查询的方式去读取串口中的数据,首先设置定时器,当定时器时间到时,去执行槽函数ReadMycom()函数,该函数的作用是读取串口中的数据。



/*
函数名:
函数功能:读取串口中的数据
函数类型:槽函数
函数返回值:无
*/
void MainWindow::ReadMycom()
{
    int byteLen = myCom->bytesAvailable(); //返回串口缓冲区字节
    if(byteLen<=0) return;  //减小内存占用
    qDebug("byteLen=%d\n",byteLen);
    //串口内有数据才往下继续执行
    QByteArray temp = myCom->readAll();    //返回读取的字节
    this->ui->textEdit->clear();
    if(this->ui->HexShow->isChecked())  //如果是16进制显示
    {
       this->ui->textEdit->setText(temp.toHex());
        //temp.toHex();
    }
    else
    {
       this->ui->textEdit->setText(temp);
    }
    this->ui->ReceiveNumber->display(byteLen);
}

  注意:增加了一个判断

    int byteLen = myCom->bytesAvailable(); //返回串口缓冲区字节

    if(byteLen<=0) return;  //减小内存占用

   如果不这样的话,每次定时读取都会延时,内存占用很高,当然,如果采用事件机制的话,这里不需要任何延时或者判断。


/*
函数名:
函数功能:发送数据
函数类型:槽函数
返回值:无
*/
void MainWindow::on_SendButton_clicked()
{
    QString input=this->ui->SDendData->text();
    QByteArray hexByte;
    if(input.isEmpty())
    {
        qDebug("no message\n");
    }
    else
    {
        if(this->ui->HexSend->isChecked())  //选中16进制发送数据
        {
            hexByte=QString2Hex(input);
            myCom->write(hexByte);
        }
        else
        {
            myCom->write(input.toAscii());
        }
    }
    this->ui->SendNumber->display(input.size());


}

void MainWindow::on_Close_clicked()
{
    close();
}
/*
在测试时发现,当底层硬件发送数据的间隔时间太短时容易在成串口读写数据错误,因为
本程序是使用定时器的方法去读取串口数据
*/

void MainWindow::on_ClearReceive_clicked()
{
    this->ui->textEdit->clear();
}

void MainWindow::on_ClearSend_clicked()
{
    this->ui->SDendData->clear();
}
/*
函数名:
函数功能:将QString类型转换为hex形式
函数类型:
函数参数:
返回值:
*/
QByteArray MainWindow::QString2Hex(QString str)
{
    QByteArray senddata;
    qDebug("QString2Hex\n");
            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].toAscii();
                if(hstr == ' ')
                {
                    i++;
                    continue;
                }
                i++;
                if(i >= len)
                    break;
                lstr = str[i].toAscii();
                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;
}
/*
函数功能:将单个字符串转换为hex
*/
char MainWindow::ConvertHexChar(char ch)
{
    qDebug("ConvertHexChar\n");
    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);
}

  与其他程序相比,本程序实现了HEX发送,当在界面选择HEX发送时,程序就会执行到


  通过调用QString2Hex()函数转为16进制,采用16进制发送的原因是很多单片机只吃16进制数据。



源代码下载地址:

http://download.csdn.net/detail/qq_27312943/9661418


参考资料:

1 http://blog.csdn.net/wangzhen209/article/details/52605514 本文主要是参考这一篇文章,但是原文章中没有给出全部的代码以及实现16进制的发送方式,本文进行了增添。

2 http://blog.csdn.net/huwei2003/article/details/36418471 介绍了有关串口通信的基本知识,对于串口通信不明白的可以参考这篇文章

3 http://www.cnblogs.com/feiyangqingyun/p/3483764.html 


注意事项:

1 在程序中没有采用QT5的QtSerialPort 类主要是我们在一次实际开发当中,调用这个类的一个readall()函数时,明明串口中有数据,但是无法读出来,最后采用了第三方库qextserialport得到了解决。


  • 13
    点赞
  • 127
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Qt是一款跨平台的C++图形界面开发框架,其提供了丰富的功能和类库,方便开发者进行串口通信。下面我将用300字的篇幅为您介绍一种基于Qt串口通信实现源码。 在Qt中,串口通信需要使用QSerialPort类。首先,我们需要在程序中包含QSerialPort头文件。然后,创建一个QSerialPort对象并打开串口: QSerialPort serial; serial.setPortName("COM1"); // 设置串口名称 serial.setBaudRate(QSerialPort::Baud9600); // 设置波特率 serial.setDataBits(QSerialPort::Data8); // 设置数据位数 serial.setParity(QSerialPort::NoParity); // 设置校验位 serial.setStopBits(QSerialPort::OneStop); // 设置停止位 serial.setFlowControl(QSerialPort::NoFlowControl); // 设置流控制 if (serial.open(QIODevice::ReadWrite)) { // 串口打开成功,进行数据通信,如发送数据和接收数据的操作 } else { // 串口打开失败,进行错误处理 } 打开串口后,我们可以使用serial.write()函数向串口发送数据,该函数接收一个QByteArray类型的参数。例如,发送一个字符串"Hello, World!": serial.write("Hello, World!"); 我们可以使用serial.waitForBytesWritten()函数来等待数据发送完成,以防数据丢失。 另外,我们可以使用serial.readyRead()信号来接收串口数据。在槽函数中,我们可以使用serial.readAll()函数来读取串口中所有可用的数据,然后对数据进行处理。 当通信完成后,我们需要关闭串口: serial.close(); 这就是一个简单的Qt串口通信实现源码,当然在实际应用中还可以加入更多的功能,如设置超时时间、错误处理等。希望这能帮到您!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值