QT:BMS_TTL

BMS工程的QT文件

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QTextCodec>
#include <QMessageBox>
#include <QThread>
#include <QSerialPort>          // 补充串口头文件
#include <QSerialPortInfo>
#include <QFileDialog>
#include <QTimer>
#include <QTextBrowser>         // 若UI用QTextBrowser,需包含
#include <QLineEdit>            // 若UI用QLineEdit,需包含
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    COM = new QSerialPort(this);

    // 初始化串口列表
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        ui->COM->addItem(info.portName());
    }
    // 连接串口接收信号(defbug)
    connect(COM, SIGNAL(readyRead()), this, SLOT(Ser_COMDebug_RX()));
}

MainWindow::~MainWindow()
{
    delete ui;
}




//刷新串口按钮

void MainWindow::on_Refresh_COM_clicked()
{
    ui->COM->clear();
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        ui->COM->addItem(info.portName());
    }
}
//点击连接按钮
void MainWindow::on_connect_COM_clicked()
{
    QSerialPort::BaudRate baudRate;
    QSerialPort::StopBits stopBits = QSerialPort::OneStop;
    QSerialPort::DataBits dataBits = QSerialPort::Data8;
    QSerialPort::Parity checkBits = QSerialPort::NoParity;
    QSerialPort::FlowControl flowControl = QSerialPort::NoFlowControl;

    // 设置波特率 currentText获得文本中的内容
    if(ui->Baud_rate->currentText() == "9600"){
        baudRate = QSerialPort::Baud9600;
    }
    else if(ui->Baud_rate->currentText() == "115200"){
        baudRate = QSerialPort::Baud115200;
    }
    else{
        QMessageBox::warning(this, "参数错误", "仅支持9600/115200波特率!");
        return;
    }

    // 配置串口参数
    COM->setPortName(ui->COM->currentText());
    COM->setBaudRate(baudRate);
    COM->setStopBits(stopBits);
    COM->setDataBits(dataBits);
    COM->setParity(checkBits);
    COM->setFlowControl(flowControl);

    // 打开串口逻辑
    if(ui->connect_COM->text() == "连接BMS"){
        if(COM->open(QIODevice::ReadWrite)){
            ui->connect_COM->setText("断开BMS");
          ui->connect_COM->setStyleSheet("QPushButton  { background-color: red }");
        }else{
            QMessageBox::critical(this, "错误", "串口打开失败:\r\n" + COM->errorString());
        }
    }
    // 关闭串口逻辑 text 单行文本,简单控件返回的是QString类型的文本。
    else if(ui->connect_COM->text() == "断开BMS"){
        if(COM->isOpen()){
            COM->close();
            ui->connect_COM->setText("连接BMS");
           ui->connect_COM->setStyleSheet("QPushButton  { background-color: white;  }");
        }
    }
}
//清空调试信息的文本
void MainWindow::on_connect_COM_2_clicked()
{
      ui->Debug_text->clear();
}
void MainWindow::Ser_COMDebug_RX()
{
    QByteArray buf = COM->readAll();
    if (buf.isEmpty()) return;

    // ========== 新增:处理STM32的MOS控制确认反馈(Aok/Bok/Cok/Dok) ==========
    QString feedback = QString::fromUtf8(buf); // 或用GB2312解码,根据实际串口编码
    if (feedback.contains("Aok")) {
        // 充电MOS打开确认
        ui->label_73->setText("打开");
        ui->Debug_text->insertPlainText("[反馈] 充电MOS已打开\n");
    }
    else if (feedback.contains("Bok")) {
        // 充电MOS关闭确认
        ui->label_73->setText("关闭");
        ui->Debug_text->insertPlainText("[反馈] 充电MOS已关闭\n");
    }
    else if (feedback.contains("Cok")) {
        // 放电MOS打开确认
        ui->label_72->setText("打开");
        ui->Debug_text->insertPlainText("[反馈] 放电MOS已打开\n");
    }
    else if (feedback.contains("Dok")) {
        // 放电MOS关闭确认
        ui->label_72->setText("关闭");
        ui->Debug_text->insertPlainText("[反馈] 放电MOS已关闭\n");
    }

    // 1. 解码数据并追加到缓存
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    QString newData = codec->toUnicode(buf).trimmed();
    m_dataBuffer += newData;  // 拼接新接收的数据到缓存
    // ui->Debug_text->insertPlainText("[接收片段] " + newData + "\n"); // 注释:隐藏接收片段提示

    // 2. 检查缓存中是否包含完整帧结束符(AAAA)
    int endPos = m_dataBuffer.indexOf("AAAA");
    if (endPos == -1) {
        // 未找到结束符,继续缓存
        // ui->Debug_text->insertPlainText("[缓存] 数据未完整,继续缓存\n"); // 注释:隐藏缓存提示
        ui->Debug_text->moveCursor(QTextCursor::End);
        return;
    }

    // 3. 提取完整帧(从开头到AAAA结束)
    QString completeFrame = m_dataBuffer.left(endPos + 4);  // +4是"AAAA"的长度
    m_dataBuffer = m_dataBuffer.mid(endPos + 4);  // 剩余数据保留到缓存(防止多帧重叠)
    // 注释掉完整帧的输出,不再显示
    // ui->Debug_text->insertPlainText("[完整帧] " + completeFrame + "\n"); // 注释:隐藏完整帧提示

    // 4. 清理完整帧中的无关内容(如"电流+温度+全部电压"这类提示)
    completeFrame = completeFrame.remove("电流+温度+全部电压").trimmed();
    completeFrame = completeFrame.remove("AAAA");  // 移除结束符

    // 5. 分割数据并校验格式
    QStringList dataList = completeFrame.split("-", QString::SkipEmptyParts);
    if (dataList.size() < 10) {  // 至少10个电池字段
        // ui->Debug_text->insertPlainText("[错误] 完整帧格式错误,字段不足:" + completeFrame + "\n"); // 注释:隐藏错误提示
        ui->Debug_text->moveCursor(QTextCursor::End);
        return;
    }

    // 6. 解析并显示电池数据(恢复setText,显示数据)
    auto updateBattery = [this](int batteryNum, const QString &value) {
        QTextBrowser *batteryWidget = findChild<QTextBrowser*>(QString("battery%1").arg(batteryNum));
        if (batteryWidget) {
            batteryWidget->setText(value);  // 恢复显示
        } else {
            // ui->Debug_text->insertPlainText("[警告] 未找到电池" + QString::number(batteryNum) + "控件\n"); // 注释:隐藏控件未找到警告
        }
    };

    // 电池1~9对应数据列表前9项(根据实际数据调整索引)
    updateBattery(1, dataList[0]);
    updateBattery(2, dataList[1]);
    updateBattery(3, dataList[2]);
    updateBattery(4, dataList[3]);
    updateBattery(5, dataList[4]);
    updateBattery(6, dataList[5]);
    updateBattery(7, dataList[6]);
    updateBattery(8, dataList[7]);
    updateBattery(9, dataList[8]);

    // 6. 总电压(TOL_V)
       if (ui->battery_All) {
           ui->battery_All->setText(dataList[9] );
       } else {
           // ui->Debug_text->insertPlainText("[警告] 未找到总电压控件:TOL_V\n"); // 注释:隐藏控件未找到警告
       }

       // 7. 电流(cur)
       if (ui->electricity) {
           ui->electricity->setText(dataList[10] );
       } else {
           // ui->Debug_text->insertPlainText("[警告] 未找到电流控件:cur\n"); // 注释:隐藏控件未找到警告
       }

       // 8. 温度(Temp)
       if (ui->Tem) {
           ui->Tem->setText(dataList[11] + " °C");
       } else {
           // ui->Debug_text->insertPlainText("[警告] 未找到温度控件:Temp\n"); // 注释:隐藏控件未找到警告
       }
       if (ui->Tem_2) {
           ui->Tem_2->setText(dataList[12] + " %");
           // 设置大字体
           QFont font = ui->Tem_2->font(); // 获取控件当前字体
           font.setPointSize(22); // 设置字体大小(可根据需求调整数值,如16、18等)
           // 可选:加粗字体
           // font.setBold(true);
           ui->Tem_2->setFont(font); // 应用字体设置
       } else {
           // ui->Debug_text->insertPlainText("[警告] 未找到温度控件:Temp\n"); // 注释:隐藏控件未找到警告
       }
    ui->Debug_text->insertPlainText("[完成] 数据解析成功\n");
    ui->Debug_text->moveCursor(QTextCursor::End);
}
//开始采集按钮
// 示例:发送GB2312编码的文本(比如"测试数据")
// 发送GB2312编码的文本(例如"测试数据")
void MainWindow::on_startgather_clicked()
{
    if (!COM->isOpen()) {
        QMessageBox::warning(this, "提示", "串口未连接,请先打开串口!");
        return;
    }

    QString sendText = "0xAA 0xBB 0x13 0xCC\r\n"; // 要发送的文本
    // 关键:用GB2312编码转为字节数组
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    QByteArray sendData = codec->fromUnicode(sendText); // 转为GB2312编码的字节

    COM->write(sendData);
    ui->Debug_text->insertPlainText("已发送GB2312文本:" + sendText + "\n");
}
//停止采集数据按键
void MainWindow::on_connect_COM_4_clicked()
{
    if (!COM->isOpen()) {
        QMessageBox::warning(this, "提示", "串口未连接,请先打开串口!");
        return;
    }

    QString sendText = "0xAA 0xBB 0x14 0xCC\r\n"; // 要发送的文本
    // 关键:用GB2312编码转为字节数组
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    QByteArray sendData = codec->fromUnicode(sendText); // 转为GB2312编码的字节

    COM->write(sendData);
    ui->Debug_text->insertPlainText("已发送GB2312文本:" + sendText + "\n");
}
//清空按键的全部数据
void MainWindow::on_clearData_clicked()
{



    // 2. 清空数据缓存(防止残留数据干扰后续解析)
    m_dataBuffer.clear();

    // 3. 清空所有单体电池控件(battery1~battery9)
    for (int i = 1; i <= 9; ++i) {
        QTextBrowser *batteryWidget = findChild<QTextBrowser*>(QString("battery%1").arg(i));
        if (batteryWidget) {
            batteryWidget->clear();  // 清空电池控件内容
        }
    }

    // 4. 清空总电压控件
    if (ui->battery_All) {
        ui->battery_All->clear();
    }

    // 5. 清空电流控件
    if (ui->electricity) {
        ui->electricity->clear();
    }

    // 6. 清空温度控件
    if (ui->Tem) {
        ui->Tem->clear();
    }


}
//打开放电MOS
void MainWindow::on_connect_COM_5_clicked()
{
    if (!COM->isOpen()) {
        QMessageBox::warning(this, "提示", "串口未连接,请先打开串口!");
        return;
    }

    QString sendText = "0xAA 0xAB 0x03 0xCC\r\n"; // 要发送的文本
    // 关键:用GB2312编码转为字节数组
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    QByteArray sendData = codec->fromUnicode(sendText); // 转为GB2312编码的字节

    COM->write(sendData);
    ui->Debug_text->insertPlainText("已发送GB2312文本:" + sendText + "\n");
   // ui->label_72->setText("打开");
}
//打开充电mos
void MainWindow::on_connect_COM_7_clicked()
{
    if (!COM->isOpen()) {
        QMessageBox::warning(this, "提示", "串口未连接,请先打开串口!");
        return;
    }

    QString sendText = "0xAA 0xAB 0x01 0xCC\r\n"; // 要发送的文本
    // 关键:用GB2312编码转为字节数组
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    QByteArray sendData = codec->fromUnicode(sendText); // 转为GB2312编码的字节

    COM->write(sendData);
    ui->Debug_text->insertPlainText("已发送GB2312文本:" + sendText + "\n");
    // ui->label_73->setText("打开");
}
//关闭放电mos
void MainWindow::on_connect_COM_6_clicked()
{
    if (!COM->isOpen()) {
        QMessageBox::warning(this, "提示", "串口未连接,请先打开串口!");
        return;
    }

    QString sendText = "0xAA 0xAB 0x04 0xCC\r\n"; // 要发送的文本
    // 关键:用GB2312编码转为字节数组
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    QByteArray sendData = codec->fromUnicode(sendText); // 转为GB2312编码的字节

    COM->write(sendData);
    ui->Debug_text->insertPlainText("已发送GB2312文本:" + sendText + "\n");
   //  ui->label_72->setText("关闭");
}
//关闭充电mos
void MainWindow::on_connect_COM_8_clicked()
{
    if (!COM->isOpen()) {
        QMessageBox::warning(this, "提示", "串口未连接,请先打开串口!");
        return;
    }

    QString sendText = "0xAA 0xAB 0x02 0xCC\r\n"; // 要发送的文本
    // 关键:用GB2312编码转为字节数组
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    QByteArray sendData = codec->fromUnicode(sendText); // 转为GB2312编码的字节

    COM->write(sendData);
    ui->Debug_text->insertPlainText("已发送GB2312文本:" + sendText + "\n");
     //ui->label_73->setText("关闭");
}

mainwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:


    void on_Refresh_COM_clicked();

    void on_connect_COM_clicked();

    void on_connect_COM_2_clicked();
    void Ser_COMDebug_RX();



    void on_startgather_clicked();

    void on_connect_COM_4_clicked();

    void on_clearData_clicked();

    void on_connect_COM_5_clicked();

    void on_connect_COM_7_clicked();

    void on_connect_COM_6_clicked();

    void on_connect_COM_8_clicked();

private:
    Ui::MainWindow *ui;
     QSerialPort *COM;                  // 串口对象
     QString m_dataBuffer;  // 串口数据缓存,用于拼接分段数据

};
#endif // MAINWINDOW_H
相关推荐
Scott9999HH1 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海2 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
马优晨4 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区5 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大6 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai6 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜6 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa6 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio