QT 多线程串口通讯 串口助手

发布于:2022-10-21 ⋅ 阅读:(375) ⋅ 点赞:(0)

前言

模仿XCom写的一个串口助手 没模仿完全 因为帮助页是我不需要的 其次就是协议通讯我也不太懂 所以这2个界面也没有弄
在这里插入图片描述

在这里插入图片描述

1.讲一些个人认为比较麻烦的实现功能

其实如果用QT比较多应该都明白 那么多无非就是一些按钮的功能实现

1.打开跟关闭串口

为什么要说这个 因为我们打开跟关闭串口的时候需要去检查串口的状态 就是isOpen 因为我们其他类无法直接去调用线程对象的open 或是 close 那么就要通过QT的信号与槽 QT的信号与槽是线程安全的 所以去延时给QT跳转到槽函数的时间并查看串口状态

//延时
void PubFunction::Delay_MSec(unsigned int msec)
{
    QTime _Timer = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < _Timer )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
bool SingleTonPort::OpenSerialPort(QStringList msg)
{
    _portObj->SetParValue(msg);

    emit OpenSerialPortSignal();

    //跨线程信号需要时间 所以需要等待30ms才考虑返回串口的状态
    PubFunction::Get()->Delay_MSec(100);

    return _portObj->State();
}

bool SingleTonPort::CloseSerialPort()
{
    emit CloseSerialPortSignal();

    //跨线程信号需要时间 所以需要等待30ms才考虑返回串口的状态
    PubFunction::Get()->Delay_MSec(100);

    return _portObj->State();
}

2.串口接受函数

为什么我觉得这个难 因为这个感觉就跟TcpIP的一样 需要通过包头包尾去处理粘包的感觉 如果我没记错的话 一些关于readyRead的一些讲解 就是实际上不是你每一包来的时候都会触发ReadyRead函数 而是有一个缓冲区 只有缓冲区达到一定量的时候 才会去触发你的readyRead函数 所以你的包发送过来的时候可能是一个粘包的情况 最好的处理方式 我个人认为就是通过包头包尾的方式去分割 因为是串口助手所以对于的是大部分的串口都可以承接 所以不能通过字符串或是长度去定义是不是一个包 只能说这个没做好 目前的处理方式还是选择等待 如果是主线程的串口 那么你可以选择waitforreadyread函数去等待

在这里插入图片描述

void SerialPortThread::readyReadSlot()
{
    PubFunction::Get()->Delay_MSec(_readWaitTime);
    if(_port->bytesAvailable() > 0)
    {
        QByteArray byes = _port->readAll();

        PubFunction::Get()->writeInfo(byes);
        emit SendPortStr(byes);
    }
}

3.导入导出

在这里插入图片描述
在这里插入图片描述
因为有着添加页码等功能 我个人的想法就是需要每一条都是一个独立的对象 而每一个对象里面又需要包含描述 指令 以及一个单选框 我觉得比较方便的方法就是封装成一个类 通过返回类内的对象来索引到他的指令描述以及单选框 然后再点开ModelView的时候就可以通过Get到所有的所有的数据传输到导入导出的列表里面

class PageWidget : public BaseWidget
{
    Q_OBJECT
public:
    PageWidget(QString num,QWidget* parent = nullptr);
    PageWidget(QString num,bool isClicked,QString text,QString description,QWidget* parent = nullptr);
    ~PageWidget();

    QWidget* Init(bool isChlcked = false,QString text = "");
    bool isGetStr(QString& str);
    void isGetTableInfo(bool&,QString&);

    void SetDescription(QString);
    QString GetDescription() const;
    int GetButtonText();

signals:
    void ButtonClicked(QString text);

private:
    QString _num;
    QString _description;
};

PageWidget::PageWidget(QString num, QWidget *parent)
    :BaseWidget(parent),_num(num),_description("")
{
    QHBoxLayout* mLayout = GetHLayout();
    mLayout->addWidget(Init());

    this->setLayout(mLayout);
}

PageWidget::PageWidget(QString num, bool isClicked, QString text, QString description,QWidget* parent)
    :BaseWidget (parent),_num(num),_description(description)
{
    QHBoxLayout* mLayout = GetHLayout();
    mLayout->addWidget(Init(isClicked,text));

    this->setLayout(mLayout);
}

PageWidget::~PageWidget()
{

}

QWidget* PageWidget::Init(bool isChlcked, QString text)
{
    QWidget* pageWidget = new QWidget();
    QHBoxLayout* pageLayout = GetHLayout(5);

    QCheckBox* box = new QCheckBox();
    if(isChlcked)
        box->click();
    box->setObjectName("box");
    QLineEdit* edit = new QLineEdit();
    edit->setText(text);
    edit->setObjectName("edit");
    edit->setFixedWidth(210);
    QPushButton* btn = GetButton(_num,37,24);

    pageLayout->addWidget(box);
    pageLayout->addWidget(edit);
    pageLayout->addWidget(btn);


    this->connect(btn,&QPushButton::clicked,this,[=]()
    {
        const QString text = edit->text();
        emit ButtonClicked(text);
    });

    pageWidget->setLayout(pageLayout);
    return pageWidget;
}

bool PageWidget::isGetStr(QString& str)
{
    QCheckBox* box = this->findChild<QCheckBox*>("box");
    QLineEdit* edit = this->findChild<QLineEdit*>("edit");

    if(box->isChecked())
    {
        str = edit->text();
        return true;
    }
    return false;
}

void PageWidget::isGetTableInfo(bool& isClicked, QString& text)
{
    QCheckBox* box = this->findChild<QCheckBox*>("box");
    QLineEdit* edit = this->findChild<QLineEdit*>("edit");

    isClicked = box->isChecked();
    text = edit->text();
}

void PageWidget::SetDescription(QString description)
{
    _description = description;
}

QString PageWidget::GetDescription() const
{
    return _description;
}

int PageWidget::GetButtonText()
{
    return _num.toInt();
}

4.关联数字键盘

这个也很简单 怕有人不明白 随便讲一下

void MainWidget::keyPressEvent(QKeyEvent *event)
{
    if(_isKeyConnect)
    {
        if(event->key() == Qt::Key_0)
        {
            //dosomething...
        }
}

5.发送以及校验

在这里插入图片描述
因为串口有不同形式的校验方式在发送的时候根据你选择的模式判断即可
因为这玩意找的也比较久…额 验证过crc16 其他没有 但是还是先贴出来吧
都是网上摘抄的

 if(!SingleTonPort::Get()->GetState())
    {
        return;
    }
    if(!isMore)
    {
        if(sendNewLineBox->isChecked())
        {
            qDebug() << text.split("\n");
            text = text.split("\n").last();
        }
    }
    if(text.isEmpty())
    {
        return;
    }
    QByteArray byte1;

    text.remove(" ");
    QString lastStr = "";
    if(_verify == CRC16)
    {
         lastStr = PubFunction::Get()->Crc16(text);
    }
    else if(_verify == CRC8)
    {
        lastStr = PubFunction::Get()->Crc8(text);
    }
    else if(_verify == BBC)
    {
        lastStr = PubFunction::Get()->BccCRC(text);
    }

    if(lastStr != "")
    {
        text += lastStr;
    }

    if(!isMore)
    {
        if(send16Box->isChecked())
        {
            PubFunction::Get()->convertStringToHex(text,byte1);
        }
        else
        {
             byte1 = text.toLatin1();
        }
    }
    else
    {
        if(moreSend16Box->isChecked())
        {
            PubFunction::Get()->convertStringToHex(text,byte1);
        }
        else
        {
             byte1 = text.toLatin1();
        }
    }

//crc16
QString PubFunction::Crc16(QString str)
{
    QByteArray byte1;
    QString removeStr = str;
    removeStr.remove(" ");
    for(int i = 0; i < removeStr.length(); i += 2)
    {
        QString a1 = removeStr.mid(i,2);
        bool ok;
        unsigned int den=a1.toUInt(&ok,16);
        byte1.append(char(den));
    }

    uint16_t crc16 = Crc16(reinterpret_cast<unsigned char*>(byte1.data()),byte1.length());
    QString str1 = QString::number(crc16,16);
    QString high = str1.left(2);
    QString low = str1.right(2);
    QString returnStr = low + high;

    return returnStr;
}

unsigned int PubFunction::Crc16(unsigned char* data, unsigned int length)
{
    int j;
    unsigned int reg_crc=0xFFFF;
    while(length--)
    {
        reg_crc ^= *data++;
        for(j=0;j<8;j++)
        {
            if(reg_crc & 0x01)
            {
                reg_crc=(reg_crc>>1) ^ 0xA001;
            }else
            {
               reg_crc=reg_crc >>1;
            }
        }
    }
    return reg_crc;
}

//crc8
QString PubFunction::Crc8(QString str)
{
    QByteArray byte1;
    QString removeStr = str;
    removeStr.remove(" ");
    for(int i = 0; i < removeStr.length(); i += 2)
    {
        QString a1 = removeStr.mid(i,2);
        bool ok;
        unsigned int den=a1.toUInt(&ok,16);
        byte1.append(char(den));
    }

    quint8 crc8 = Crc8(reinterpret_cast<unsigned char*>(byte1.data()),byte1.length());
    QString str1 = QString::number(crc8,16);

    return str1;
}

quint8 PubFunction::Crc8(unsigned char* p_buffer, unsigned int buf_size)
{
    uint8_t crc = 0;
    if(buf_size <= 0)
    {
        return crc;
    }
    while( buf_size-- )
    {
        for ( uint8_t i = 0x80; i != 0; i /= 2 )
        {
            if ( (crc & 0x80) != 0)
            {
                crc *= 2;
                crc ^= 0x07; // 多项式:X8 + X2 + X + 1
            }
            else
            {
                crc *= 2;
            }

            if ( (*p_buffer & i) != 0 )
            {
                crc ^= 0x07;
            }
        }
        p_buffer++;
    }
    return crc;
}

//异或
QString PubFunction::BccCRC(QString str)
{
    QByteArray byte1;
    QString removeStr = str;
    removeStr.remove(" ");
    for(int i = 0; i < removeStr.length(); i += 2)
    {
        QString a1 = removeStr.mid(i,2);
        bool ok;
        unsigned int den=a1.toUInt(&ok,16);
        byte1.append(char(den));
    }

    quint16 bcc = BccCRC(reinterpret_cast<unsigned char*>(byte1.data()),byte1.length());
    QString str1 = QString::number(bcc,16);

    return str1;
}

quint16 PubFunction::BccCRC(quint8 *data,quint16 len)
{
    quint16 bcc=0;
    for(; len>0;len--){
        bcc ^= *data;
        data++;
    }
    return  ((bcc & 0xff) << 8) | (bcc >> 8);
}

2.总结

其他都比较简单-。-

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到