#include "serialport.h" #include #include #include #include #include #include "protocol.h" #include "defines.h" #include "dataparser.h" #include "global.h" #include "logger.h" using namespace std; const u16 conVid = 1155; // 0x0483 const u16 conPid = 22336; // 0x5740 SerialPort::SerialPort(QObject *parent) : QObject(parent), _sp(nullptr) { // displayPortInfo(); #if 0 // 1.初始化 _sp = new QSerialPort(); _sp->setPortName(conSPName); if(_sp == nullptr){ qDebug()<<"sp is null."; exit(0); return; } // 3.设置 //设置波特率和读写方向 _sp->setBaudRate(QSerialPort::Baud115200, QSerialPort::AllDirections); _sp->setDataBits(QSerialPort::Data8); //数据位为8位 _sp->setFlowControl(QSerialPort::NoFlowControl);//无流控制 _sp->setParity(QSerialPort::NoParity); //无校验位 _sp->setStopBits(QSerialPort::OneStop); //一位停止位 //4.连接信号槽 connect(_sp,&QSerialPort::readyRead, this,&SerialPort::slotReadData); // 2.打开串口 if(false == _sp->open(QIODevice::ReadWrite)){ qDebug()<<"open failed." <<_sp->error(); exit(0); } else{ qDebug()<<"open succ."; // 设置 DTR 信号为就绪状态(true 表示低电平) _sp->setDataTerminalReady(true); } //写数据定时器 // startTimer(500); #endif #if 0 sendCmd(e_zero); for(int i = 0; i < 9; i++){ sendCmd(e_back); } #endif } SerialPort *SerialPort::instance() { static SerialPort ins; return &ins; } SerialPort::~SerialPort() { if (_sp && _sp->isOpen()) { _sp->clear(); _sp->close(); } delete _sp; _sp = nullptr; } void SerialPort::timerEvent(QTimerEvent *event) { } void SerialPort::slotReadData() { QByteArray ba = _sp->readAll(); if(ba.size() == 0){ return; } #if 0 QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数 qDebug() << "receive info (hex):" << hexData; #endif SerialPortProtocol *spp = (SerialPortProtocol *)ba.data(); if (FRANE_HEAD != spp->head) { qDebug() << "Data header error."; return; } //phase setting data if(spp->addr == PHASE_START_ADDR){ emit sigSendPhaseInfo(ba); return; } int dataLength = spp->len - 5; CommonData cd; u8 *cdPtr = (u8 *)&cd; memcpy(cdPtr + spp->addr, spp->data_buf, dataLength); if (WRITE_CMD == spp->cmd) { commonDataParser(dataLength, spp->addr, cd); } else if (READ_CMD == spp->cmd) { DataParser::experimentalStateSwitching(cd); setAxis(); if (spp->addr == 0) { if (Global::Mode::Experiment == Global::_mode) { emit sigSendCommonData(cd); } // emit sigSendCommonDataToRealDataForm(cd); } } } void SerialPort::commonDataParser(const int dataLength, const u16 addr, const CommonData &cd) { int localLength = dataLength; int localAddr = addr; int phaseByteSize = sizeof(Phase); auto phaseParserFunc = [&](const int index) { Phase phase; phase.onoff = 1; phase.gas = cd.phase_data[index].gas; phase.temp_flow = cd.phase_data[index].temp_flow; phase.cutoff_temp = cd.phase_data[index].cutoff_temp; phase.constant_temp_time_min = cd.phase_data[index].constant_temp_time_min; localLength -= phaseByteSize; localAddr += phaseByteSize; }; while (localLength) { qDebug()<<"localLength:"<setMode(Global::Mode::Analysis); Global::_mode = Global::Mode::Analysis; logde<<"set global mode analysis.common data parser."; break; default:break; } localAddr += 1; localLength -= 1; break; } case offsetof(CommonData, current_gas): // 当前气氛 // gas_type_set(dev->temp, msg_data.current_gas); localAddr += 1; localLength -= 1; break; case offsetof(CommonData, auto_pid_temp_flow): // 自整定升温速率 localAddr += 4; localLength -= 4; break; case offsetof(CommonData, run_mode): { DeviceStartMode mode = (DeviceStartMode)cd.run_mode; switch (mode) { case DeviceStartMode::Stop: // Global::instance()->setMode(Global::Mode::Analysis); Global::_mode = Global::Mode::Analysis; logde<<"set global mode analysis."; break; case DeviceStartMode::Start: // Global::instance()->setMode(Global::Mode::ExperimentStart); Global::_mode = Global::Mode::Experiment; break; default: break; } // localLength--; localAddr++; break; } case offsetof(CommonData, phase_data[0].onoff): phaseParserFunc(0); break; case offsetof(CommonData, phase_data[1].onoff): phaseParserFunc(1); break; case offsetof(CommonData, phase_data[2].onoff): phaseParserFunc(2); break; case offsetof(CommonData, phase_data[3].onoff): phaseParserFunc(3); break; case offsetof(CommonData, phase_data[4].onoff): phaseParserFunc(4); break; case offsetof(CommonData, phase_data[5].onoff): phaseParserFunc(5); break; default: break; }; } } bool SerialPort::openSp() { if (_sp != nullptr && _sp->isOpen()) { return true; } foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { u16 pid = info.productIdentifier(); u16 vid = info.vendorIdentifier(); if ((pid == conPid) && (vid == conVid)) { _sp = new QSerialPort(info); break; } } if (_sp == nullptr) { qDebug() << "Device not found."; return false; } // 设置波特率和读写方向 _sp->setBaudRate(QSerialPort::Baud115200, QSerialPort::AllDirections); _sp->setDataBits(QSerialPort::Data8); // 数据位为8位 _sp->setFlowControl(QSerialPort::NoFlowControl); // 无流控制 _sp->setParity(QSerialPort::NoParity); // 无校验位 _sp->setStopBits(QSerialPort::OneStop); // 一位停止位 // 4.连接信号槽 connect(_sp, &QSerialPort::readyRead, this, &SerialPort::slotReadData); // 2.打开串口 if (!_sp->open(QIODevice::ReadWrite)) { qDebug() << "open failed." << _sp->error(); return false; } else { qDebug() << "open succ."; // 设置 DTR 信号为就绪状态(true 表示低电平) _sp->setDataTerminalReady(true); } return true; } void SerialPort::sendCmd(const SerialPort::E_CMD_TYPE e) { #if 1 int length = 20; char in_char[21] = {'\0'}; if (e == e_zero) { // char data[10] = {'55','aa','0b','0a','20', // '4e','00','00','00','c3'}; const char *data = "55aa0b0a204e000000c3"; memcpy(in_char, data, length); } else if (e == e_back) { // char data[10] = {'55','aa','08','10','27', // 'f0','d8','ff','ff','c3'}; const char *data = "55aa081027f0d8ffffc3"; memcpy(in_char, data, length); } else if (e == e_forward) { // char data[10] = {'55','aa','08','10','27', // '10','27','00','00','c3'}; const char *data = "55aa08102710270000c3"; memcpy(in_char, data, length); } #endif // char in_char[] = "55aa0b0a204e000000c3"; char out_char[21] = {'\0'}; int hex_length = 10; to_hex(in_char, hex_length, out_char); int num = _sp->write(out_char, hex_length); if (num == -1) { qDebug() << "write failed."; } else { qDebug() << "write ok|num:" << num; } } void SerialPort::to_hex(char *in_char, int char_length, char *out_char) { while (char_length--) { *out_char = (*in_char & 0x40 ? *in_char + 9 : *in_char) << 4; ++in_char; *out_char |= (*in_char & 0x40 ? *in_char + 9 : *in_char) & 0xF; ++in_char; ++out_char; } } void SerialPort::displayPortInfo() { // 获取系统中所有可用的串口信息 QList serialPorts = QSerialPortInfo::availablePorts(); // 遍历每个串口信息 for (const QSerialPortInfo &portInfo : serialPorts) { qDebug() << "================================================"; // 打印串口的名称 qDebug() << "串口名称: " << portInfo.portName(); // 打印串口的描述信息 qDebug() << "描述信息: " << portInfo.description(); // 打印串口的制造商信息 qDebug() << "制造商: " << portInfo.manufacturer(); // 打印串口的序列号 qDebug() << "序列号: " << portInfo.serialNumber(); // 打印串口的系统位置 qDebug() << "系统位置: " << portInfo.systemLocation(); // 打印是否有虚拟调制解调器 qDebug() << "是否有虚拟调制解调器: " << (portInfo.hasVendorIdentifier() ? "是" : "否"); // 打印是否有产品标识符 qDebug() << "是否有产品标识符: " << (portInfo.hasProductIdentifier() ? "是" : "否"); // 如果有虚拟调制解调器,打印其标识符 if (portInfo.hasVendorIdentifier()) { qint16 vid = portInfo.vendorIdentifier(); qDebug() << "虚拟调制解调器标识符: " << vid; QString hexStr = QString("0x%1").arg(vid, 4, 16, QChar('0')).toUpper(); qDebug() << "vid 0x" << hexStr; } // 如果有产品标识符,打印其标识符 if (portInfo.hasProductIdentifier()) { qint16 pid = portInfo.productIdentifier(); qDebug() << "产品标识符: " << pid; QString hexStr = QString("0x%1").arg(pid, 4, 16, QChar('0')).toUpper(); qDebug() << "pid 0x" << hexStr; } } } void SerialPort::setAxis() { static Global::Mode previousMode = Global::Analysis; // 记录上一次的模式 if (previousMode == Global::Analysis && Global::_mode == Global::Experiment) { // std::cout << "Mode has changed from Analysis to Experiment!" << std::endl; Global::ExperimentInfo & eti = Global::_experimentInfo; if(eti.phaseVtr.size() > 0){ logde<<"serialport set axis."; float temp = eti.phaseVtr.at(0).cutoff_temp; emit sigAxisModify(temp); } } if(previousMode != Global::_mode){ previousMode = Global::_mode; } } void SerialPort::parserTest() { const uchar data[] = {0xa5, 0x5a, 0x2d, 0x83, 0x00, 0x00, 0x00, 0x01, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x07, 0xbc, 0xb5, 0xf2, 0xc8, 0x57, 0x38, 0x40, 0x1b, 0x63, 0x27, 0xbc, 0x04, 0xa7, 0xf2, 0x3f, 0x55, 0x55, 0x55, 0xd5, 0x04, 0xf3, 0xab, 0xbf, 0xfa, 0x2b, 0xcd, 0x41, 0x00, 0x00, 0x93, 0xba}; CommonData *serialPortData = nullptr; qDebug() << "data length:" << sizeof(data) / sizeof(uchar); // serialPortData = (CommonData)&data[4]; serialPortData = reinterpret_cast(const_cast(&data[6])); qDebug() << "run type:" << serialPortData->run_type; // qDebug()<<"run time:"<add_run_time; // qDebug()<<"sample temp:"<sample_temp; // 格式化输出 float 类型,保留两位小数 QString formattedRunTime = QString::number(serialPortData->add_run_time, 'f', 2); qDebug() << "run time:" << formattedRunTime; // 格式化输出 double 类型,保留三位小数 QString formattedSampleTemp = QString::number(serialPortData->sample_temp, 'f', 3); qDebug() << "sample temp:" << formattedSampleTemp; QString formattedColdTemp = QString::number(serialPortData->cold_temp, 'f', 3); qDebug() << "cold temp:" << formattedColdTemp; #if 0 // 定义小端序的 4 字节数据 unsigned char bytesLittle[] = {0x23, 0x23, 0x01, 0x00}; // 调用函数进行转换 float result = 0.0f; std::memcpy(&result, bytesLittle, sizeof(float)); // float floatValue = bytesToFloatLittleEndian(bytesLittle); // 输出转换后的浮点数 std::cout << "result: " << result << std::endl; #endif } void SerialPort::slotDeliverData(const QByteArray &ba) { qDebug()<<"slotDeliverData..."; openSp(); slotSendData(ba); } void SerialPort::slotSendData(const QByteArray &ba) { #if 1 qDebug() << "slotSendData:" << ba.size(); QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数 qDebug() << "slotSendData:" << hexData; #endif if (_sp != nullptr && _sp->isOpen()) { _sp->write(ba); } else { qDebug() << "sp not open."; return; } } void SerialPort::slotCloseSp() { if (_sp != nullptr && _sp->isOpen()) { _sp->close(); } }