DSCAnalysisTool/src/serialport/serialport.cpp
2025-04-23 15:33:39 +08:00

490 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "serialport.h"
#include <qdebug.h>
#include <qdatetime.h>
#include <iostream>
#include <cstring>
#include <QSerialPortInfo>
#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:"<<localLength;
switch (localAddr)
{
case offsetof(CommonData, run_type): // 运行状态
{
switch(cd.run_type){
case DeviceRunStatus::Cooling:
// Global::instance()->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<QSerialPortInfo> 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<CommonData *>(const_cast<uchar *>(&data[6]));
qDebug() << "run type:" << serialPortData->run_type;
// qDebug()<<"run time:"<<serialPortData->add_run_time;
// qDebug()<<"sample temp:"<<serialPortData->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();
}
}