串口通信
一、串口通信原理
处理器与外部设备通信的方式有串行通信和并行通信的方式,串口通信是串行通信。
同步通信:带有时钟同步信号的数据传输。发送端和接收端在同一时钟的控制下,同步传输数据。
异步通信:不带有时钟同步信号的数据传输。发送端和接收端使用各自不同的时钟控制数据的发送和接收过程。
单工模式:数据传输是单向的,通信双方中,一方固定为发送端,一方固定为接收端,信息只能沿一个方向传输,使用一根传输线。
半双工模式:通信使用同一根传输线,既可以发送数据又可以接收数据,但不能同时进行发送和接收。
全双工模式:通信使用同两根传输线,一根作为发送数据,另一根作为接收数据。
波特率:字符帧是按位依次传输,波特率即传输字符帧时的位速率,单位为bit/s。通信双方要使用相同的波特率,常用的波特率如9600、115200。
二、数据格式说明
字符帧由四个部分构成,分别是起始位、数据位、校验位以及停止位。起始位占1位,为逻辑0。数据位占5 ~ 8位,可配置。校验位占1位,可配置为奇校验、偶校验、无校验;配置为无校验时字符帧不包含校验位;配置为奇校验时,数据位中逻辑1的个数为奇数时,校验位的值为逻辑0,否则为逻辑1;配置为偶校验时,数据位中逻辑1的个数为偶数时,校验位的值为逻辑0,否则为逻辑1。停止位占1/1.5/2位,可配置,停止位的值为逻辑1。常用的字符帧格式如下图1.1所示,1位起始位、8位数据位、1位校验位、1位停止位。
三、配置虚拟串口环境
1.安装虚拟串口驱动程序,添加一对虚拟串口。(若成功可以通过设备管理查看添加的串口)
2.使用串口调试工具根据配对的虚拟串口,分别作为收、发端进行收发数据试验。
四、QT实现串口通信
头文件:
#ifndef SERIALPORT_H #define SERIALPORT_H #include <QObject> #include <QSerialPort> #include <QSerialPortInfo> class SerialPort : public QObject { Q_OBJECT public: explicit SerialPort(QObject *parent = nullptr); QStringList getPortNumList(); bool initSerial(const QString &portName, int baudRate, int dataBit, int parityBit, int stopBit); QString getError(); qint64 sendData(const QByteArray &data); signals: void sglSerialData(const QByteArray &data); private: QSerialPort m_qSerialPort; }; #endif // SERIALPORT_H
源文件:
#include "SerialPort.h" #include <QDebug> SerialPort::SerialPort(QObject *parent) : QObject{parent} { } QStringList SerialPort::getPortNumList() { QStringList portNumList; foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { // qDebug() << "Name : " << info.portName(); // qDebug() << "Description : " << info.description(); // qDebug() << "Manufacturer: " << info.manufacturer(); // qDebug() << "Serial Number: " << info.serialNumber(); // qDebug() << "System Location: " << info.systemLocation(); portNumList.append(info.portName()); } return portNumList; } bool SerialPort::initSerial(const QString &portName, int baudRate, int dataBit, int parityBit, int stopBit) { m_qSerialPort.setPortName(portName); switch (baudRate) { case QSerialPort::Baud115200: m_qSerialPort.setBaudRate(QSerialPort::Baud115200); break; default: return false; } switch (dataBit) { case QSerialPort::Data8: m_qSerialPort.setDataBits(QSerialPort::Data8); break; default: return false; } switch (parityBit) { case QSerialPort::NoParity: m_qSerialPort.setParity(QSerialPort::NoParity); break; default: return false; } switch (stopBit) { case QSerialPort::OneStop: m_qSerialPort.setStopBits(QSerialPort::OneStop); break; default: return false; } if(!m_qSerialPort.setFlowControl(QSerialPort::NoFlowControl)) { return false; } if(m_qSerialPort.open(QIODevice::ReadWrite)) { connect(&m_qSerialPort, &QSerialPort::readyRead, this, [=](){ emit sglSerialData(m_qSerialPort.readAll()); }); return true; } else { return false; } } QString SerialPort::getError() { return QString("error code:%1").arg(m_qSerialPort.error()); } qint64 SerialPort::sendData(const QByteArray &data) { return m_qSerialPort.write(data); }
坚持成就伟大