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
本文参考了以下文章,在此表示感谢:http://blog.csdn.net/u014695839/article/details/50611549