[STM32F103C8T6]W5500+Modbus TCP(HAL库)

这篇具有很好参考价值的文章主要介绍了[STM32F103C8T6]W5500+Modbus TCP(HAL库)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本章节是博主学习Modbus TCP所写的一篇文章


一、Modbus TCP是什么?

1.1.1 Modbus TCP介绍

Modbus TCP是Modbus的一个分支,主要用到网口通信的,在工业上也用的很频繁,我们公司最近的项目就是用的W5500+modbus TCP来和PC端的上位机通信和交互的。虽然这个项目不是我在写代码,但是我都学了Modbus RTU了,那我也抽空学习一下Modbus TCP吧。本次的Modbus TCP不是博主写的,是一个大佬开源的一个W5500写的一个Mobus TCP代码,我在这个基础上自己写了主机读从机多个数据,和主机写从机寄存器的函数。这个项目搞了一天,主要是一直ping不通,最后ping通了。
Modbus TCP 相较于 Mobus RTU是没有CRC16校验位的,而且还多了4个字节的事务协议。

1.1.2 报文格式

0x03 主机读从机寄存器

/*******************************************************************************	
                             Modbus TCP
主机保持读从机        实物协议     字节长度    从机地址  功能码   起始地址    读取线圈个数
	        主机    05 95 00 00    00 06        01        03     00 00          00 01
	                  实物协议    字节长度    从机地址   功能码    字节个数     上传数据
	        从机    05 95 00 00    00 05        01        03       02           00 04
0x03 读保持寄存器
********************************************************************************/	

0x06 主机写从机寄存器

/*******************************************************************************	
                             Modbus TCP
主机写单一从机             实物协议     字节长度   从机地址  功能码  寄存器地址   下发数据
	            主机    31 C9 00 00     00 06       01       06       00 00          00 20
	                      实物协议     字节长度   从机地址  功能码  寄存器地址   下发数据
	            从机    31 C9 00 00     00 06       01       06       00 00          00 20
0x06 写单一寄存器
********************************************************************************/		

总体来说还是很简单的

二、W5500配置

工程源码:添加链接描述,大家记得给博主点赞哈。
首先是配置
然后是查看你的IP地址、网关、子网掩码等
Win+R弹出运行框,然后输入cmd进入到w5500 modbus,STM32高级功能,stm32,tcp/ip,嵌入式硬件
然后是 ipconfig/all可以查看IP地址等,这里我用的以太网.
w5500 modbus,STM32高级功能,stm32,tcp/ip,嵌入式硬件
然后可以自己静态分配地址 IPv4
w5500 modbus,STM32高级功能,stm32,tcp/ip,嵌入式硬件
然后就是修改代码

/*******************************************************************************
* 函数名  : Load_Net_Parameters
* 描述    : 装载网络参数
* 输入    : 无
* 输出    : 无
* 返回值  : 无
* 说明    : 网关、掩码、物理地址、本机IP地址、端口号、目的IP地址、目的端口号、端口工作模式
*******************************************************************************/
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]=0x08;//加载物理地址 ,这个可以和主机的不一样
	Phy_Addr[1]=0x97;
	Phy_Addr[2]=0x98;
	Phy_Addr[3]=0xBE;
	Phy_Addr[4]=0x2F;
	Phy_Addr[5]=0x7F;

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

	S0_Port[0] = 0x13;//加载端口0的端口号5000 
	S0_Port[1] = 0x88;
	
	S0_Mode=TCP_SERVER;//加载端口0的工作模式,TCP服务端模式
}

然后我们在cmd里面ping一下看通不通
输入 ping 自己的IP,我这里是 ping 192.168.1.17,下面是Ping成功的情况。
w5500 modbus,STM32高级功能,stm32,tcp/ip,嵌入式硬件
这个时候我们就可以用Modbus调试了。
w5500 modbus,STM32高级功能,stm32,tcp/ip,嵌入式硬件

三.读保持寄存器&&写单一寄存器函数

1.代码展示

/*******************************************************************************
* 函数名  : Process_Socket_Keep_Read_nData
* 描述    : W5500接收并发送接收到的多个数据
* 输入    : s:端口号
* 输出    : 无
* 返回值  : 无
* 说明    : 本过程先调用S_rx_process()从W5500的端口接收数据缓冲区读取数据,
*			然后将读取的数据从Rx_Buffer拷贝到Temp_Buffer缓冲区进行处理。
*			处理完毕,将数据从Temp_Buffer拷贝到Tx_Buffer缓冲区。调用S_tx_process()
*			发送数据。注意这里是发送多个数据(0x03),写一个数据是(0x06) 
*******************************************************************************/
void Process_Socket_Keep_Read_nData(SOCKET s,uint8_t* Tx_Buff_datas){
	uint16_t size;
	uint8_t Tx_Buffer_CP[128];
	uint8_t p=0;	
	
	size=Read_SOCK_Data_Buffer(s, Rx_Buffer);
/*******************************************************************************	
                             Modbus TCP
主机保持读从机        实物协议    字节长度  从机地址 功能码  起始地址   读取线圈个数
	            主机    05 95 00 00    00 06        01        03     00 00          00 01
	                      实物协议    字节长度  从机地址 功能码  字节个数     上传数据
	            从机    05 95 00 00    00 05        01        03       02           00 04
0x03 读保持寄存器
********************************************************************************/	
	if(Rx_Buffer[6]==0x01){//判读是否是该从机寄存器地址
		if(Rx_Buffer[7]==0x03){//主机读取从机保持读寄存器
//			printf("PC receive Data(0x03)=");
//			for(int i=0;i<size;i++){
//				printf("0x%X,",Rx_Buffer[i]);		
//			}
//			printf("\r\n");
			//判断发送的字节数量
			uint16_t Begin_addr=Rx_Buffer[8]<<8;//读取起始地址高八位
			Begin_addr=Rx_Buffer[9];	//读取起始地址低八位
			uint16_t End_addr=Rx_Buffer[10]<<8;//读取结束地址高八位
			End_addr=Rx_Buffer[11];//读取结束地址低八位
			uint16_t RX_SUM=End_addr-Begin_addr;//主机读取多少个数据
			uint16_t RX_SUM_size=RX_SUM*2;
			//printf("PULL READ Data=%d\r\n",RX_SUM_size); 
			//判断事务协议后的字节数量
			uint16_t start_size=3+RX_SUM_size;
				
			//实物协议码
			Tx_Buffer_CP[0]=Rx_Buffer[0]; 
			Tx_Buffer_CP[1]=Rx_Buffer[1];	
			Tx_Buffer_CP[2]=Rx_Buffer[2]; 	
			Tx_Buffer_CP[3]=Rx_Buffer[3];
			//下发长度
			Tx_Buffer_CP[4]=start_size>>8;
			Tx_Buffer_CP[5]=start_size;
			//从机地址	
			Tx_Buffer_CP[6]=Rx_Buffer[6];
			//功能码
			Tx_Buffer_CP[7]=Rx_Buffer[7];
			//发送的字节长度
			Tx_Buffer_CP[8]=RX_SUM_size;
			p=9;
			for(int j=0;j<RX_SUM_size;j++){
				if((p+j)%2==1){ //填充高8位
					Tx_Buffer_CP[p+j]=Tx_Buff_datas[j];
				}else{         //填充低8位
					Tx_Buffer_CP[p+j]=Tx_Buff_datas[j];  						
				} 		
			}		
			memcpy(Tx_Buffer, Tx_Buffer_CP, p+RX_SUM_size);
			//printf("size=%d\r\n",p+RX_SUM_size);
			//发送响应报文
			Write_SOCK_Data_Buffer(0, Tx_Buffer, p+RX_SUM_size);	
		}else if(Rx_Buffer[7]==0x06){//主机写从机单一寄存器
/*******************************************************************************	
                             Modbus TCP
主机写单一从机        实物协议    字节长度  从机地址 功能码  寄存器地址   下发数据
	            主机    31 C9 00 00     00 06       01       06       00 00          00 20
	                      实物协议    字节长度  从机地址 功能码  寄存器地址   下发数据
	            从机    31 C9 00 00     00 06       01       06       00 00          00 20
0x06 写单一寄存器
********************************************************************************/						
			//写地址
			uint16_t Write_addr=Rx_Buffer[8]>>8;
			Write_addr=Rx_Buffer[9];
			//写数据
			uint16_t Write_data=Rx_Buffer[10]>>8;
			Write_data=Rx_Buffer[11];
			printf("Write_addr=0x%x,Write_data=0x%x\r\n",Write_addr,Write_data);
			
			printf("PC receive Data(0x06)=");
			for(int w=0;w<size;w++){
				printf("0x%X,",Rx_Buffer[w]);		
			}
			printf("\r\n");
		  for(int i=0;i<size;i++){
				Tx_Buffer[i]=Rx_Buffer[i];			
			}
			printf("0x06_data_size=%d\r\n",size);
 			Write_SOCK_Data_Buffer(0, Tx_Buffer, size);
      
			if(Write_addr==0x04){
				if(Write_data==0x01){
					HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);//控制LED灯
					
				}else if(Write_data==0x02){
					HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);									
				}				
			}

			
		}
	}else{
		printf("Not the address, but=0x%X,\r\n",Rx_Buffer[6]);	
	}
}

这里就介绍完了,最后效果展示
w5500 modbus,STM32高级功能,stm32,tcp/ip,嵌入式硬件

2.参考资料

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


总结

Modbus TCP使用还是非常好的,之前博主没有学Modbus的时候一直用的JSON格式来打包数据给上位机。现在掌握两种数据格式,美滋滋文章来源地址https://www.toymoban.com/news/detail-616176.html

到了这里,关于[STM32F103C8T6]W5500+Modbus TCP(HAL库)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SG90舵机的使用--STM32F103C8T6

    SG90带有一个3P的接头 根据颜色分为 黄线(信号线) 红线(电源线) 棕色 (地线) 舵机的 工作电压 在 4.8V-6V ,接在STM32系统板上驱动不了,所以需要接电源模块单独的5V供电,我使用的是如图所示的电源模块 注: 如果STM32系统板供电和舵机供电不为同一模块,则需要共地,

    2024年02月03日
    浏览(19)
  • STM32---stm32f103c8t6与stm32f103zet6之间的代码移植转换

    目录 一、将c8t6转换为zet6 1、修改启动文件 2、修改芯片 3、将MD修改为HD  4、下载器的修改 5、修改完成,编译成功  二、将zet6转换为c8t6 最终结果如下:   将STM32F103C8改为STM32F103ZE   基本相同,反向即可。    

    2024年02月06日
    浏览(18)
  • [附源码] STM32F103C8T6+外接MCP4725 外部DAC

            STM32F103C8T6最小系统板是大家很常用的一款单片机,它内部有多个ADC模数转换通道,但并 没有DAC数模转换功能 ,当需要进行数字量转换为模拟量时就需要借助外部DAC。             MCP4725是具有非易失性存储器的单通道12位缓冲电压输出DAC。用户可将配置寄存器

    2024年02月04日
    浏览(20)
  • JQ8400语音模块-stm32f103c8t6(内含全代码)-亲测有效

    一.模块介绍 1.常见的JQ8400-FL语音模块有两种,一种是带3W功放,有4M的存储空间,可通过USB拷贝声音文件,通过单片机串口控制;另外一种是附有SD卡槽,用SD卡存储文件的文件(MP3格式)进行语音播报,也是通过单片机串口控制 2.我用的是二线串口通信,一线的没试过 3.程序

    2023年04月26日
    浏览(22)
  • STM32F103C8T6+ESP8266WIFI+DHT11模块连接巴法云

    1.MCU:STM32F103C8T6 2.ESP8266:正点原子WIFI模块 3.串口模块:正点原子串口模块 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客: ESP8266固件刷写 我用的是安信可的固件,可以在官网上下载。正点

    2023年04月27日
    浏览(38)
  • 【沧海拾昧】STM32F103C8T6/C6T6的ISP烧录

    #C0105 沧海茫茫千钟粟,且拾吾昧一微尘 ——《沧海拾昧集》@CuPhoenix 【阅前敬告】 沧海拾昧集仅做个人学习笔记之用,所述内容不专业不严谨不成体系 【如有问题必是本集记录有谬,切勿深究】   对于某种STM32F103C8T6/C6T6最小系统板,没有配置J-LINK/ST-LINK烧录口,此时可以

    2024年02月03日
    浏览(42)
  • STM32F103C8T6---定时器1&定时器8输出PWM信号注意事项

    博主今天在驱动定时器1的通道1输出PWM信号的时候,遇到了好多问题,在这里指出,警醒自己的同时希望能给各位带来帮助 首先,第一个错误, 第一:PA8引脚默认模式就是定时器1的通道一,我们在代码里面,直接 将PA8的输出模式改为复用推挽输出,不要去重定向它,也不要

    2024年02月16日
    浏览(17)
  • STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

    作者:公子易平 时间:2023/6/6 前段时间做一个智能小车的相关项目时,发现很少有人能够将STM32的PWM控制讲清楚,故而书此文,希望对后来的学习者有所帮助。 STM32F103C8T6最小系统板 直流TT电机 电机驱动芯片(TB6612) 杜邦线若干 接线情况: TB6612引脚说明: STM32主控芯片与TB6612接

    2024年02月15日
    浏览(21)
  • STM32F103C8T6+ESP-01S+MQTT服务器实现数据上传和接收(一)

    文章目录 STM32F103C8T6+ESP-01S+MQTT服务器实现数据的上传和接收(二) ESP-01S推荐使用安信可官网1471号固件,烧录配置如下图。 请替换其中里面的内容 使用PA9、PA10分别连接ESP8266的RXD、TXD引脚。 由于每次发送的AT指令都会被8266通过串口再发送回来,为了缓解串口的压力,并且更

    2024年04月17日
    浏览(19)
  • STM32F103C8T6+2.4寸SPI TFT触摸屏代码+标准库 项目开发

    目录 模块清单: 模块介绍: 1:STM32F103C8T6 2:2.4寸SPI TFT触摸屏 项目结果展示 2.4寸 TFT SPI显示触摸屏 2.4寸 SPI TFT 显示触摸屏代码下载链接: https://download.csdn.net/download/weixin_49492286/88458377 清单 STM32F103C8T6 2.4寸SPI TFT触摸屏         STM32F103C8T6是意法半导体(STMicroelectronics)推

    2024年02月07日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包