1、创建桌面程序
2、在.pro添加串口支持:
#增加串口支持
QT += serialport
3、在头文件添加串口类
// 提供访问串口的功能
#include <QSerialPort>
// 提供系统中存在的串口信息
#include <QSerialPortInfo>
4、设置界面
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