From 718f3f21aaa27a468df29d168e3e5d5d12f27ba7 Mon Sep 17 00:00:00 2001 From: Fuyao Date: Wed, 19 Nov 2025 13:36:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=86=99=E5=85=A5=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rtu_transport.go | 87 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/rtu_transport.go b/rtu_transport.go index 11bcaaf..b23a912 100644 --- a/rtu_transport.go +++ b/rtu_transport.go @@ -80,7 +80,6 @@ func (rt *rtuTransport) ExecuteRequest(req *pdu) (res *pdu, err error) { // build an RTU ADU out of the request object and // send the final ADU+CRC on the wire n, err = rt.link.Write(rt.assembleRTUFrame(req)) - fmt.Printf("send: %X\n", rt.assembleRTUFrame(req)) if err != nil { fmt.Printf("write error: %s", err.Error()) return @@ -189,6 +188,55 @@ func (rt *rtuTransport) WriteResponse(res *pdu) (err error) { return } +func calculateModbusCRC16(data []byte) uint16 { + // 初始值 (标准 Modbus RTU) + var crc uint16 = 0xFFFF + + // 遍历所有需要校验的字节 + for _, b := range data { + // 1. 当前 CRC 异或当前字节 (注意:字节 b 转换为 uint16) + crc = crc ^ uint16(b) + + // 2. 8 次迭代进行位运算 + for i := 0; i < 8; i++ { + // 检查最低有效位 (LSB) + if crc&0x0001 != 0 { + // 如果 LSB 是 1: 右移一位,然后异或多项式 0xA001 + // 0xA001 是 0x8005 反射后的结果 + crc = (crc >> 1) ^ 0xA001 + } else { + // 如果 LSB 是 0: 直接右移一位 + crc = crc >> 1 + } + } + } + + // 3. 返回最终的 CRC 值 + return crc +} + +// 示例用法:使用此函数替换您原来的 crc.add/crc.value 逻辑 + +// 假设您的数据帧已完整接收到 rxbuf 中 +func checkCRC(rxbuf []byte, totalFrameSize int) bool { + // 1. 确定校验范围 (地址到数据结束) + crcEndIndex := totalFrameSize - 2 + dataToVerify := rxbuf[0:crcEndIndex] + + // 2. 使用模拟从机的函数计算 CRC + calculatedCRC := calculateModbusCRC16(dataToVerify) + + // 3. 提取接收到的 CRC (Little-Endian 顺序) + recvCRCLow := rxbuf[crcEndIndex] + recvCRCHigh := rxbuf[crcEndIndex+1] + + // 4. 重组接收到的 CRC + receivedCRC := (uint16(recvCRCHigh) << 8) | uint16(recvCRCLow) + + // 5. 比较 + return calculatedCRC == receivedCRC +} + // Waits for, reads and decodes a frame from the rtu link. func (rt *rtuTransport) readRTUFrame() (res *pdu, err error) { var rxbuf []byte @@ -206,9 +254,9 @@ func (rt *rtuTransport) readRTUFrame() (res *pdu, err error) { err = ErrShortFrame return } - if uint8(rxbuf[1]) == fcCustomize { - fmt.Printf("receive: %v\n", rxbuf[0:3]) - } + // if uint8(rxbuf[1]) == fcCustomize { + // fmt.Printf("receive: %v\n", rxbuf[0:3]) + // } if err != nil && err != io.ErrUnexpectedEOF { return } @@ -233,7 +281,6 @@ func (rt *rtuTransport) readRTUFrame() (res *pdu, err error) { // 数据长度位于 rxbuf[4] 和 rxbuf[5] dataLength := bytesToUint16(BIG_ENDIAN, rxbuf[4:6]) bytesNeeded = int(dataLength) - fmt.Println(bytesNeeded) // 3. 计算总共需要读取的字节数 // 数据域长度 + 2 字节 CRC @@ -276,20 +323,30 @@ func (rt *rtuTransport) readRTUFrame() (res *pdu, err error) { // 7. CRC 校验 crcEndIndex := totalFrameSize - 2 // CRC 校验范围的结束索引 (不包含) - fmt.Println("crc end index", crcEndIndex) + + // if checkCRC(rxbuf, totalFrameSize) { + // fmt.Println("66666666666666") + // } crc.init() crc.add(rxbuf[0:crcEndIndex]) // 校验范围从 rxbuf[0] 到数据域结束 // 比较接收到的 CRC - // recvCRCLow := rxbuf[crcEndIndex] - // recvCRCHigh := rxbuf[crcEndIndex+1] + // sentHigh := rxbuf[crcEndIndex] // C_high (例如 0x8B) + // sentLow := rxbuf[crcEndIndex+1] // C_low (例如 0xB0) - // fmt.Println("len: ", len(rxbuf[6:crcEndIndex])) + // 由于 isEqual 期望 (low, high),我们需要将 sentLow 传给 low - // if !crc.isEqual(recvCRCLow, recvCRCHigh) { + // fmt.Printf("ddd: % X\n", rxbuf) + // fmt.Println("c.crc: ", crc.crc) + // fmt.Println("sentLow: ", sentLow, "sentHigh: ", sentHigh) + // fmt.Println("rxbuf[0:10]: ", rxbuf[0:10], "rxbuf[crcEndIndex-10:crcEndIndex]: ", rxbuf[crcEndIndex-10:crcEndIndex]) + + // fmt.Println("len: ", len(rxbuf[crcEndIndex-10:crcEndIndex])) + + // if !crc.isEqual(sentLow, sentHigh) { // err = ErrBadCRC - // fmt.Println("crc: ", recvCRCLow, recvCRCHigh, "byte needed: ", bytesNeeded) + // fmt.Println("crc: ", sentLow, sentHigh, "byte needed: ", bytesNeeded) // return // } @@ -413,6 +470,13 @@ func (rt *rtuTransport) readRTUFrameWithRes() (res *pdu, err error) { return } + // fmt.Println("---: ", rxbuf[:10]) + + // a := make([]byte, 100) + // n, err := io.ReadFull(rt.link, a) + // fmt.Println("n: ", n, "err: ", err, "a: ", a) + time.Sleep(1 * time.Second) + // 使用临时缓冲区循环读取自定义数据 tempBuf := make([]byte, 256) // 每次读取最多256字节 totalRead := 0 @@ -476,6 +540,7 @@ func (rt *rtuTransport) readRTUFrameWithRes() (res *pdu, err error) { functionCode: rxbuf[1], // payload包含标准响应的payload + 自定义数据 payload: completePayload, + // payload: a, } return