darker
2025-02-15 46996b55fed671525f1aaf01a29c8aa73662be9e
1. 修复位读写,位读写的起始地址需要是8的倍数
已修改2个文件
101 ■■■■■ 文件已修改
SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.cpp 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.h 42 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.cpp
@@ -483,15 +483,33 @@
        return nRet;
    }
    // 计算需要读取的字节大小(按位对齐为字节数)
    if (nDevNo % 8 != 0) {
        nRet = -2;
        UpdateLastError(nRet);
        return nRet;
    }
    const short nDevType = CalculateDeviceType(station, enDevType);
    const auto nSize = static_cast<short>((nBitCount + 7) / 8);     // 向上取整
    std::vector<short> vecTempBuffer((nSize + 1) / 2, 0); // 临时缓冲区,字节对齐
    const auto nSize = static_cast<short>((static_cast<int>(nBitCount) + 15) / 16);  // 计算需要读取的字数量(向上取整)
    std::vector<short> vecTempBuffer(nSize, 0);
    nRet = ReadData(station, nDevType, nDevNo, nSize, vecTempBuffer);
    if (nRet == 0) {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertShortToUint8(vecTempBuffer, vecData);
        vecData.clear();
        // 将字数据解析为位数据
        for (short nIdx = 0; nIdx < nSize; ++nIdx) {
            const short nCurrentValue = vecTempBuffer[nIdx];
            // 遍历当前 short 中的每一位
            for (int bitIdx = 0; bitIdx < 16; ++bitIdx) {
                bool bBit = (nCurrentValue & (1 << bitIdx)) != 0;
                vecData.push_back(bBit);
                if (vecData.size() >= nBitCount) {
                    return nRet;  // 如果已经读取完所需的位数,提前退出
                }
            }
        }
    }
    return nRet;
@@ -573,22 +591,35 @@
// 写位数据
int CPerformanceMelsec::WriteBitData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const BitContainer& vecData) {
    // 验证站点参数和数据有效性
    const int nRet = ValidateStationAndData(station, vecData);
    int nRet = ValidateStationAndData(station, vecData);
    if (nRet != 0) {
        UpdateLastError(nRet);
        return nRet;
    }
    // 计算需要写入的字节数(位数据需要按 8 位对齐为字节数)
    const short nDevType = CalculateDeviceType(station, enDevType);
    const auto nSize = static_cast<short>((vecData.size() + 7) / 8);
    std::vector<short> vecBuffer(vecData.size() / 2 + vecData.size() % 2, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        ConvertUint8ToShort(vecData, vecBuffer);
    if (nDevNo % 8 != 0) {
        nRet = -2;
        UpdateLastError(nRet);
        return nRet;
    }
    return WriteData(station, nDevType, nDevNo, nSize, vecBuffer.data());
    const short nDevType = CalculateDeviceType(station, enDevType);
    const auto nSize = static_cast<short>((static_cast<int>(vecData.size()) + 15) / 16);  // 计算需要写入的字数量(向上取整)
    // 准备临时缓冲区来存储转换后的 16 位数据
    std::vector<short> vecTempBuffer(nSize, 0);
    {
        std::lock_guard<std::mutex> lock(m_mtx); // 线程安全保护
        // 将位数据按字打包到临时缓冲区
        for (int i = 0; i < vecData.size(); ++i) {
            if (vecData[i]) {
                // 使用 & 0xFFFF 保证不会超过 16 位,防止溢出
                vecTempBuffer[i / 16] |= static_cast<short>((1 << (i % 16)) & 0xFFFF);
            }
        }
    }
    return WriteData(station, nDevType, nDevNo, nSize, vecTempBuffer.data());
}
// 写字数据
SourceCode/Bond/Servo/CCLinkPerformance/PerformanceMelsec.h
@@ -28,7 +28,7 @@
#define CC_LINK_IE_FIELD_CHANNEL(x) (180 + (x))   // x 范围:1~4
#define CC_LINK_IE_TSN_CHANNEL(x) (280 + (x))     // x 范围:1~4
// 自定义错误码
 // 自定义错误码
#define ERROR_CODE_UNKNOWN                0x00010000 // 未知
#define ERROR_CODE_NOT_CONNECTED        0x00020000 // 未连接
#define ERROR_CODE_INVALID_PARAM        0x00030000 // 参数无效
@@ -130,7 +130,7 @@
enum class DataType {
    BIT = 1,   // 位 (1位)
    WORD = 2,  // 字 (16位)
    DWORD =4   // 双字 (32位)
    DWORD = 4  // 双字 (32位)
};
// 控制代码
@@ -180,22 +180,22 @@
     * 1~239 表示普通网络号
     **/
    /*
     * [Station No.]
     * MELSECNET/H:1~64 表示其他站点,255 表示本站
     * CC-Link 系列网络的范围类似,区别在于站号的取值范围
     * MELSECNET/H             : 1~64(Other stations),255(Own station)
     * CC-Link                 : 0~63(Other stations),255(Own station)
     * CC-Link IE Controller   : 1~120(Other stations),255(Own station)
     * CC-Link IE Field        : 0~120(Other stations),255(Own station)
     * CC-Link IE TSN          : 0~120(Other stations),255(Own station)
     **/
     /*
      * [Station No.]
      * MELSECNET/H:1~64 表示其他站点,255 表示本站
      * CC-Link 系列网络的范围类似,区别在于站号的取值范围
      * MELSECNET/H             : 1~64(Other stations),255(Own station)
      * CC-Link                 : 0~63(Other stations),255(Own station)
      * CC-Link IE Controller   : 1~120(Other stations),255(Own station)
      * CC-Link IE Field        : 0~120(Other stations),255(Own station)
      * CC-Link IE TSN          : 0~120(Other stations),255(Own station)
      **/
    /*
     * 高 8 位(网络号): 指定设备所属的网络
     * 低 8 位(站点号): 指定设备在网络中的编号
     * 用一个参数传递设备的网络号和站点号时: nSt = station.nStNo | ((station.nNetNo << 8) & 0xFF00);
     **/
      /*
       * 高 8 位(网络号): 指定设备所属的网络
       * 低 8 位(站点号): 指定设备在网络中的编号
       * 用一个参数传递设备的网络号和站点号时: nSt = station.nStNo | ((station.nNetNo << 8) & 0xFF00);
       **/
    short nNetNo = 0;    // 网络编号:PLC所连接的网络编号,0表示默认网络
    short nStNo = 255;   // 站点编号:指定与PLC连接的站点编号,255通常表示广播或所有站点
@@ -211,13 +211,13 @@
    // 重载 < 运算符(用于排序或比较,通常用于 map 或 set 中作为 key)
    bool operator<(const StationIdentifier& other) const {
        return std::tie(nNetNo, nStNo) <
               std::tie(other.nNetNo, other.nStNo);
            std::tie(other.nNetNo, other.nStNo);
    }
    // 重载 == 运算符(用于相等比较)
    bool operator==(const StationIdentifier& other) const {
        return std::tie(nNetNo, nStNo) ==
               std::tie(other.nNetNo, other.nStNo);
            std::tie(other.nNetNo, other.nStNo);
    }
    // 重载 = 运算符(用于赋值)
@@ -330,7 +330,7 @@
    }
};
using BitContainer = std::vector<uint8_t>;        // 每个元素存储 8 个位
using BitContainer = std::vector<bool>;            // 每个元素存储 1  位
using WordContainer = std::vector<uint16_t>;    // 每个元素存储 16 位
using DWordContainer = std::vector<uint32_t>;    // 每个元素存储 32 位
@@ -435,7 +435,7 @@
    // 容器转换
    static void ConvertCharToShort(const std::vector<char>& vecChar, std::vector<short>& vecShort);
    static void ConvertShortToChar(const std::vector<short>& vecShort, std::vector<char>&vecChar);
    static void ConvertShortToChar(const std::vector<short>& vecShort, std::vector<char>& vecChar);
    static void ConvertUint8ToShort(const std::vector<uint8_t>& vecUint8, std::vector<short>& vecShort);
    static void ConvertShortToUint8(const std::vector<short>& vecShort, std::vector<uint8_t>& vecUint8);
    static void ConvertUint32ToShort(const std::vector<uint32_t>& vecUint32, std::vector<short>& vecShort);