Embed/microCLib

添加modbus主机部分的支持。
JiuHuan authored at 2024-11-13 16:38:32
ab769f4
Tree
1 Parent(s) 07d6e41
Summary: 4 changed files with 208 additions and 14 deletions.
Modified +145 -0
Modified +18 -4
Modified +31 -0
Modified +14 -10
Modified +145 -0
diff --git a/Core/ModbusRtuCodec.c b/Core/ModbusRtuCodec.c
index 3da4910..1946906 100644
--- a/Core/ModbusRtuCodec.c
+++ b/Core/ModbusRtuCodec.c
@@ -129,6 +129,151 @@ int MrcSlaveGetLenStream(Stream_t* st)
 	return MrcSlaveGetLength(p, remain);
 }
 
+/// <summary>通过包头计算数据长度,不校验</summary>
+/// <param name="p">最少给3个字节的数组</param>
+/// <returns>理论上包长。-1 数据包类型不对,0 p为null</returns>
+static int _masterCalcRxLen(byte* p)
+{
+	if (p == NULL)return 0;
+
+	byte cmd = p[1];
+	switch (cmd)
+	{
+	case 1:
+	case 2:
+	{
+		byte bitlen = p[2];
+		byte bytelen = (bitlen + 7) / 8;
+		// addr+cmd+bitcnt + 2crc * 5
+		int pklen = 5 + bytelen;
+
+		return pklen;
+	}
+	case 3:
+	case 4:
+	{
+		byte bytelen = p[2];
+		// addr+cmd+bytelen+2crc = 5
+		int pklen = 5 + bytelen;
+
+		return pklen;
+	}
+
+	case 5:
+	case 6:
+	case 0xf:
+	case 0x10:
+	{
+		return 8;
+	}
+
+	default: return -1;
+	}
+}
+
+int MrcMasterGetRxLength(byte* p, int len)
+{
+	if (p == NULL)return 0;
+	if (len < 5)return 0;
+
+	int pklen = _masterCalcRxLen(p);
+
+	// 数据包类型不对
+	if (pklen < 0)return -1;
+	// 长度超出
+	if (pklen > 130)return -2;
+	// 长度不够
+	if (pklen > len)return 0;
+
+	if (Check(p, pklen))return pklen;
+	// 校验失败
+	return -1;
+}
+
+int MrcMasterGetRxLenCircularQueue(CircularQueue_t* queue)
+{
+	if (queue == NULL)return 0;
+	int remian = CircularQueueGetLength(queue);
+	if (remian < 6)return 0;
+
+	// 缓冲
+	byte cache[130];
+	// 读3个字节判断长度
+	CircularQueueReads(queue, cache, 3, true);
+	int pklen = _masterCalcRxLen(cache);
+	// 数据包类型不对
+	if (pklen < 0)return -1;
+	// 长度超出
+	if (pklen > 130)return -2;
+	// 数据包长度
+	if (pklen > remian)return 0;
+		
+	// if (sizeof(cache) >= pklen)
+	// {
+
+	// 直接使用缓冲区读出来判断
+	CircularQueueReads(queue, cache, pklen, true);	
+	if (Check(cache, pklen))return pklen;
+	// 校验失败
+	return -1;
+
+	// }
+	// else
+	// {
+	// 	// 再弄一个缓冲区使用
+	// 	byte* p = (byte*)GlobleMalloc(pklen);
+	// 	if (p == NULL)return -1;
+	// 
+	// 	// 读出来校验一下
+	// 	CircularQueueReads(queue, p, pklen, true);
+	// 	bool crcok = Check(p, pklen);
+	// 	GlobleFree(p);
+	// 
+	// 	if (crcok)return pklen;
+	// 	// 校验失败
+	// 	return -1;
+	// }
+}
+
+int MrcMasterGetRxLenStream(Stream_t* st)
+{
+	int remain = st->Size - st->Position;
+	byte* p = &st->MemStart[st->Position];
+
+	return MrcMasterGetRxLength(p, remain);
+}
+
+/// <summary>获取应答消息内负载数据的偏移量</summary>
+/// <param name="pkt">已经校验通过的数据包</param>
+/// <returns>返回偏移量,-1 消息类型错误,0 无负载数据</returns>
+int MrcMasterGetRxPyOffset(byte* pkt)
+{
+	if (pkt == NULL)return 0;
+
+	byte cmd = pkt[1];
+	switch (cmd)
+	{
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	{
+		return 3;
+	}
+	case 5:
+	case 6:
+	{
+		return 4;
+	}
+	case 0x0f:
+	case 0x10:
+	{
+		return 0;
+	}
+	default: return -1;
+	}
+}
+
 // 01 02 请求指令。 len = 8
 int Mrc01a02(byte addr, byte cmd, ushort regaddr, ushort bitlen, byte* data, int len)
 {
Modified +18 -4
diff --git a/Core/ModbusRtuCodec.h b/Core/ModbusRtuCodec.h
index b420b31..fa8b476 100644
--- a/Core/ModbusRtuCodec.h
+++ b/Core/ModbusRtuCodec.h
@@ -4,8 +4,9 @@
 #include "Stream.h"
 #include "CircularQueue.h"
 
-/*
+// Modbus Rtu Controller  (Mrc)
 
+/*
 1:  读线圈
 2:	读离散输入
 3:  读多个保持寄存器
@@ -15,8 +16,6 @@
 15  写多个线圈 
 16	写多个寄存器
 
-// modbus 请求包格式
-
 // 请求包
 // 01   addr+cmd+2regaddr+2bitcnt+2crc
 // 02   addr+cmd+2regaddr+2bitcnt+2crc
@@ -33,7 +32,7 @@
 // 03	addr+cmd+bytelen+ (bytelen*data) +2crc
 // 04	addr+cmd+bytelen+ (bytelen*data) +2crc
 // 05   06   等于请求包
-// 10	addr+cmd+2regaddr+2bitcnt+2crc
+// 0f	addr+cmd+2regaddr+2bitcnt+2crc
 // 10	addr+cmd+2regaddr+2regcnt+2crc
 
 解释:
@@ -57,6 +56,21 @@ int MrcSlaveGetLength(byte* data, int len);
 int MrcSlaveGetLenCircularQueue(CircularQueue_t* queue);
 int MrcSlaveGetLenStream(Stream_t* st);
 
+// 获取有效的modbus rtu数据包长度(会校验数据包)
+// 应答消息的长度(从机发送给主机的回复消息)
+// 0 没有足够长度的数据。
+// -1 数据包校验出错
+// -2 数据长度不对,modbus rtu 数据包小于 130 字节。
+int MrcMasterGetRxLength(byte* p, int len);
+int MrcMasterGetRxLenCircularQueue(CircularQueue_t* queue);
+int MrcMasterGetRxLenStream(Stream_t* st);
+
+/// <summary>获取应答消息内负载数据的偏移量</summary>
+/// <param name="pkt">已经校验通过的数据包</param>
+/// <returns>返回偏移量,-1 消息类型错误,0 无负载数据</returns>
+int MrcMasterGetRxPyOffset(byte* pkt);
+
+
 // 01 02 请求指令。 len = 8
 int Mrc01a02(byte addr, byte cmd, ushort regaddr, ushort bitlen, byte* data, int len);
 // 01 02 指令回复。 len > (bitlen+7)/8 + 5;
Modified +31 -0
diff --git a/Core/ModbusTcpCodec.c b/Core/ModbusTcpCodec.c
index fde0edd..8247506 100644
--- a/Core/ModbusTcpCodec.c
+++ b/Core/ModbusTcpCodec.c
@@ -38,6 +38,37 @@ int MtcGetLenStream(Stream_t* st)
 	return res;
 }
 
+/// <summary>获取应答消息内负载数据的偏移量</summary>
+/// <param name="pkt">已经校验通过的数据包</param>
+/// <returns>返回偏移量,-1 消息类型错误,0 无负载数据</returns>
+int MtcMasterGetRxPyOffset(byte* pkt)
+{
+	if (pkt == NULL)return 0;
+
+	byte cmd = pkt[1];
+	switch (cmd)
+	{
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	{
+		return 3 + 6;
+	}
+	case 5:
+	case 6:
+	{
+		return 4 + 6;
+	}
+	case 0x0f:
+	case 0x10:
+	{
+		return 0;
+	}
+	default: return -1;
+	}
+}
+
 // 01 02 请求指令。 len = 12
 int Mtc01a02(MtcHead_t* head, byte cmd, ushort regaddr, ushort bitlen, byte* data, int len)
 {
Modified +14 -10
diff --git a/Core/ModbusTcpCodec.h b/Core/ModbusTcpCodec.h
index dc7ef96..8ce6bfa 100644
--- a/Core/ModbusTcpCodec.h
+++ b/Core/ModbusTcpCodec.h
@@ -1,21 +1,15 @@
 #pragma once
 
 #include "Type.h"
-
-
-#include "CircularQueue.h"
 #include "Stream.h"
+#include "CircularQueue.h"
 
-// 获取 modbus tcp/udp 数据包长度,不区分请求和应答
-int MtcGetLength(byte* p, int len);
-int MtcGetLenCircularQueue(CircularQueue_t* queue);
-int MtcGetLenStream(Stream_t* st);
-
+// Modbus Tcp Controller  (Mtc)
 
 // modbus tcp/udp 相对于 rtu 来说,头部增加了 6字节,尾部少2字节。
 // 其余部分一致。参考 modbus-rtu 即可。
-// rtu				     addr cmd ndata 2crc
-// tcp   2seq 2pro 2len  addr cmd ndata
+// rtu:					addr cmd ndata 2crc
+// tcp:	2seq 2pro 2len	addr cmd ndata
 
 /*
 1:  读线圈
@@ -28,6 +22,16 @@ int MtcGetLenStream(Stream_t* st);
 16	写多个寄存器
 */
 
+// 获取 modbus tcp/udp 数据包长度,不区分请求和应答
+int MtcGetLength(byte* p, int len);
+int MtcGetLenCircularQueue(CircularQueue_t* queue);
+int MtcGetLenStream(Stream_t* st);
+
+/// <summary>获取应答消息内负载数据的偏移量</summary>
+/// <param name="pkt">已经校验通过的数据包</param>
+/// <returns>返回偏移量,-1 消息类型错误,0 无负载数据</returns>
+int MtcMasterGetRxPyOffset(byte* pkt);
+
 #pragma pack(push)
 #pragma pack(1)
 typedef struct