串口读取的封装类

#pragma once
#include <QObject>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QDebug>
#include <QMutex>
#include <QThread>

#include <QtCore/qglobal.h>

#ifndef BUILD_STATIC
# if defined(BUSINESSMGR_LIB)
#  define BUSINESSMGR_EXPORT Q_DECL_EXPORT
# else
#  define BUSINESSMGR_EXPORT Q_DECL_IMPORT
# endif
#else
# define BUSINESSMGR_EXPORT
#endif




class BUSINESSMGR_EXPORT CSerialPort : public QObject
{
    Q_OBJECT

public:
    // 默认构造函数
    CSerialPort() : m_serial(nullptr), m_icom(0), m_buffer(), m_mutex() {}

    ~CSerialPort();

    //void run() override;

    //CSerialPort(int icom, QObject* parent = nullptr);

    //CSerialPort(const CSerialPort& other);

    //CSerialPort& operator=(const CSerialPort& other);

    bool init(int icom);
    bool setIsOn(bool isOn);
    bool getIsOn();

    void ClosePort();
    void ClosePort(int nName);

    //bool SendData(QByteArray arry);
    //bool DoReadSerial();

    QByteArray PraseData(int len,char MsgCode);

    QString GetPortName();
    bool SendDataBySignal(QByteArray arry);

public slots:
    void readData();
    void SendData(QByteArray arry);
signals:
    void sig_SendData(QByteArray data);


public:
    QSerialPort* m_serial;
    int m_icom;
    QByteArray m_buffer; // 缓冲区用于存放未完整处理的数据
    QMutex m_mutex;
    QThread m_thread;
    bool m_isOn = false;
};

#include "CSerialPort.h"
#define MAXBUFFERLEN 1024*4

//CSerialPort::CSerialPort(int icom, QObject* parent ) : QObject(parent), m_icom(icom), m_buffer(), m_mutex()
//{
//
//    m_serial = new QSerialPort();
//
//    if (m_serial)
//    {
//        m_serial->setPortName("COM" + QString::number(icom)); // 根据实际串口名称设置
//        m_serial->setBaudRate(QSerialPort::Baud9600); // 波特率为9600
//        m_serial->setDataBits(QSerialPort::Data8); // 8个数据位
//        m_serial->setStopBits(QSerialPort::OneStop); // 1个停止位
//        m_serial->setParity(QSerialPort::NoParity); // 无奇偶校验
//        m_serial->setFlowControl(QSerialPort::NoFlowControl);
//
//        connect(m_serial, &QSerialPort::readyRead, this, &CSerialPort::readData);
//    }
//
//
//
//}

//
//CSerialPort::CSerialPort(const CSerialPort& other)
//    : QObject(other.parent()), m_serial(other.m_serial), m_icom(other.m_icom),m_buffer(other.m_buffer), m_mutex()
//{
//
//}
//
//CSerialPort& CSerialPort::operator=(const CSerialPort& other)
//{
//    if (this != &other) 
//    {
//        // 复制其他成员变量
//        m_serial = other.m_serial;
//        m_buffer = other.m_buffer;
//        m_icom = other.m_icom;
//    }
//    return *this;
//
//
//    //if (this != &other) 
//    //{
//    //    // 删除原有的 QSerialPort 对象
//    //    delete m_serial;
//    //    // 深拷贝 QSerialPort 对象
//    //    m_serial = new QSerialPort(other.m_serial);
//    //    m_icom = other.m_icom;
//    //    m_buffer = other.m_buffer; // QByteArray 赋值运算符重载会进行深拷贝
//    //    // 不需要处理互斥量 m_mutex,因为它没有动态分配内存,直接使用默认构造函数即可
//    //}
//    //return *this;
//
//}

void CSerialPort::readData()
{
    if (!m_serial)
        return;

    m_mutex.lock();
    QByteArray responseData = m_serial->readAll();
    m_buffer += responseData; // 将接收到的数据存入缓冲区
    LOGINFO(("[COM%1]Recv:"+ QString(responseData)).arg(m_icom));

    
    m_mutex.unlock();



}

CSerialPort::~CSerialPort()
{
    if (m_serial)
    {
        m_serial->close();

        delete m_serial;
        m_serial = nullptr;
    }
}

//void CSerialPort::run()
//{
//    // 在子线程中循环读取串口数据
//    while (!isInterruptionRequested()) 
//    {
//        //if (m_serial->waitForReadyRead(100)) 
//        { // 等待串口数据
//            if (!m_serial)
//                return;
//
//            if (!m_serial->isOpen())
//                return;
//
//            m_mutex.lock();
//
//            QThread::msleep(500);
//            QByteArray responseData;
//            if (m_serial->bytesAvailable())//判断串口缓存区内部是否存在数据,存在数据再将数据读出来
//            {
//                responseData = m_serial->readAll();
//                m_buffer += responseData; // 将接收到的数据存入缓冲区
//            }
//                
//            LOGINFO(("[COM%1]Recv:" + QString(responseData)).arg(m_icom));
//
//
//            m_mutex.unlock();
//        }
//    }
//}

bool CSerialPort::init(int icom)
{
    m_serial = new QSerialPort();  
    m_icom = icom;
    if (m_serial)
    {
        m_serial->setPortName("COM" + QString::number(icom)); // 根据实际串口名称设置
        m_serial->setBaudRate(QSerialPort::Baud9600); // 波特率为9600
        m_serial->setDataBits(QSerialPort::Data8); // 8个数据位
        m_serial->setStopBits(QSerialPort::OneStop); // 1个停止位
        m_serial->setParity(QSerialPort::NoParity); // 无奇偶校验
        m_serial->setFlowControl(QSerialPort::NoFlowControl);
        connect(m_serial, &QSerialPort::readyRead, this, &CSerialPort::readData,Qt::DirectConnection);
        connect(this, &CSerialPort::sig_SendData, this, &CSerialPort::SendData);

        
        this->moveToThread(&m_thread);
        // 启动子线程
        m_thread.start();

        return true;
    }
    else
    {
        return false;
    }
}

bool CSerialPort::setIsOn(bool isOn)
{
    m_isOn = isOn;
    return true;
}
bool CSerialPort::getIsOn()
{
    return m_isOn;
}
void CSerialPort::ClosePort()
{
    if (!m_serial)
        return;

    if (m_serial->isOpen())
    {
        m_serial->close();

        if (m_serial->isOpen())
        {
            LOGINFO(tr("关闭软件时,close强固化串口失败!"));
        }
    }
    else;

    if (m_serial)
    {
        delete m_serial;
        m_serial = nullptr;
    }
    
}

void CSerialPort::ClosePort(int nName)
{
    if (!m_serial)
        return;

    if (m_serial->isOpen())
    {
        m_serial->close();

        if (m_serial->isOpen())
        {
            LOGINFO(tr("复位时,关闭串口COM%1失败!").arg(nName));
        }
    }
    else;

    if (m_serial)
    {
        delete m_serial;
        m_serial = nullptr;
    }
}

bool CSerialPort::SendDataBySignal(QByteArray arry)
{
    emit sig_SendData(arry);
    return true;
}


void CSerialPort::SendData(QByteArray arry)
{
    qint64 bytesWritten = 0;

    if (m_serial->isOpen())
    {

        bytesWritten = m_serial->write(arry);
        if (bytesWritten != arry.size())
        {
            LOGINFO(tr("写入失败,[COM%1]写入数据时写入和实际数据不同").arg(m_icom));
            //return false;
        }
    }
    else
    {
        LOGINFO(tr("写入失败,[COM%1]写入数据时串口打开失败" ).arg(m_icom));
        //return false;
    }

    //return true;
}

//bool CSerialPort::DoReadSerial()
//{
//    while (true)
//    {
//        if (!m_serial)
//            return;
//
//        m_mutex.lock();
//        QByteArray responseData = m_serial->readAll();
//        m_buffer += responseData; // 将接收到的数据存入缓冲区
//        LOGINFO(("[COM%1]Recv:" + QString(responseData)).arg(m_icom));
//        m_mutex.unlock();
//
//        QThread::msleep(100);
//    }
//
//    return false;
//}

QByteArray CSerialPort::PraseData(int len, char MsgCode)
{
    //从数据包的末尾往前查找完整包,实时解析最新数据
    QByteArray arr;//011000   010300
    arr.append(char(0x01));
    arr.append(MsgCode);
    arr.append(char(0x00));

    m_mutex.lock();
    QByteArray packet;

    int lastIndex = m_buffer.length() - 1; // 记录最后一个数据的索引
    while (lastIndex >= 0 && m_buffer.length() >= len)
    {
        if (m_buffer.mid(lastIndex - len + 1, 3) == arr)
        {

            packet = m_buffer.mid(lastIndex - len + 1, len); // 获取符合条件的数据包

            if (MsgCode == char(0x10))//写数据返回值
            {
                if (packet[4] != char(0x00) || packet[5] != char(0x04))
                {
                    lastIndex--; // 索引减一,继续向前查找
                    continue;
                }
                else;
            }
            else if (MsgCode == char(0x03))//读数据返回值
            {
                if (packet[3] != char(0x0A))
                {
                    lastIndex--; // 索引减一,继续向前查找
                    continue;
                }
                else;
            }
            else;

            m_buffer = m_buffer.left(lastIndex - len + 1); // 删除已经读取的数据
            break;
        }
        else
        {
            lastIndex--; // 索引减一,继续向前查找
        }
    }

    //超多清空
    if (m_buffer.length() > MAXBUFFERLEN)
    {
        m_buffer.clear();
    }
    else;

    m_mutex.unlock();

    return packet;
}

QString CSerialPort::GetPortName()
{
    return m_serial->portName();
}

//调用
 

do
	{
		if (port && bconnect)
		{
			//先发送查询指令再解析返回数据
			for (int i = 0; i < 1; i++)//4个通道,暂时读一个通道
			{
				//设备地址
				requestData.append(char(0x01));
				//功能码
				requestData.append(char(0x03));
				//寄存器起始地址CH1-CH4
				requestData.append(char(0x00));
				if (i == 0)
				{
					requestData.append(char(0x10));
				}
				else if (i == 1)
				{
					requestData.append(char(0x15));
				}
				else if (i == 2)
				{
					requestData.append(char(0x1A));
				}
				else if (i == 3)
				{
					requestData.append(char(0x20));
				}
				else;
				//写寄存器个数
				requestData.append(char(0x00));
				requestData.append(char(0x05));
				//crc校验
				requestData += crc16(requestData);
				m_SerialPortsArr[index].SendDataBySignal(requestData);



				//等待返回数据,超时判断
				ULONGLONG TimeOut = 5000; //5s
				ULONGLONG nowTime = GetTickCount64();
				bool issuccess = false;
				while (true)
				{
					QByteArray arr_res = m_SerialPortsArr[index].PraseData(16, 0x03);
					if (arr_res.size() == 16)//查询的返回结果
					{
						//查询结果
						int ipower = (int)arr_res[7];
						double dduration = 0.0;
						QByteArray arr_duration;
						arr_duration.append(arr_res[8]);
						arr_duration.append(arr_res[9]);

						QString hexString = arr_duration.toHex(); // 将 QByteArray 转换为十六进制字符串
						bool ok;
						int decimalValue = hexString.toInt(&ok, 16); // 将十六进制字符串转换为十进制数

						if (ok)
						{
							dduration = (double)(decimalValue / 10.0);

							powervalue = ipower;
							duration = dduration;

							issuccess = true;

							break;
						}
						else
						{
							issuccess = false;
							LOGERROR(m_SerialPortsArr[index].GetPortName() + "查询UV灯返回值数据时转换失败");
						}
					}
					else;


					if ((GetTickCount64() - nowTime) > TimeOut)
					{
						issuccess = false;
						LOGERROR("查询串口" + m_SerialPortsArr[index].GetPortName() + "失败,超时");
						break;
					}
					else;

					QThread::msleep(1000);

				}
				if (issuccess == false)//有一个通道失败就退出
				{
					ReturnValue.m_bReturn = issuccess;
					break;
				}
				else
				{
					ReturnValue.m_bReturn = issuccess;
				}

			}
		}
		else
		{
			LOGERROR(port->portName() + "未初始化并连接");
			ReturnValue.m_bReturn = false;
		}
	} while (0);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值