串口封装

1、头文件

#ifndef MYSERIAL_H
#define MYSERIAL_H#include <QSerialPort>
#include "mymethod.h"
class MySerial : public QSerialPort
{
    Q_OBJECT

public:
    MySerial(QObject *parent);
    ~MySerial();

private:
    QSerialPort* serialPort = NULL;//串口对象
    QByteArray HEAD;//报文头
    void init();//初始化private slots:
    void openSlot(SerialPortInfo serialPortInfo);//连接函数
    void rcvSlot();//接收数据槽函数
    void sendSlot(QByteArray ba);//发送数据槽函数
    void closeSlot();//关闭槽函数

signals:
    void serialStateSignal(QString info);//向外发出的调试信息
    void getPacketSignal(int type, QByteArray ba);//tcp将不同的包发出去
};

#endif // MYSERIAL_H

2、源文件

#include "myserial.h"

MySerial::MySerial(QObject *parent)
: QSerialPort(parent)
{
    this->init();
}

MySerial::~MySerial()
{

}


/*****************************************************************/
//作者:朱小勇
//函数名称:初始化
//函数参数:NULL
//函数返回值:NULL
//函数作用:NULL
//备注:NULL
/*****************************************************************/
void MySerial::init()
{
    HEAD.resize(2); HEAD[0] = 0x55; HEAD[1] = 0xAA;
}

/*****************************************************************/
//作者:朱小勇
//函数名称:打开串口
//函数参数:NULL
//函数返回值:NULL
//函数作用:NULL
//备注:NULL
/*****************************************************************/
void MySerial::openSlot(SerialPortInfo serialPortInfo)
{
    if (NULL == serialPort)
    {
        serialPort = new QSerialPort();
        QObject::connect(serialPort, SIGNAL(readyRead()), this, SLOT(rcvSlot()));
    }
    if (serialPort->isOpen())
    {
        return;
    }
    serialPort->setPortName(serialPortInfo.portName);
    serialPort->setBaudRate(serialPortInfo.baudRate, QSerialPort::AllDirections);
    serialPort->setDataBits(serialPortInfo.dataBits);//数据位
    serialPort->setParity(serialPortInfo.parity);//校验位
    serialPort->setStopBits(serialPortInfo.stopBits);//停止位
    serialPort->setFlowControl(QSerialPort::NoFlowControl);//流控制
    if (serialPort->open(QIODevice::ReadWrite))//打开串口
    {
        emit serialStateSignal("串口打开成功...");
    }
    else
    {
        emit serialStateSignal("串口打开失败!!!");
    }
}

/*****************************************************************/
//作者:朱小勇
//函数名称:接收数据
//函数参数:NULL
//函数返回值:NULL
//函数作用:NULL
//备注:NULL
/*****************************************************************/
void MySerial::rcvSlot()
{
    static QByteArray allBa;//用来存所有文件
    allBa.append(serialPort->readAll());//读取数据
    int head = allBa.indexOf(HEAD);//报文头的位置
    uint16_t length = 0;//存长度字节
    QByteArray currentBa;
    int id = 0;
    while (-1 != head)
    {
        allBa = allBa.mid(head);//去掉报头之前的
        memcpy(&length, allBa.data() + 2, 2);
        if (allBa.size() >= length)//长度够,进行解析
        {
            currentBa = allBa.mid(0, length);//获取当前完成包
            id = Mymethod::getPacketType(currentBa);
            if (-1 != id)
            {
                emit getPacketSignal(id, currentBa);
            }
            allBa = allBa.mid(2);
        }
        else
        {
            break;
        }
        head = allBa.indexOf(HEAD);//刷新报文头的位置
    }
}

/*****************************************************************/
//作者:朱小勇
//函数名称:发送
//函数参数:NULL
//函数返回值:NULL
//函数作用:NULL
//备注:NULL
/*****************************************************************/
void MySerial::sendSlot(QByteArray ba)
{
    if (NULL == serialPort)
    {
        emit serialStateSignal("串口未初始化!!!");
        return;
    }
    if (!serialPort->isOpen())
    {
        emit serialStateSignal("串口未打开!!!");
        return;
    }
    if (ba.size() != serialPort->write(ba))
    {
        emit serialStateSignal("指令发送失败!!!");
    }
    else
    {
        emit serialStateSignal("发送指令成功...");
    }
}

/*****************************************************************/
//作者:朱小勇
//函数名称:关闭
//函数参数:NULL
//函数返回值:NULL
//函数作用:NULL
//备注:NULL
/*****************************************************************/
void MySerial::closeSlot()
{
    if (NULL == serialPort)
    {
        return;
    }
    serialPort->close();
    emit serialStateSignal("已关闭串口...");
}

3、自定义函数,获取报文类型

int Mymethod::getPacketType(const QByteArray& ba)
{
    int result = -1;
    uint16_t length = 0;
    if ((ba[0] == (char)0x55) && (ba[1] == (char)0xAA))//报文头正确
    {
        memcpy(&length, ba.data() + 2, 2);
        if (length == ba.size())//长度正确
        {
            QByteArray tempBa; tempBa.resize(ba.size() - 1);
            memcpy(tempBa.data(), ba.data(), ba.size() - 1);
            char crc = Mymethod::CRC(tempBa);
            if (crc == ba[ba.size() - 1])//CRC正确
            {
                result = (int)ba[4];
            }
        }
    }
    return result;
}

 

转载于:https://www.cnblogs.com/judes/p/9530522.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Visual 串口封装库是一种用于在Windows操作系统上进行串口通信的软件开发库。它提供了一套方便易用的函数和类,来实现串口设备的连接、读写操作以及配置参数的设置等功能。 Visual 串口封装库的使用具有以下特点: 1. 方便易用:Visual 串口封装库提供了简洁明了的函数和类,使得开发者能够以简单且直观的方式进行串口通信的代码编写。无论是连接串口、写入数据还是读取数据,都能够轻松实现。 2. 功能丰富:Visual 串口封装库支持多种串口操作,例如设置波特率、数据位、停止位和校验位等。此外,还支持流控制功能,如硬件流控和软件流控,以满足不同应用场景的需求。 3. 可靠稳定:Visual 串口封装库在封装底层串口API的基础上,对异常情况进行了处理和封装,从而提高了代码的可靠性和稳定性。无论是串口连接中断、读写失败还是其他异常情况,都能够及时捕获并进行相应的处理。 4. 跨平台性:Visual 串口封装库在Windows操作系统上使用广泛,并且与主流的开发环境(如Visual Studio)兼容。这使得开发者能够在不同版本的Windows系统上进行串口通信的开发,提高了代码的可移植性。 综上所述,Visual 串口封装库是一款功能强大、易用可靠的串口通信开发库。它能够帮助开发者快速实现串口通信功能,并且适用于各种不同的应用场景,是进行串口通信开发的理想选择。 ### 回答2: visual 串口封装库是一个用于简化串口通信的库。它提供了一系列的函数和类,可以方便地进行串口的打开、关闭、读取和写入操作。 该库的设计目标是使串口通信变得更加简单易用。它的封装屏蔽了底层的复杂性,只需要简单地调用库中提供的函数和方法即可完成串口通信的操作。这样,即使对串口编程不太熟悉的开发人员也能够快速上手。 visual 串口封装库提供了一些常用的功能,比如设置串口的波特率、数据位、停止位和校验位等。它还可以进行串口的数据读取和写入操作,用户可以通过调用相应的函数或方法来完成这些操作。同时,该库还提供了一些高级功能,如事件驱动机制和缓冲区管理,可用于处理复杂的串口通信场景。 由于visual 串口封装库是基于C++开发的,因此它具有良好的跨平台性。不论是在Windows、Linux还是其他操作系统上,只要有对应的编译器和串口驱动程序,就可以使用该库进行串口通信的开发。 总之,visual 串口封装库是一个方便实用的工具,可以大大简化串口通信的开发工作。无论是初学者还是有经验的开发人员,都可以借助该库快速地实现串口通信功能。 ### 回答3: visual串口封装库是一种能够简化串口通信操作的软件工具。它能够将复杂的串口通信过程封装成简单易用的接口,方便开发人员进行串口通信相关的程序编写。 首先,visual串口封装库提供了一系列的函数和方法,用于打开串口、设置串口参数、发送和接收数据等操作。开发人员只需要调用对应的函数,就可以实现串口的开启和关闭,以及数据的发送和接收等功能。这样,开发人员无需关注底层的串口通信细节,极大地简化了串口通信的编程难度。 其次,visual串口封装库还提供了丰富的错误处理机制,对异常情况进行了处理,保证了程序的稳定性和可靠性。当发生错误时,封装库能够提供详细的错误提示信息,帮助开发人员快速定位和解决问题。 此外,visual串口封装库还支持多线程和事件驱动的编程模式,使得开发人员能够更加灵活地处理串口通信相关的任务。通过多线程,可以实现同时与多个串口进行通信;而通过事件驱动,可以响应串口收到数据的事件,及时做出相应的处理。 综上所述,visual串口封装库通过简化串口通信操作,提供了易用、稳定的接口,帮助开发人员快速开发串口通信相关的应用程序。无论是在嵌入式系统开发、数据采集、串口设备通信等领域,visual串口封装库都是一种非常实用的工具。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值