W5500+STM32F103C8T6进行TCP通信(modbus)

一、W5500以太网模块介绍

Niren_W5500模块是一款基于WIZnet W5500芯片的以太网模块,是泥人电子继 Niren_W5100模块后设计的一块性能更好、性价比更高的以太网模块。模块集成硬件化TCP/IP协议:内部32K字节存储器作TX/RX
缓存:支持10/100Mbps的传输速率;支持8个独立端口同时运行;同时模块还支持3.3V或5V电源供电,5V供电时还可以输出3.3V电源,方便用户在不同的单片机系统中使用;模块与单片机系统的通讯方式是简单、方便的SPI通信。

二、modbus通信

  • 当设备设置为使用ASCII(美国信息交换标准代码)模式在MODBUS串行线上进行通信时,消息中的每个8位字节将作为两个ASCII4位字符发送。当物理通信链路或设备的功能不允许符合RTU计时器管理要求时,使用此模式。
    所以此模式的效率不如RTU,因为每个字节需要两个字符。示例:字节0x7D编码为两个字符:0x35和0x42(在ASCII表中为0x37=‘7’,而0x44 =‘D’)。
  • Modbus RTU是一种紧凑的,采用二进制表示数据的方式;因为使用二进制编码和CRC错误检查的结合使得Modbus RTU适用于工业应用,因为它比ASCII字符的替代方案更有效地传输。 在Modbus RTU与ASCII之间进行选择时,如果考虑性能,则RTU是首选。在这里插入图片描述
  • Modbus TCP 是在TCP/IP网络上运行的Modbus的实现,旨在允许Modbus ASCII / RTU协议在基于TCP /IP的网络上传输。Modbus / TCP将Modbus消息嵌入TCP /IP帧内。尽管实现起来非常简单,但是与网络相关的特性增加了一些挑战。例如,由于Modbus主机期望并要求在一定时间范围内对其轮询做出响应,因此必须考虑TCP/ IP网络的不确定性(和其他方面)。 Modbus ASCII和Modbus TCP之间的主要区别在于,Modbus ASCII所需的LRC错误检查由IP层执行。

三、从机代码

void Load_Net_Parameters(void)
{
	Gateway_IP[0] = 192;//加载网关参数
	Gateway_IP[1] = 168;
	Gateway_IP[2] = 0;
	Gateway_IP[3] = 1;

	Sub_Mask[0]=255;//加载子网掩码
	Sub_Mask[1]=255;
	Sub_Mask[2]=255;
	Sub_Mask[3]=0;

	Phy_Addr[0]=0x0c;//加载物理地址
	Phy_Addr[1]=0x29;
	Phy_Addr[2]=0xab;
	Phy_Addr[3]=0x7c;
	Phy_Addr[4]=0x00;
	Phy_Addr[5]=0x01;

	IP_Addr[0]=192;//加载本机IP地址
	IP_Addr[1]=168;
	IP_Addr[2]=0;
	IP_Addr[3]=199;

	S0_Port[0] = 0x13;//加载端口0的端口号5000 
	S0_Port[1] = 0x88;

	S0_Mode=TCP_SERVER;//加载端口0的工作模式,TCP服务端模式
}
  • 简单响应函数,这里需要在开始定义一个全局变量data,每次调用都会使data++,而返回的数据就是把data置于数据位,值通过tcp回传回去,能在modbus poll里看到这个值
void Process_Socket_Data(SOCKET s)
{
	int len;
	unsigned char msg[11]={0x00,0x00,0x00 ,0x00, 0x00, 0x05, 0x01, 0x03, 0x02, 0x00, 0x70};
	len=sizeof(msg);
	unsigned short size;
	size=Read_SOCK_Data_Buffer(s, Rx_Buffer);
	memcpy(Tx_Buffer, Rx_Buffer, size);
	
	//打印查询报文
	for (int j=0;j<size;j++){
		 printf("0x%02X ",Tx_Buffer[j]);
	}

	//写响应报文
	//检验码
	msg[0]=Tx_Buffer[0];
	msg[1]=Tx_Buffer[1];
	
	//协议
	msg[2]=0x00;
	msg[3]=0x00;
	
	//数据包长度
	msg[4]=0x00;
	msg[5]=0x05;
	
	//设备编号
	msg[6]=Tx_Buffer[6];
	//功能码
	msg[7]=Tx_Buffer[7];
	//数据长度
	msg[8]=0x02;
	
	//低八位
	msg[10]=data&0XFF;
	//高八位
	msg[9]=data>>8;
	
	memcpy(Tx_Buffer, msg, len);	
	//发送响应报文
	Write_SOCK_Data_Buffer(0, Tx_Buffer, len);
	data++;
}
  • main函数循环等待连接
 while (1)
  {
		W5500_Socket_Set();//W5500端口初始化配置

		W5500_Interrupt_Process();//W5500中断处理程序框架
		
		if((S0_Data & S_RECEIVE) == S_RECEIVE)//如果Socket0接收到数据
		{
			S0_Data&=~S_RECEIVE;
			Process_Socket_Data(0);//W5500接收并发送接收到的数据
		}
		//从机状态标志
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);

  }
  • Modbus Poll读取设置
    在这里插入图片描述
    在这里插入图片描述

  • 读取效果
    在这里插入图片描述

四、总结

有的人天生就是主角,只能说,大佬确实强啊


参考链接

https://blog.csdn.net/junseven164/article/details/122148326
https://blog.csdn.net/qq_45659777/article/details/121952778

版权声明:本文为CSDN博主「羚漆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zero_zero_seven/article/details/122203016

一、w5500资料

  • w5500的资料就放在下面了,单纯的客户端和其他模式上面有教程

https://www.aliyundrive.com/s/enPnnZgNtpE

二、modbus通信

  • Modbus RTU通信时使用的数据帧结构如下图,而Moubus TCP通信的数据帧和这个稍微不一样,没有crc检验,因为tcp本就是一种可靠传输协议
    在这里插入图片描述

  • 这里是Modbus TCP数据帧
    在这里插入图片描述

  • 公共功能码定义在这里插入图片描述

三、从机代码

  • 关键代码,这里需要在开始定义一个全局变量data,每次调用都会使data++,而返回的数据就是把data置于数据位,值通过tcp回传回去,能在modbus poll里看到这个值
void Process_Socket_Data(SOCKET s)
{
	int len;
	unsigned char msg[11]={0x00,0x00,0x00 ,0x00, 0x00, 0x05, 0x01, 0x03, 0x02, 0x00, 0x70};
	len=sizeof(msg);
	unsigned short size;
	size=Read_SOCK_Data_Buffer(s, Rx_Buffer);
	memcpy(Tx_Buffer, Rx_Buffer, size);
	
	//打印查询报文
	for (int j=0;j<size;j++){
		 printf("0x%02X ",Tx_Buffer[j]);
	}

	//写响应报文
	//检验码
	msg[0]=Tx_Buffer[0];
	msg[1]=Tx_Buffer[1];
	
	//协议
	msg[2]=0x00;
	msg[3]=0x00;
	
	//数据包长度
	msg[4]=0x00;
	msg[5]=0x05;
	
	//设备编号
	msg[6]=Tx_Buffer[6];
	//功能码
	msg[7]=Tx_Buffer[7];
	//数据长度
	msg[8]=0x02;
	
	//低八位
	msg[10]=data&0XFF;
	//高八位
	msg[9]=data>>8;
	
	memcpy(Tx_Buffer, msg, len);	
	//发送响应报文
	Write_SOCK_Data_Buffer(0, Tx_Buffer, len);
	data++;
}

  • 代码下载链接

https://gitee.com/zxsjunqi/keilcode/tree/master/Modbus_TCP-main/Modbus_TCP-main

  • Modbus Poll读取设置
    在这里插入图片描述
  • 这里是通过TCP连接,地址就是代码里所写的,比如我是192.168.201.68,端口为5000,有个前提,要通信得先把前面的客户端例子调通,也就是需要修改适配器在这里插入图片描述
    在这里插入图片描述
  • 读取效果在这里插入图片描述

四、总结

modbus tcp通信原理基本清楚了,但在代码实现的时候却很犹豫,不知道拿什么来接收并应答,直到看到同学的博客之后,突然就明白了,大佬是真的强啊。

五、参考

STM32F103基于W5500实现Modbus简单TCP通信
Modbus TCP通信概述

版权声明:本文为CSDN博主「伊始不觉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/junseven164/article/details/122148326

一、w5500

        D-W5500 EVB以太网模块是一款基于WIZnet W5500芯片的以太网模块,且性价比高的以太网模块。W5500是一款全硬件TCP/IP嵌入式以太网控制器,为嵌入式系统提供了更加建议的互联网连接方案。
        W5500固化了TCP/IP协议栈,10/100Mbps以太网数据链路层(MAC)及物理层(PHY),使得用户使用单芯片就能够在他们的应用中拓展网络连接。内嵌32K字节片上缓存以供以太网处理,并且可以同时使用8个硬件Socket独立通讯;SPI(外设船型接口)从而能够更加容易与外设MCU整合,并且W5500使用了高效SPI协议支持80MHz,从而实现高速网络通讯。
        模块还支持3.3V或者5V电源供电,当5V供电时还可以输出3.3V的电压,方便用户在不同的单片机系统中使用。

二、modbus通信

1.Modbus三种通讯方式

Modbus有下列三种通信方式:

(1)、以太网:对应的通信模式是Modbus TCP/IP

(2)、异步串行传输(各种介质如有线RS-232-/422/485/;光纤、无线等):对应的通信模式是Modbus RTU或Modbus ASCII

(3)、高速令牌传递网络:对应的通信模式是Modbus PLUS

Modbus RTU和Modbus ASCII协议应用于串口链接(RS232、RS485、RS422),Modbus tcp/ip协议应用于以太网链接。
 

2.在Modbus网络上传输

标准的Modbus口是使用RS-232C兼容串行接口,它定义了连接口的针脚、电缆、信号位、传输波特率、奇偶校验。控制器能直接或经由Modem组网。

控制器通信使用主/从技术,即仅一设备(主设备)能初始化传输(查询)。其它设备(从设备)根据主设备查询提供的数据作出相应反应。

典型的主设备:主机和可编程仪表。

典型的从设备:可编程控制器。

主设备可单独和从设备通信,也能以广播方式和所有从设备通信。如果单独通信,从设备返回一消息作为回应,如果是以广播方式查询的,则不作任何回应。

Modbus协议建立了主设备查询的格式:设备(或广播)地址、功能代码、所有要发送的数据、一错误检测域。

从设备回应消息也由Modbus协议构成,包括确认要行动的域、任何要返回的数据、和一错误检测域。如果在消息接收过程中发生一错误,或从设备不能执行其命令,从设备将建立一错误消息并把它作为回应发送出去。

3.以太网(modbus tcp/ip)

对于Modbus TCP而言,主站通常称为Client,从站称为Server;而对于Modbus RTU和Modbus ASCII来说,主站是Master,从站是Slave。

ModbusTCP的数据帧可分为两部分:ADU=MBAP+PDU = MBAP + 功能码 + 数据域,MBAP 7byte,功能码1byte,数据域不确定,由具体功能决定。

三、代码实现

(一)初始化从机网络

void Load_Net_Parameters(void)
{
	Gateway_IP[0] = 192;//加载网关参数
	Gateway_IP[1] = 168;
	Gateway_IP[2] = 1;
	Gateway_IP[3] = 1;

	Sub_Mask[0]=255;//加载子网掩码
	Sub_Mask[1]=255;
	Sub_Mask[2]=255;
	Sub_Mask[3]=0;

	Phy_Addr[0]=0x0c;//加载物理地址
	Phy_Addr[1]=0x29;
	Phy_Addr[2]=0xab;
	Phy_Addr[3]=0x7c;
	Phy_Addr[4]=0x00;
	Phy_Addr[5]=0x01;

	IP_Addr[0]=192;//加载本机IP地址
	IP_Addr[1]=168;
	IP_Addr[2]=1;
	IP_Addr[3]=199;

	S0_Port[0] = 0x13;//加载端口0的端口号5000 
	S0_Port[1] = 0x88;

	S0_Mode=TCP_SERVER;//加载端口0的工作模式,TCP服务端模式

(二)响应函数

void Process_Socket_Data(SOCKET s)
{
	int len;
	unsigned char msg[11]={0x00,0x00,0x00 ,0x00, 0x00, 0x05, 0x01, 0x03, 0x02, 0x00, 0x70};
	len=sizeof(msg);
	unsigned short size;
	size=Read_SOCK_Data_Buffer(s, Rx_Buffer);
	memcpy(Tx_Buffer, Rx_Buffer, size);
	
	//打印查询报文
	for (int j=0;j<size;j++){
		 printf("0x%02X ",Tx_Buffer[j]);
	}

	//写响应报文
	//检验码
	msg[0]=Tx_Buffer[0];
	msg[1]=Tx_Buffer[1];
	
	//协议
	msg[2]=0x00;
	msg[3]=0x00;
	
	//数据包长度
	msg[4]=0x00;
	msg[5]=0x05;
	
	//设备编号
	msg[6]=Tx_Buffer[6];
	//功能码
	msg[7]=Tx_Buffer[7];
	//数据长度
	msg[8]=0x02;
	
	//低八位
	msg[10]=data&0XFF;
	//高八位
	msg[9]=data>>8;
	
	memcpy(Tx_Buffer, msg, len);	
	//发送响应报文
	Write_SOCK_Data_Buffer(0, Tx_Buffer, len);
	data++;
}

(三)main函数循环等待连接

 while (1)
  {
		W5500_Socket_Set();//W5500端口初始化配置

		W5500_Interrupt_Process();//W5500中断处理程序框架
		
		if((S0_Data & S_RECEIVE) == S_RECEIVE)//如果Socket0接收到数据
		{
			S0_Data&=~S_RECEIVE;
			Process_Socket_Data(0);//W5500接收并发送接收到的数据
		}
		//从机状态标志
		HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);

  }

四、结果

 

 

五、总结

本次实验用了Mudbus协议栈实现了简单的TCP通信。

六、参考资料

W5500+STM32F103C8T6进行TCP通信(modbus)_junseven164的博客-CSDN博客

版权声明:本文为CSDN博主「枫叶的鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/w798214705/article/details/122201346

一、w5500资料

  • w5500的资料就放在下面了,单纯的客户端和其他模式上面有教程

https://www.aliyundrive.com/s/enPnnZgNtpE

二、modbus通信

  • Modbus RTU通信时使用的数据帧结构如下图,而Moubus TCP通信的数据帧和这个稍微不一样,没有crc检验,因为tcp本就是一种可靠传输协议
    在这里插入图片描述

  • 这里是Modbus TCP数据帧
    在这里插入图片描述

  • 公共功能码定义在这里插入图片描述

三、从机代码

  • 关键代码,这里需要在开始定义一个全局变量data,每次调用都会使data++,而返回的数据就是把data置于数据位,值通过tcp回传回去,能在modbus poll里看到这个值
void Process_Socket_Data(SOCKET s)
{
	int len;
	unsigned char msg[11]={0x00,0x00,0x00 ,0x00, 0x00, 0x05, 0x01, 0x03, 0x02, 0x00, 0x70};
	len=sizeof(msg);
	unsigned short size;
	size=Read_SOCK_Data_Buffer(s, Rx_Buffer);
	memcpy(Tx_Buffer, Rx_Buffer, size);
	
	//打印查询报文
	for (int j=0;j<size;j++){
		 printf("0x%02X ",Tx_Buffer[j]);
	}

	//写响应报文
	//检验码
	msg[0]=Tx_Buffer[0];
	msg[1]=Tx_Buffer[1];
	
	//协议
	msg[2]=0x00;
	msg[3]=0x00;
	
	//数据包长度
	msg[4]=0x00;
	msg[5]=0x05;
	
	//设备编号
	msg[6]=Tx_Buffer[6];
	//功能码
	msg[7]=Tx_Buffer[7];
	//数据长度
	msg[8]=0x02;
	
	//低八位
	msg[10]=data&0XFF;
	//高八位
	msg[9]=data>>8;
	
	memcpy(Tx_Buffer, msg, len);	
	//发送响应报文
	Write_SOCK_Data_Buffer(0, Tx_Buffer, len);
	data++;
}

  • 代码下载链接

https://gitee.com/zxsjunqi/keilcode/tree/master/Modbus_TCP-main/Modbus_TCP-main

  • Modbus Poll读取设置
    在这里插入图片描述
  • 这里是通过TCP连接,地址就是代码里所写的,比如我是192.168.201.68,端口为5000,有个前提,要通信得先把前面的客户端例子调通,也就是需要修改适配器在这里插入图片描述
    在这里插入图片描述
  • 读取效果在这里插入图片描述

四、总结

modbus tcp通信原理基本清楚了,但在代码实现的时候却很犹豫,不知道拿什么来接收并应答,直到看到同学的博客之后,突然就明白了,大佬是真的强啊。

五、参考

STM32F103基于W5500实现Modbus简单TCP通信
Modbus TCP通信概述

版权声明:本文为CSDN博主「伊始不觉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/junseven164/article/details/122148326

生成海报
点赞 0

伊始不觉

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

W5500+STM32F103C8T6进行TCP通信(modbus)

一、w5500资料 w5500的资料就放在下面了,单纯的客户端和其他模式上面有教程 https://www.aliyundrive.com/s/enPnnZgNtpE 二、modbus通信 Modbus RTU通信时使用的数据帧

STM32+W5500以太网模块

一:w5500以太网模块介绍: W5500 是一款全硬件 TCP/IP 嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方 案。W5500 集成了 TCP/IP 协议栈,10/

W5500+STM32F103C8T6进行TCP通信(modbus)

一、w5500 D-W5500 EVB以太网模块是一款基于WIZnet W5500芯片的以太网模块,且性价比高的以太网模块。W5500是一款全硬件TCP/IP嵌入式以太网控制器,为嵌入式系统提供了更加建议的互联网连接

W5500+STM32F103C8T6进行TCP通信(modbus)

一、W5500以太网模块介绍 Niren_W5500模块是一款基于WIZnet W5500芯片的以太网模块,是泥人电子继 Niren_W5100模块后设计的一块性能更好、性价比更高的以太网模块。模块集成硬件化TCP/IP协议:内