STM32+W5500网络通信

目录

前言

一.Modbus/TCP协议

1. Modbus/TCP报文格式

2.功能码

 二.W5500以太网模块

1.简介

2.模块排针功能表

三.STM32+W5500+modbus协议编程

四.STM32+W5500的web服务

五.参考文献


前言

掌握W5500网络模块的特点,参在此基础上,实现应用层modbus、httpd(web服务)协议编程。考模块厂商配套资料,完成TCP数据通信、DHCP自动获取IP的程序设计。

一.Modbus/TCP协议

1. Modbus/TCP报文格式

 
起始字符组:于前面再多加6个字符,以定义一些TCP/IP的需要 系数。说明如下: 

Byte0:本次通信Message的编号以2 bytes整数(Byte 0、1)表示,此 byte为上字符,一般是由Master编号之,以区分每次Message。如果是Slave则将Master传来的Query Message照转至Response Message。 

Byte1:本次通信Message的编号下字符。

Byte2:通信协议识别号码以2 bytes整数(Byte 2、3)表示,此 byte 为上字符,于此处为零。 

Byte3:通信协议识别号码下字符,于此处为零。 

Byte4:Message长度以2 bytes整数(Byte 4、5)表示,此 byte 为上字符(由Device Address至Data为止),因为长度不能超过256位,所以此位永远为零。 

Byte5:Message长度下字符(由Device Address至Data为止)。 

由Device Address至Data等资料,都是将 8 bits原始值转换为两码的十六进制ASCII码,所以其实际传送的字符数约为RTU格式的两倍。Data:数个字符是表示每个Function Code有不同数目的详细资料规定。

Modbus规定IP Port No. 为 502。

2.功能码

 Modbus协议定义了一个与基础通信层无关的简单协议数据单元(PDU)。特定总线或网线路上的Modbus协议映射能够在应用数据单元(ADU)上引入一些附加域。

启动Modbus事务处理的客户机创建Modbus应用数据单元。功能码向服务器指示将执行哪种操作。

Modbus协议建立了客户机启动的请求格式。

用一个字节编码Modbus数据单元的功能码域。有效范围是十制制1-255(128-255为异常响应保留)。当从客户机向服务器发送报文时,功能码域通过服务器执行哪种操作。

从客户机向服务器发送的报文数据域包括附加信息,服务器使用这个信息执行功能码定义的操作。这个域还包括离散项目和寄存器地址、处理项目的数量以及域中的实际数据字节数。

在某种请求中,数据域可以是不存在的,在此情况下服务器不需要任何附加信息。功能码仅说明操作。

功能码的类型
    功能码主要分为有效功能码、异常功能码和错误功能码。

如果在一个正确接收Modbus ADU中,不出现与请求Modbus功能有关的差错,那么服务器至客户机的响应数据会包含请求中的正常功能码。如果出现与请求Modbus功能有关的差错,那么响应数据会包含一个异常码和错误码。

 二.W5500以太网模块

1.简介

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


2.模块排针功能表

排针标识    功能说明    排针标识    功能说明
3.3V    3.3V电源输入引脚    5V    5V电源输入引脚
MISO    SPI主机输入从机输出引脚    GND    电源地引脚
MOSI    SPI主机输出从机输入引脚    RST    W5500硬件初始化引脚(低电平有效)
SCS    SPI SLAVE选择引脚(低电平有效)    INT    W5500中断引脚(低电平有效)
SCLK    SPI时钟引脚    NC    悬空
 

三.STM32+W5500+modbus协议编程

代码

main()函数

int main(void)
{
	unsigned char i;

	/* Initialize STM32F103 */
	System_Initialization();//系统配置
	SysTick_Init();//启动系统滴答定时器 SysTick

	/* Config W5500 */
	W5500_Configuration();//W5500配置
	Delay_ms(200);//延时等待

	/* Modbus-TCP Init */
    eMBTCPInit(MB_TCP_PORT_USE_DEFAULT); //端口依赖事件模块初始化
	Delay_ms(200); //延时等待
	
	/* Enable Modbus-TCP Stack */    
    eMBEnable();//激活协议栈	
    

    printf("\r\nModbus-TCP Start!\r\n");
    printf("IP:192.168.1.128\r\n");


	while(1)
	{
		
		i=Read_SOCK_1_Byte(0,Sn_SR);  //读W5500状态
		if(i==0)	  
		{
			do
			{
				Delay_ms(100);//延时等待
			
			}while(Socket_Listen(0)==FALSE);//设置“Socket n”为“TCP服务器模式”
		}
		else if(i==SOCK_ESTABLISHED)		 //建立TCP连接
		{
		eMBPoll();//启动modbus侦听
		BSP_LED();//线圈控制LED灯
		}
				
	}
}

W5500配置函数

/* W5500 configuration */
void W5500_Configuration()
{
	unsigned char array[6];

	GPIO_SetBits(GPIO_W5500_RST_PORT, GPIO_W5500_RST_Pin);//上拉
	Delay_ms(100);    /*delay 100ms 使用systick 1ms时基的延时*/
    //等待以太网链路
	while((Read_1_Byte(PHYCFGR)&LINK)==0); 		/* Waiting for Ethernet Link */

	Write_1_Byte(MR, RST);//写入W5500普通寄存器一个字节
	Delay_ms(20);		/*delay 20ms */

	/* Set Gateway IP as: 192.168.1.1 */
	array[0]=192;
	array[1]=168;
	array[2]=1;
	array[3]=1;
	Write_Bytes(GAR, array, 4);//设置网关IP

	/* Set Subnet Mask as: 255.255.255.0 */
	array[0]=255;
	array[1]=255;
	array[2]=255;
	array[3]=0;
	Write_Bytes(SUBR, array, 4);//设置子网掩码

	/* Set MAC Address as: 0x48,0x53,0x00,0x57,0x55,0x00 */
	array[0]=0x48;
	array[1]=0x53;
	array[2]=0x00;
	array[3]=0x57;
	array[4]=0x55;
	array[5]=0x00;
	Write_Bytes(SHAR, array, 6);//设置MAC地址

	/* Set W5500 IP as: 192.168.1.128 */
	array[0]=192;
	array[1]=168;
	array[2]=1;
	array[3]=128;
	Write_Bytes(SIPR, array, 4);//设置W5500的IP地址
}

四.STM32+W5500的web服务

main函数

int main(void)
{
	Systick_Init(72);//系统时钟初始化
	GPIO_Configuration(); //GPIO configuration
	USART1_Init(); //串口初始化:115200@8-n-1
	printf("W5500 EVB initialization over.\r\n");
	Reset_W5500();
	WIZ_SPI_Init();//W5500相关引脚配置
	printf("W5500 initialized!\r\n");
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7))
	{
		DefaultSet();//出厂值
	}
	else
	{
 		get_config();//read config data from flash
	}
	printf("Firmware ver%d.%d\r\n",ConfigMsg.sw_ver[0],ConfigMsg.sw_ver[1]);
	if(ConfigMsg.debug==0) ConfigMsg.debug=1;

	set_network();//配置网络信息
	printf("Network is ready.\r\n");
	while(1)
	{
		if(ConfigMsg.JTXD_Control == 0)
		  	do_http();//开启http服务
		else
		  	JTXD_do_http();
		if(reboot_flag)
			NVIC_SystemReset();//发起系统复位请求复位单片机
//        reboot();
        
	}
}

GPIO初始化函数

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO , ENABLE);
  // Port A output
  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0|GPIO_Pin_1| GPIO_Pin_2 |GPIO_Pin_3; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
//  GPIO_ResetBits(GPIOA, GPIO_Pin_0);
//  GPIO_ResetBits(GPIOA, GPIO_Pin_1);
//  GPIO_SetBits(GPIOA, GPIO_Pin_2); // led off
//  GPIO_SetBits(GPIOA, GPIO_Pin_3); // led off
  // Port B output;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_SetBits(GPIOB, GPIO_Pin_9);
  // Port C input
//  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
//  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//控制flash
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_SetBits(GPIOB, GPIO_Pin_7);	
}

W5500相关配置:

void WIZ_SPI_Init(void)
{
	SPI_InitTypeDef   SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO , ENABLE);	
  // Port B output
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_SetBits(GPIOB, GPIO_Pin_12);
  /* Configure SPIy pins: SCK, MISO and MOSI */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
	  /* SPI Config -------------------------------------------------------------*/
	  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
	  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
	  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
	  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
	  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
	  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
	  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	  SPI_InitStructure.SPI_CRCPolynomial = 7;

	  SPI_Init(SPI2, &SPI_InitStructure);
	  SPI_Cmd(SPI2, ENABLE);
}

http请求

void do_http(void)
{
  uint8 ch=SOCK_HTTP;
  uint16 len;

  st_http_request *http_request;
  memset(rx_buf,0x00,MAX_URI_SIZE);
  http_request = (st_http_request*)rx_buf;		// struct of http request  
  /* http service start */
  switch(getSn_SR(ch))
  {
    case SOCK_INIT:
      listen(ch);
      break;
    case SOCK_LISTEN:
      break;
    case SOCK_ESTABLISHED:
    //case SOCK_CLOSE_WAIT:
      if(getSn_IR(ch) & Sn_IR_CON)
      {
        setSn_IR(ch, Sn_IR_CON);
      }
      if ((len = getSn_RX_RSR(ch)) > 0)		
      {
        len = recv(ch, (uint8*)http_request, len); 
        *(((uint8*)http_request)+len) = 0;
        proc_http(ch, (uint8*)http_request); // request is processed
        disconnect(ch);
      }
      break;
    case SOCK_CLOSE_WAIT:   
      if ((len = getSn_RX_RSR(ch)) > 0)
      {
        //printf("close wait: %d\r\n",len);
        len = recv(ch, (uint8*)http_request, len);       
        *(((uint8*)http_request)+len) = 0;
        proc_http(ch, (uint8*)http_request); // request is processed
      }
      disconnect(ch);
      break;
    case SOCK_CLOSED:
      socket(ch, Sn_MR_TCP, 80, 0x00);    /* reinitialize the socket */
      break;
    default:
    break;
  }// end of switch
}


void JTXD_do_http(void)
{
  uint8 ch=SOCK_HTTP;
  uint16 len;

  st_http_request *http_request;
  memset(rx_buf,0x00,MAX_URI_SIZE);
  http_request = (st_http_request*)rx_buf;		// struct of http request
  
  /* http service start */
  switch(getSn_SR(ch))
  {
    case SOCK_INIT:
      listen(ch);
      break;
    case SOCK_LISTEN:

      break;
    case SOCK_ESTABLISHED:
    //case SOCK_CLOSE_WAIT:
      if(getSn_IR(ch) & Sn_IR_CON)
      {
        setSn_IR(ch, Sn_IR_CON);
      }
      if ((len = getSn_RX_RSR(ch)) > 0)		
      {
        len = recv(ch, (uint8*)http_request, len); 
        *(((uint8*)http_request)+len) = 0;
        JTXD_proc_http(ch, (uint8*)http_request); // request is processed
        disconnect(ch);
      }
      break;
    case SOCK_CLOSE_WAIT:   
      if ((len = getSn_RX_RSR(ch)) > 0)
      {
        //printf("close wait: %d\r\n",len);
        len = recv(ch, (uint8*)http_request, len);       
        *(((uint8*)http_request)+len) = 0;
        JTXD_proc_http(ch, (uint8*)http_request); // request is processed
      }
      disconnect(ch);
      break;
    case SOCK_CLOSED:                   
      socket(ch, Sn_MR_TCP, 80, 0x00);    /* reinitialize the socket */
      break;
    default:
    break;
  }// end of switch
}

五.参考文献

STM32+W5500以太网模块_机智的橙子的博客-CSDN博客

ModBus/TCP协议分析_kevin_bobolkevin的博客-CSDN博客_modbus通讯协议

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
W5500 Modbus TCP服务器断网时,可能会发生以下情况: 1. 无法与其他设备通信:W5500 Modbus TCP服务器无法接收或发送数据,从而无法与其他Modbus TCP客户端设备进行通信。这可能导致实时数据无法更新或无法进行监控和控制操作。 2. 网络连接中断:当W5500 Modbus TCP服务器断网时,它将无法与网络交换机、路由器或其他网络设备进行通信。这可能是由于网络故障、设备配置错误或设备硬件故障引起的。 3. 通信错误或超时:如果W5500 Modbus TCP服务器断网,它将无法与其他设备建立连接,因此可能会出现通信错误或超时。这可能导致数据丢失、数据传输失败或操作超时。 4. 无法访问服务器:当W5500 Modbus TCP服务器断网时,其他Modbus TCP客户端设备将无法访问服务器上的数据。这可能导致数据监控和控制系统无法正常运行,从而影响生产和操作过程。 为了解决W5500 Modbus TCP服务器断网的问题,可以采取以下措施: 1. 检查网络连接:确保网络连接正常,检查网络设备(交换机、路由器等)是否工作正常,并确认网络配置是否正确。 2. 检查服务器硬件:检查W5500 Modbus TCP服务器硬件是否正常,确认电源供应是否稳定,排除硬件故障的可能性。 3. 重新配置服务器:如果服务器配置文件或参数有误,可以重新配置W5500 Modbus TCP服务器,确保参数设置正确。 4. 检查网络故障:如果断网是由网络故障引起的,可以联系网络管理员或相关技术支持人员进行故障诊断和修复。 5. 备份和恢复数据:在解决问题之前,将重要数据备份,以免数据丢失。一旦恢复正常,可以将备份数据重新导入服务器。 总之,当W5500 Modbus TCP服务器断网时,需要进行详细的故障诊断和修复操作,以确保服务器能够正常运行,并重新建立与其他设备的通信连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值