From f4a795105507799c5446657aa1b915ef70293af1 Mon Sep 17 00:00:00 2001
From: mrDarker <mr.darker@163.com>
Date: 星期一, 04 八月 2025 18:20:17 +0800
Subject: [PATCH] 1. 修改SGMeasurement工程文件,添加生成后事件和远程调试

---
 SourceCode/Bond/SGMeasurement/PLCSignalListener.cpp |  203 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 203 insertions(+), 0 deletions(-)

diff --git a/SourceCode/Bond/SGMeasurement/PLCSignalListener.cpp b/SourceCode/Bond/SGMeasurement/PLCSignalListener.cpp
new file mode 100644
index 0000000..27ad0c9
--- /dev/null
+++ b/SourceCode/Bond/SGMeasurement/PLCSignalListener.cpp
@@ -0,0 +1,203 @@
+#include "pch.h"
+#include "PLCSignalListener.h"
+
+// === 日志打印类型 ===
+#define LOG_TYPE_ERROR     -1
+#define LOG_TYPE_SUCCESS    0
+#define LOG_TYPE_WARNING    1
+#define LOG_TYPE_NORMAL     2
+
+// === PLC 控制命令输入位配置 ===
+#define PLC_CMD_BIT_START       0     // PLC命令起始位(通常为B0)
+#define PLC_CMD_BIT_COUNT       2     // 总共几个命令位(B0=Start, B1=Stop)
+
+// === PLC 信号监听器相关宏定义 ===
+#define PLC_ACK_MAX_LIFE        5     // PLC响应信号最大保留周期数(每周期为 m_nIntervalMs 毫秒)
+#define PLC_ACK_BASE_BIT        10    // PLC应答起始地址(B10表示B0的应答;B11表示B1)
+
+// === PLC软元件类型宏(用于应答、数据写入)===
+#define PLC_BIT_DEVICE_TYPE    DeviceType::B   // 位操作设备类型(如M、B)
+#define PLC_WORD_DEVICE_TYPE   DeviceType::W   // 字操作设备类型(如D、W)
+
+#define IS_RISING_EDGE(prev, curr) (!(prev) && (curr))
+
+CPLCSignalListener::CPLCSignalListener() = default;
+
+CPLCSignalListener::~CPLCSignalListener() {
+    Stop();
+}
+
+bool CPLCSignalListener::Initialize(StationIdentifier station, int nIntervalMs/* = 200*/)
+{
+    m_pPlc = std::make_unique<CCCLinkIEControl>();
+    if (!m_pPlc) {
+		if (m_cbLog) {
+			m_cbLog(_T("PLC控制器初始化失败,无法创建 CCCLinkIEControl 实例。"), LOG_TYPE_ERROR);
+		}
+        return false;
+    }
+
+    int ret = m_pPlc->Connect(CC_LINK_IE_CONTROL_CHANNEL(1));
+    if (ret != 0) {
+		m_bConnected = false;
+		if (m_cbLog) {
+			CString strError;
+			strError.Format(_T("PLC控制器连接失败,错误码:%d"), ret);
+			m_cbLog(strError, LOG_TYPE_ERROR);
+		}
+        return false;
+    }
+
+	m_bConnected = true;
+    m_station = station;
+    m_nIntervalMs = nIntervalMs;
+
+    m_vecPrevBits.assign(PLC_CMD_BIT_COUNT, false);
+
+    return true;
+}
+
+void CPLCSignalListener::SetStartCallback(Callback cb)
+{
+    m_cbStart = std::move(cb);
+}
+
+void CPLCSignalListener::SetStopCallback(Callback cb)
+{
+    m_cbStop = std::move(cb);
+}
+
+void CPLCSignalListener::SetAnalyzeCallback(AnalyzeCallback cb)
+{
+    m_cbAnalyze = std::move(cb);
+}
+
+void CPLCSignalListener::SetLogCallback(LogCallback cb)
+{
+    m_cbLog = std::move(cb);
+}
+
+bool CPLCSignalListener::Start()
+{
+    if (m_bRunning || !m_pPlc) {
+		if (m_cbLog) {
+			m_cbLog(_T("PLC信号监听器已在运行或PLC控制器未初始化。"), LOG_TYPE_ERROR);
+		}
+        return false;
+    }
+
+    m_bRunning = true;
+    m_thread = std::thread(&CPLCSignalListener::ThreadProc, this);
+    return true;
+}
+
+void CPLCSignalListener::Stop()
+{
+    m_bRunning = false;
+    if (m_thread.joinable()) {
+        m_thread.join();
+    }
+}
+
+void CPLCSignalListener::PulseBitDevice(DeviceType eDevType, short nBitNo, int nDelayMs/* = 50*/)
+{
+    m_pPlc->SetBitDevice(m_station, eDevType, nBitNo);
+    ::Sleep(nDelayMs);
+    m_pPlc->ResetBitDevice(m_station, eDevType, nBitNo);
+}
+
+void CPLCSignalListener::HandleAckLife(int i, bool bCurrTriggerBit)
+{
+    if (m_vecAckSent[i] && !bCurrTriggerBit) {
+        m_pPlc->ResetBitDevice(m_station, PLC_BIT_DEVICE_TYPE, short(PLC_ACK_BASE_BIT + i));
+        m_vecAckSent[i] = false;
+    }
+
+    if (m_vecAckSent[i]) {
+        if (++m_vecAckCounter[i] > PLC_ACK_MAX_LIFE) {
+            m_pPlc->ResetBitDevice(m_station, PLC_BIT_DEVICE_TYPE, short(PLC_ACK_BASE_BIT + i));
+            m_vecAckSent[i] = false;
+        }
+    }
+}
+
+void CPLCSignalListener::ThreadProc()
+{
+    while (m_bRunning) {
+        BitContainer vecBits;
+        int ret = m_pPlc->ReadBitData(m_station, PLC_BIT_DEVICE_TYPE, PLC_CMD_BIT_START, PLC_CMD_BIT_COUNT, vecBits);
+        if (ret != 0/*&& vecBits.size() != PLC_CMD_BIT_COUNT*/) {
+			::Sleep(m_nIntervalMs);
+
+			if (m_cbLog) {
+				CString strError;
+				strError.Format(_T("PLC读取位数据失败,错误码:%d"), ret);
+				m_cbLog(strError, LOG_TYPE_ERROR);
+			}
+
+			continue;
+        }
+
+        for (int i = 0; i < PLC_CMD_BIT_COUNT; ++i) {
+            if (IS_RISING_EDGE(m_vecPrevBits[i], vecBits[i])) {
+                // 上升沿触发
+                switch (i) {
+                case 0:
+                    if (m_cbStart) {
+                        m_cbStart();
+                        WriteOutValues(OutValuesArray{ 0.0, 0.0, 0.0, 0.0 });
+                        if (m_pPlc->SetBitDevice(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) {
+                            m_vecAckSent[i] = true;
+                            m_vecAckCounter[i] = 0;
+                        }
+                    }
+                    break;
+
+                case 1:
+                    if (m_cbStop) {
+                        m_cbStop();
+                        if (m_pPlc->SetBitDevice(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) {
+                            m_vecAckSent[i] = true;
+                            m_vecAckCounter[i] = 0;
+                        }
+                    }
+
+                    if (m_cbAnalyze) {
+                        auto results = m_cbAnalyze();
+                        WriteOutValues(results);
+                    }
+                    break;
+                }
+            }
+
+            HandleAckLife(i, vecBits[i]);
+            m_vecPrevBits[i] = vecBits[i];
+        }
+
+        ::Sleep(m_nIntervalMs);
+    }
+}
+
+bool CPLCSignalListener::WriteOutValues(const OutValuesArray& values)
+{
+    if (!m_pPlc) {
+		if (m_cbLog) {
+			m_cbLog(_T("PLC控制器未初始化,无法写入输出值。"), LOG_TYPE_ERROR);
+		}
+        return false;
+    }
+
+    static const short PLC_RESULT_ADDR[4] = { 100, 102, 104, 106 };
+
+    for (int i = 0; i < 4; ++i) {
+        uint16_t nScaled = static_cast<uint16_t>(std::round(values[i] * 100.0));
+        WordContainer vec = { nScaled };
+
+        int ret = m_pPlc->WriteWordData(m_station, PLC_WORD_DEVICE_TYPE, PLC_RESULT_ADDR[i], vec);
+        if (ret != 0) {
+            return false;
+        }
+    }
+
+    return true;
+}
\ No newline at end of file

--
Gitblit v1.9.3