1、创建桌面程序

2、在.pro添加串口支持:

#增加串口支持
QT       += serialport

3、在头文件添加串口类

// 提供访问串口的功能
#include <QSerialPort>
// 提供系统中存在的串口信息
#include <QSerialPortInfo>

4、设置界面

qt 做手机android的串口通讯 qt下串口通信_串口

5、头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
// 提供访问串口的功能
#include <QSerialPort>
// 提供系统中存在的串口信息
#include <QSerialPortInfo>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_clearBtn_clicked();

    void on_sendBtn_clicked();

    void on_openBtn_clicked();

    void read_data();

private:
    Ui::MainWindow *ui;
    QSerialPort *serial;
};

#endif // MAINWINDOW_H

6、cpp文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QIODevice>
#include <QComboBox>
#include <QObject>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 查找可用的串口
    // 这个foreach的意思:
    // QSerialPortInfo::availablePorts()返回一个列表,列表里每个个体是const QSerialPortInfo &info
    // 遍历这些info
    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort serial;
        serial.setPort(info);
        // 端口如果可以操作读写的话
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->portBox->addItem(serial.portName());
            serial.close();
        }
    }
    // 波特率菜单默认显示第3项
    ui->baudBox->setCurrentIndex(3);
    // 关闭发送按钮的功能
    ui->sendBtn->setEnabled(false);
    qDebug()<<tr("界面设定成功");
}

MainWindow::~MainWindow()
{
    delete ui;
}
// 清空接收窗口
void MainWindow::on_clearBtn_clicked()
{
    ui->receiveText->clear();
}
// 发送数据
void MainWindow::on_sendBtn_clicked()
{
    serial->write(ui->sendText->toPlainText().toLatin1());
}
// 打开串口
void MainWindow::on_openBtn_clicked()
{

    if(ui->openBtn->text()==tr("打开串口"))
    {
        serial = new QSerialPort;
        // 设置串口名
        serial->setPortName(ui->portBox->currentText());
        // 打开串口
        serial->open(QIODevice::ReadWrite);
        // 设置波特率
        serial->setBaudRate(ui->baudBox->currentText().toInt());
        // 设置数据位数
        switch(ui->bitNumBox->currentIndex())
        {
        case 8:
            serial->setDataBits(QSerialPort::Data8);
            break;
        default:
            break;
        }
        // 设置奇偶校验
        switch(ui->parityBox->currentIndex())
        {
        case 0:
            serial->setParity(QSerialPort::NoParity);
            break;
        default:
            break;
        }
        // 设置停止位
        switch(ui->stopBox->currentIndex())
        {
        case 1:
            serial->setStopBits(QSerialPort::OneStop);
            break;
        case 2:
            serial->setStopBits(QSerialPort::TwoStop);
            break;
        default:
            break;
        }
        // 设置流控制
        serial->setFlowControl(QSerialPort::NoFlowControl);
        // 关闭设置菜单功能
        ui->portBox->setEnabled(false);
        ui->baudBox->setEnabled(false);
        ui->bitNumBox->setEnabled(false);
        ui->parityBox->setEnabled(false);
        ui->stopBox->setEnabled(false);
        ui->openBtn->setText(tr("关闭串口"));
        ui->sendBtn->setEnabled(true);
        // 连接信号槽
        QObject::connect(serial,SIGNAL(readyRead()),this,SLOT(read_data()));
    }else
    {
        // 关闭串口
        serial->clear();
        serial->close();
        serial->deleteLater();
        // 恢复设置功能
        ui->portBox->setEnabled(true);
        ui->baudBox->setEnabled(true);
        ui->bitNumBox->setEnabled(true);
        ui->parityBox->setEnabled(true);
        ui->stopBox->setEnabled(true);
        ui->openBtn->setText(tr("打开串口"));
        ui->sendBtn->setEnabled(false);
    }
}
void MainWindow::read_data()
{
    QByteArray buf;
    buf = serial->readAll();
    if(!buf.isEmpty())
    {
        QString str = ui->receiveText->toPlainText();
        str+=tr(buf);
        ui->receiveText->clear();
        ui->receiveText->append(str);
    }
    buf.clear();
}


7、串口模式1

1起始位,8数据位,1停止位。这就是8-n-1的模式(8数据位,没有校验位,1停止位)

8、16进制传输

写入:

QString str = ui->sendText->toPlainText();// 取出文本

    QByteArray ba = QByteArray::fromHex(str.toLatin1().data());// 直接把字面当作16进制读取,使用fromHex,自动会将这些char两两组成一个字节

    serial->write(ba);// 写入QByteArray

接收:

QByteArray ba = serial->readAll();// 从QSerialPort读取到的是QByteArray

    QString str = ba.toHex().data();// 转为16进制的时候要指定toHex

    ui->receiveText->append(str);

如果觉得这样输出不好认,则可以将每个字节中间用空格隔开(两个字符一个字节),然后小写转大写:

QByteArray ba = serial->readAll();// 从QSerialPort读取到的是QByteArray

    QString str = ba.toHex().data();// 转为16进制的时候要指定toHex

    QString strOut;

    for(int i = 0;i<str.length();i+=2)
    {
        QString s = str.mid(i,2);
        strOut += s;
        strOut += " ";
    }

    ui->receiveText->append(strOut.toUpper());

9、位、字节等计算机信息单位辨析

位(Bit,即比特):最小的计算机信息单位,因为计算机本质上来说只存储0和1,即高电平和低电平,换算成2进制的一个位;

字节(Byte):8个位组成一个字节。用各进制表示:

二进制        十进制        16进制
//__________正数____________
00000000        0                00
00000001        1                01
...
01111111        127            7F
0~127共128个正数
//___________负数____________
11111111        -1                FF(注意这个FF为什么不是代表255?因为他这里包含了符号)
11111110        -2                FE
...
10000000        -128            80

-1~-128共128个负数

所以一个字节可以表示128+128=256个数。

十进制即(-128~127)

16进制没有负数,用补码表示的,即(80~7F)

16进制两位构成一个字节;

16进制每一位占用半个字节;

原码:二进制定点表示法,即最高位为符号位,0表示正,1表示负(原码简单理解就是字面意义的码,比如1就是00000001,2就是00000002);

反码:正数的反码与其原码相同,负数的反码是对其原码逐位取反,但符号位除外;(暂时不要去管反码,免得与其他概念弄混)

补码:正数的补码与其原码相同,负数的补码是其绝对值的原码逐位取反最后加1得到。

计算机数据是用补码表示的。正数的补码就是他的原码,负数的补码是将其原码(取绝对值后的原码)逐位取反加1得到。

比如,一个字节最大应该是01111111,第一位0表示他是正数,他的值是127(其实二进制表示的时候0可能省略,即表示位1111111);

最小应该是10000000(1表示他是负数,而0000000则无疑是最小的),他的值是-128;

11111111表示他是负数(1打头),然后他的值最大,每位都是1,他的值是-1,是最大的负数。

那么看下1和-1的计算机补码表示法是怎么通过原码(字面意义的码)转换得到的:

1->原码(即字面意义的码)->00000001->补码与原码相同

-1->原码(先不管负号,暂时记为1)->00000001->取反->11111110->加1->11111111