Qt之串口通信(各配置参数测试)

串口的数据格式为:

规定传输的数据格式由起始位(start bit)、数据位(data bit)、奇偶校验位(parity bit)和停止位(stop bit)组成,如图1所示(该图中未画出奇偶校验位,因为奇偶检验位不是必须有的,如果有奇偶检验位,则奇偶检验位应该在数据位之后,停止位之前)。

(1)起始位:起始位必须是持续一个bit时间的逻辑0电平,标志传输一个字符的开始,接收方可用起始位使自己的接收时钟与发送方的数据同步。

(2)数据位:数据位紧跟在起始位之后,是通信中的真正有效信息。数据位的位数可以由通信双方共同约定,一般可以是5位、7位或8位,标准的ASCII码是0~127(7位),扩展的ASCII码是0~255(8位)。传输数据时先传送字符的低位,后传送字符的高位。

(3)奇偶校验位:奇偶校验位仅占一位,用于进行奇校验或偶校验,奇偶检验位不是必须有的。如果是奇校验,需要保证传输的数据总共有奇数个逻辑高位;如果是偶校验,需要保证传输的数据总共有偶数个逻辑高位。举例来说,假设传输的数据位为01001100,如果是奇校验,则奇校验位为0(要确保总共有奇数个1),如果是偶校验,则偶校验位为1(要确保总共有偶数个1)。由此可见,奇偶校验位仅是对数据进行简单的置逻辑高位或逻辑低位,不会对数据进行实质的判断,这样做的好处是接收设备能够知道一个位的状态,有可能判断是否有噪声干扰了通信以及传输的数据是否同步。

(4)停止位:停止位可以是是1位、1.5位或2位,可以由软件设定。它一定是逻辑1电平,标志着传输一个字符的结束。这里所说的位并不是bit,所谓的停止位实际上是一个时间长度。这个时间长度与串口通信的波特率有关,通信所用波特率的倒数值即为1位,它在实际中表示为一个时间段。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。

(5)空闲位:空闲位是指从一个字符的停止位结束到下一个字符的起始位开始,表示线路处于空闲状态,必须由高电平来填充。

串口数据的发送和接收

3.1、发送数据的具体步骤如下

  1. 初始化后或者没有数据需要发送时,发送端输出逻辑1,可以有任意数量的空闲位;
  2. 当需要发送数据时,发送端首先输出逻辑0,作为起始位;
  3. 接着开始输出数据位,发送端首先输出数据的最低位D0,然后是D1,最后是数据的最高位;
  4. 如果设有奇偶检验位,发送端输出检验位;
  5. 最后,发送端输出停止位(逻辑1);
  6. 如果没有信息需要发送,发送端输出逻辑1(空闲位),如果有信息需要发送,则转入步骤2;
  7. 如果是以232电平发送的,示波器上看到的发送端信号应是上述数据包取反后的结果(负逻辑);

3.2、接收数据的具体步骤如下,其中假设串口通信的波特率为B(每秒传送数据的位数),则由T=1/B即可得出每发送或者接受一个位所需的时间。发送与接收的波特率必须相同,才能保证发送与接收的同步。

  1. 开始通信时,信号线为空闲(逻辑1),当检测到由1到0的跳变时,开始计数;
  2. 接收端检测到起始位后,隔T时间对输入信号检测一次,把对应的值作为D0位数据;
  3. 再隔T时间,对输入信号检测一次,把对应的值作为D1位数据,直到全部数据位都输入;
  4. 再过T时间,接受奇偶校验位;
  5. 接收到规定的数据位个数和校验位之后,通信接口电路希望收到停止位(逻辑1),若此时未收到逻辑1,说明出现了错误,在状态寄存器中置“帧错误”标志;若没有错误,对全部数据位进行奇偶校验,无校验错时,把数据位从移位寄存器中取出送至数据输入寄存器,若校验错,在状态寄存器中置“奇偶错”标志;
  6. 本帧信息全部接收完,把线路上出现的高电平作为空闲位;
  7. 当信号再次变为低时,开始进入下一帧的检测,重复步骤2~6;

参数代码测试

自己手上暂时没有单片机,就只能用arm板将串口tx和rx连在一起,然后做一个软件做自发自收测试

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QTime>
#include <QDebug>
#include <QTimer>
#include <QSerialPort>
#include <QMainWindow>
#include <QElapsedTimer>
#include <QCoreApplication>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    bool CreateSerialPort(QIODevice::OpenMode model,
                          QSerialPort::BaudRate baudrate,
                          QSerialPort::FlowControl flowCtrl,
                          QSerialPort::DataBits databits,
                          QSerialPort::Parity parity,
                          QSerialPort::StopBits stopbits);
    void CloseSerialPort();
    void WaitTaskInfo(int msec);

public slots:
    QByteArray readData();
    void on_pushButton_clicked();

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

#endif // MAINWINDOW_H

mainwindow.c

#include "mainwindow.h"
#include "ui_mainwindow.h"

const QString portName = "/dev/ttyO1";

//#define data_bit_5  1
#define data_bit_6  1
//#define data_bit_7  1
//#define data_bit_8  1
#if data_bit_5
    #define data_bit        5
    #define data_mask       0x7
    #define port_data_bits      QSerialPort::Data5
#elif data_bit_6
    #define data_bit        6
    #define data_mask       0x3
    #define port_data_bits      QSerialPort::Data6
#elif data_bit_7
    #define data_bit        7
    #define data_mask       0x1
    #define port_data_bits      QSerialPort::Data7
#elif data_bit_8
    #define data_bit 8
    #define data_mask       0x0
    #define port_data_bits      QSerialPort::Data8
#endif

#define serial_port_mode    QIODevice::ReadWrite
#define serial_port_baud    QSerialPort::Baud115200

#define serial_port_flow    QSerialPort::NoFlowControl
//#define serial_port_flow    QSerialPort::HardwareControl
//#define serial_port_flow    QSerialPort::SoftwareControl

#define serial_port_data    port_data_bits

#define serial_port_parity  QSerialPort::NoParity
//#define serial_port_parity  QSerialPort::OddParity
//#define serial_port_parity  QSerialPort::EvenParity

#define serial_port_stop    QSerialPort::OneStop
//#define serial_port_stop    QSerialPort::OneAndHalfStop
//#define serial_port_stop    QSerialPort::TwoStop
//#define serial_port_stop    QSerialPort::UnknownStopBits

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qDebug() << "cur serial port data bit = " << data_bit;
    myCom = new QSerialPort(this);
    if(!CreateSerialPort(serial_port_mode,serial_port_baud,
                         serial_port_flow,serial_port_data,
                         serial_port_parity,serial_port_stop)){
        qDebug() << QString("%1 open fail!!!").arg(portName);
    }else{
        qDebug() << QString("%1 open success!!!").arg(portName);
    }
}

MainWindow::~MainWindow()
{
    CloseSerialPort();
    delete ui;
}

void MainWindow::CloseSerialPort()
{
    if (myCom->isOpen()){
        myCom->close();
    }
}

bool MainWindow::CreateSerialPort(QIODevice::OpenMode model,QSerialPort::BaudRate baudrate,
                                  QSerialPort::FlowControl flowCtrl,QSerialPort::DataBits databits,
                                  QSerialPort::Parity parity,QSerialPort::StopBits stopbits)
{
    myCom->setPortName(portName);
    if (myCom->open(model)) {
        myCom->setBaudRate(baudrate);
        myCom->setFlowControl(flowCtrl);
        myCom->setDataBits(databits);
        myCom->setParity(parity);
        myCom->setStopBits(stopbits);
        QTimer::singleShot(100,this,SLOT(on_pushButton_clicked()));
        return true;
    }
    return false;
}

void MainWindow::WaitTaskInfo(int msec)
{
    QElapsedTimer t;
    t.start();
    while(t.elapsed() < msec)
    {
        QCoreApplication::processEvents();
    }
}

QByteArray  MainWindow::readData()
{
    QByteArray ba = myCom->readAll();
    QByteArray newBa;
    char temp;
    newBa.append(ba.at(0));
    if(ba.at(0) == 0x01){
        newBa = ba;
    }else if(ba.at(0) == 0x02){
        for(int i = 1;i < ba.count();){
            temp = 0x00;
            char h_data = ba.at(i);
            char l_data = ba.at(i+1);
            temp = (h_data << data_bit | l_data);
            i += 2;
            newBa.append(temp);
        }
    }
    return newBa;
}
void MainWindow::on_pushButton_clicked()
{
    QByteArray ba,merge_before_ba,back_ba;
    /* 第一位0x01表示一个字节, 范围0-11111 */
    uchar buff[12] = {0x01,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F};
    uchar buff2[12] = {0x02,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE};
    merge_before_ba.append((char*)buff);
    ba.append((char*)buff);
    qDebug() << "1/write ba = " << ba;
    myCom->write(ba);
    /* delay 1s */
    WaitTaskInfo(1000);
    back_ba = readData();
    qDebug() << "2/read  ba = " << back_ba;
    if(merge_before_ba == back_ba){
        qDebug() << "1/Send and receive successfully!!!";
    }else{
        qDebug() << "1/Send and receive fail!!!";
    }
    /* 第一位0x02表示两个字节, 范围0-1111111111 */
    ba.clear();
    ba.append((char)buff2[0]);
    merge_before_ba.clear();
    merge_before_ba.append((char*)buff2);
    for(int i = 1;i < 11;i++){
        /* 高位在前低位在后 */
        ba.append(buff2[i] >> data_bit);
        /* 清除高三位 */
        ba.append(buff2[i] &= ~(data_mask << data_bit));
    }
    qDebug() << "2/write ba = " << merge_before_ba;
    myCom->write(ba);
    /* delay 1s */
    WaitTaskInfo(1000);
    back_ba = readData();
    qDebug() << "2/read  ba = " << back_ba;
    if(merge_before_ba == back_ba){
        qDebug() << "2/Send and receive successfully!!!";
    }else{
        qDebug() << "2/Send and receive fail!!!";
    }
}

参考:https://blog.csdn.net/weixin_44793491/article/details/107463926?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值