STM32 以太网W5500

STM32+W5500以太网模块 一:w5500以太网模块介绍: W5500 是一款全硬件 TCP/IP 嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方 案。W5500 集成了 TCP/IP 协议栈,10/100M 以太网数据链路层(MAC) 及物理层(PHY),使得 用户使用单芯片就能够在他们的应用中拓展网络连接。 久经市场考验的 WIZnet 全硬件 TCP/IP 协议栈支持 TCP,UDP,IPv4,ICMP,ARP,IGMP 以及 PPPoE 协议。W5500 内嵌 32K 字节片上缓存以供以太网包处理。如果你使用 阅读详情

文章目录

    • W5500简介
    • 以太网接入方案
    • SPI读写访问
    • 寄存器以及地址
    • 源码以及配置
    • 实现 TCP Server
      • 三次握手过程
    • SPI 配置
    • 网络相关函数

W5500简介

W5500 是一款全硬件 TCP/IP 嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案。

特点:

  • 支持硬件 TCP/IP 协议: TCP, UDP, ICMP, IPv4, ARP, IGMP, PPPoE
  • 支持8个独立端口(Socket)同时通讯
  • 支持高速串行外设接口SPI( 80MHz 速率)
  • 内部32K字节收发缓存
  • LED状态显示
  • 支持掉电模式、网络唤醒

以太网接入方案

1、MAC+PHY方案
MCU内部自带MAC,由于软件协议栈操作需要主控不断响应中断,极大程度上占用了MCU的资源。
在这里插入图片描述
优缺点:
软件协议栈需要主控不断地响应中断,占用资源大,会影响通信质量
代码量占用大,内存资源占用多;安全角度,容易收到攻击

2、硬件协议方案
用硬件化的逻辑门电路实现所有的处理TCP/IP协议的工作。MCU只需要处理面向用户的应用层数据即可,传输、网络、链路层以及物理层全部由外围硬件芯片完成。
在这里插入图片描述
优缺点:
硬件协议栈,减少了单片机中断次数,通信速度快;
代码量少,比软件协议栈安全;
相比软件协议栈灵活性差,目前只支持8个socket

引脚连接

模块引脚说明单片机引脚
CS片选引脚PB12
CLKSPI时钟PB13
MISO主输入从输出PB14
MOSI主输出从输入PB15
INT中断引脚PC6
RST复位脚PC7
GND地GND
3V3电源3.3V供电3V3

SPI读写访问

W5500 的 SPI 数据帧包括了 16 位地址段的偏移地址, 8 位控制段和 N 字节数据段。
在这里插入图片描述
写访问
在这里插入图片描述

  • 在 VDM (可变数据长度模式)模式下, SPI 数据帧的控制段:读写控制位(RWB)为‘1’,如果是读则为‘0’,工作模式位为’00’。
  • 此时外设主机在传输 SPI 数据帧之前,须拉低 SCSn 信号引脚。
  • 然后主机通过 MOSI 将 SPI 数据帧的所有位传输给 W5500 ,并在 SCLK 的下降沿同步。
  • 在完成 SPI 数据帧的传输后,主机拉高 SCSn 信号(低电平到高电平)。
  • 当 SCSn 保持低电平且数据段持续传输,即可实现连续数据写入。

1 字节数据写访问示例

Offset Address = 0x0018
BSB[4:0] = ‘00000’
RWB = ‘1’
OM[1:0] = ‘00’
1st Data = 0xAA

在这里插入图片描述

在传输 SPI 数据帧之前, 外设主机须拉低 SCSn,然后主机在时钟(SCLK)跳变时同步
传输 1 位数据。在 SPI 数据帧传输完毕后,外设主机拉高 SCSn

寄存器以及地址

W5500 有 1 个通用寄存器,8 个 Socket 寄存器区,以及对应每个 Socket 的收/发缓存区。每个区域均通过 SPI 数据帧的区域选择位(BSB[4:0])来选取。
每个 Socket 分配多大的收/发缓存,必须在 16 位的偏移地址范围内(从0x0000 到 0xFFFF)
在这里插入图片描述
以下对地址的一些理解
在寄存器偏移计算的宏定义,采用宏定义方便计算socket n所使用的地址

#define WIZCHIP_CREG_BLOCK          0x00 	//< Common register block
#define WIZCHIP_SREG_BLOCK(N)       (1+4*N) //< Socket N register block
#define WIZCHIP_TXBUF_BLOCK(N)      (2+4*N) //< Socket N Tx buffer address block
#define WIZCHIP_RXBUF_BLOCK(N)      (3+4*N) //< Socket N Rx buffer address block

手册中的地址与源码中地址理解
手册中IP地址的定义
在这里插入图片描述
.h文件中的宏定义为

#define SIPR0                       (0x000F00)
#define SIPR1                       (0x001000)
#define SIPR2                       (0x001100)
#define SIPR3                       (0x001200)

SPI读写操作中,地址操作,高位要偏移16,低要偏移8 ,这与地址的宏定义向左偏移8相符合。
读写函数地址偏移如下:

   SPI_SendByte( (addrbsb & 0x00FF0000)>>16);//偏移16	
   SPI_SendByte( (addrbsb & 0x0000FF00)>> 8);//偏移8

源码以及配置

驱动源码

文件说明
W5500_conf.c主要配置W5500的MAC,IP地址,W5500基本的数据读写过程,服务设置函数等
Socket.c设置socket的打开、关闭、以及接收数据、发送数据等
w5500.c主要完成W5500的寄存器读写过程

W5500的socket初始化过程
1、基本配置

  • 模式寄存器(MR)
  • 中断屏蔽寄存器(IMR)
  • 重发时间寄存器(RTR)
  • 重发计数寄存器(RCR)

2、网络设置

  • 网关地址寄存器(GAR)
  • 本机物理地址寄存器(SHAR)
  • 子网掩码寄存器(SUBR)
  • 本机IP地址寄存器

3、端口设置,数据收发缓冲区
W5500 有 1 个通用寄存器,8 个 Socket 寄存器区,以及对应每个 Socket 的收/发缓存区。每一个 Socket 的发送缓存区都在一个 16KB 的物理发送内存中,初始化分配为 2KB。每一个 Socket 的接收缓存区都在一个 16KB 的物理接收内存中,初始化分配为 2KB。

4、应用层协议开发

支撑协议:域名服务系统(DNS),简单网络管理协议(SNMP)
应用协议:超文本传输协议(HTTP),简单邮件传输协议(SMTP),文件传输协议(FTP),简单文件传输协议(TFTP)和远程登录(Telnet)

实现 TCP Server

它使用 IP 作为网络层,提供全双工的和可靠交付的服务。TCP 建立通信的两端一端称为服务器端,另一端为客户端。

reactor模式epoll
多路复用 select poll epoll
多进程,多线程方式

三次握手过程

详细了解三次握手请参考 深入源码了解三次握手
TCP 协议通过三个报文段完成连接的建立,这个过程称为三次握手

1,第一次握手:建立连接时,客户端发送 SYN 包(seq=j)到服务器,并进入SYN_SEND 状态,等待服务器确认。
2,第二次握手:服务器收到 SYN 包,必须确认客户的 SYN(ack=j+1),同时自己也发送一个 SYN 包(seq=k),即 SYN+ACK 包,此时服务器进入 SYN_RECV状态。
3,第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手

在这里插入图片描述

SPI 配置

数据传输SPI总线,CS片选引脚拉低,发送数据,拉高结束发送数据

#define WIZ_SPIx_GPIO_PORT      GPIOB				      /* GPIO端口   */
#define WIZ_SPIx_GPIO_CLK       RCC_APB2Periph_GPIOB	   /* GPIO时钟*/
#define WIZ_SPIx                SPI2                   	   /*W5500所使用的SPI     */
#define WIZ_SPIx_CLK_CMD        RCC_APB1PeriphClockCmd
#define WIZ_SPIx_CLK            RCC_APB1Periph_SPI2    	   /* W5500所使用的SPI 时钟 */
#define WIZ_SPIx_SCLK           GPIO_Pin_13			       /* W5500所使用的CLK      */
#define WIZ_SPIx_MISO           GPIO_Pin_14				   /* W5500所使用的 MISO       */
#define WIZ_SPIx_MOSI           GPIO_Pin_15			       /* W5500所使用的 MOSI     */

void gpio_for_w5500_config(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  //开 RESET与片选引脚的时钟
  RCC_APB2PeriphClockCmd(WIZ_SPIx_RESET_CLK|WIZ_SPIx_INT_CLK, ENABLE);
  //开 CLK与片选引脚的时钟
  RCC_APB2PeriphClockCmd(WIZ_SPIx_GPIO_CLK|WIZ_SPIx_SCS_CLK, ENABLE);

  /*SPI Periph clock enable */
  WIZ_SPIx_CLK_CMD(WIZ_SPIx_CLK, ENABLE);

  /* Configure SCK */
  GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_SCLK;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(WIZ_SPIx_GPIO_PORT, &GPIO_InitStructure);

  /*Configure MISO */
  GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_MISO;
  GPIO_Init(WIZ_SPIx_GPIO_PORT, &GPIO_InitStructure);

  /*Configure MOSI */
  GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_MOSI;
  GPIO_Init(WIZ_SPIx_GPIO_PORT, &GPIO_InitStructure);

  /*Configure CS pin */
  GPIO_InitStructure.GPIO_Pin = WIZ_SPIx_SCS;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(WIZ_SPIx_SCS_PORT, &GPIO_InitStructure);

  /* SPI1 configuration */
  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_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  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(WIZ_SPIx, &SPI_InitStructure);
  SPI_Cmd(WIZ_SPIx, ENABLE);
	
  /*复位引脚*/
  GPIO_InitStructure.GPIO_Pin = WIZ_RESET;					        
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		     
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;		     
  GPIO_Init(WIZ_SPIx_RESET_PORT, &GPIO_InitStructure);		 
  GPIO_SetBits(WIZ_SPIx_RESET_PORT, WIZ_RESET);		
  
  /*INT引脚*/	
  GPIO_InitStructure.GPIO_Pin = WIZ_INT;						       
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		     
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;				     
  GPIO_Init(WIZ_SPIx_INT_PORT, &GPIO_InitStructure);			 
}

SPI写函数

uint8_t SPI_SendByte(uint8_t byte)
{
  /* 检测数据寄存器状态*/
  while (SPI_I2S_GetFlagStatus(WIZ_SPIx, SPI_I2S_FLAG_TXE) == RESET);
  /* 发送数据 */
  SPI_I2S_SendData(WIZ_SPIx, byte);
  /* 等待接收一个字节 */
  while (SPI_I2S_GetFlagStatus(WIZ_SPIx, SPI_I2S_FLAG_RXNE) == RESET);
  /*返回从SPI上接收到的一个字节 */
  return SPI_I2S_ReceiveData(WIZ_SPIx);
}

SPI 片选

void wiz_cs(uint8_t val)
{
	if (val == LOW) 
	{
	  GPIO_ResetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS); 
	}
	else if (val == HIGH)
	{
	  GPIO_SetBits(WIZ_SPIx_SCS_PORT, WIZ_SPIx_SCS); 
	}
}
void iinchip_csoff(void)
{
	wiz_cs(LOW);
}
void iinchip_cson(void)
{	
   wiz_cs(HIGH);
}
/*写*/
void IINCHIP_WRITE( uint32 addrbsb,  uint8 data)
{
   iinchip_csoff();                              	
   SPI_SendByte( (addrbsb & 0x00FF0000)>>16);//偏移16	
   SPI_SendByte( (addrbsb & 0x0000FF00)>> 8);//偏移8
   SPI_SendByte( (addrbsb & 0x000000F8) + 4);  
   SPI_SendByte(data);                   
   iinchip_cson();                            
}
/*读*/
uint8 IINCHIP_READ(uint32 addrbsb)
{
   uint8 data = 0;
   iinchip_csoff();                            
   SPI_SendByte( (addrbsb & 0x00FF0000)>>16);
   SPI_SendByte( (addrbsb & 0x0000FF00)>> 8);
   SPI_SendByte( (addrbsb & 0x000000F8))    ;
   data = SPI_SendByte(0x00);            
   iinchip_cson();                               
   return data;    
}

读写数据

uint16 wiz_write_buf(uint32 addrbsb,uint8* buf,uint16 len)
{
   uint16 idx = 0;
   if(len == 0) 
   		printf("Unexpected2 length 0\r\n");
   iinchip_csoff();                               
   SPI_SendByte( (addrbsb & 0x00FF0000)>>16);
   SPI_SendByte( (addrbsb & 0x0000FF00)>> 8);
   SPI_SendByte( (addrbsb & 0x000000F8) + 4); 
   for(idx = 0; idx < len; idx++)
   {
     SPI_SendByte(buf[idx]);
   }
   iinchip_cson();                           
   return len;  
}

uint16 wiz_read_buf(uint32 addrbsb, uint8* buf,uint16 len)
{
  uint16 idx = 0;
  if(len == 0)
    printf("Unexpected2 length 0\r\n");
    
  iinchip_csoff();                                
  SPI_SendByte( (addrbsb & 0x00FF0000)>>16);
  SPI_SendByte( (addrbsb & 0x0000FF00)>> 8);
  SPI_SendByte( (addrbsb & 0x000000F8));    
  for(idx = 0; idx < len; idx++)                   
  {
    buf[idx] = SPI_SendByte(0x00);
  }
  iinchip_cson();                                  
  return len;
}

网络相关函数

配置MAC地址

#define SHAR0                       (0x000900)//寄存器地址查看手册

void setSHAR(uint8 * addr)
{
  wiz_write_buf(SHAR0, addr, 6);  
}

void set_w5500_mac(void)
{
	memcpy(ConfigMsg.mac, mac, 6);
	setSHAR(ConfigMsg.mac);	/**/
	memcpy(DHCP_GET.mac, mac, 6);
}
/**brief Subnet mask Register address*/
#define SUBR0                       (0x000500)
#define SUBR1                       (0x000600)
#define SUBR2                       (0x000700)
#define SUBR3                       (0x000800)
/**brief Source MAC Register address*/
#define SHAR0                       (0x000900)
#define SHAR1                       (0x000A00)
#define SHAR2                       (0x000B00)
#define SHAR3                       (0x000C00)
#define SHAR4                       (0x000D00)
#define SHAR5                       (0x000E00)
/**@brief Source IP Register address*/
#define SIPR0                       (0x000F00)
#define SIPR1                       (0x001000)
#define SIPR2                       (0x001100)
#define SIPR3                       (0x001200)
//设置IP地址
void set_w5500_ip(void)
{	
···
	setSUBR(ConfigMsg.sub);//配置子网掩码
	setGAR(ConfigMsg.gw);//配置网关
	setSIPR(ConfigMsg.lip);//配置IP
	···
}

主循环

void do_tcp_server(void)
{	
	uint16 len=0;  
	switch(getSn_SR(SOCK_TCPS))	/*获取socket状态*/
	{
		case SOCK_CLOSED:/*关闭状态*/
			socket(SOCK_TCPS ,Sn_MR_TCP,local_port,Sn_MR_ND);	   /*创建SOCKET*/
		  break;     
		case SOCK_INIT:/*socket已初始化状态*/
			listen(SOCK_TCPS);	/*建立监听*/
		  break;
		case SOCK_ESTABLISHED:	/*建立连接状态*/
			if(getSn_IR(SOCK_TCPS) & Sn_IR_CON)
			{
				setSn_IR(SOCK_TCPS, Sn_IR_CON);		 /*清除接收中断*/
			}
			len=getSn_RX_RSR(SOCK_TCPS);/*接收数据长度*/
			if(len>0)
			{
				recv(SOCK_TCPS,buff,len);	/*接收来自client数据*/
				buff[len]=0x00;
				printf("%s\r\n",buff);
				send(SOCK_TCPS,buff,len)/*向client发送数据*/
		  }
		  break;
		case SOCK_CLOSE_WAIT:/*关闭状态*/
			close(SOCK_TCPS);
		  break;
	}
}

主函数下,子函数的实现

uint8 socket(SOCKET s, uint8 protocol, uint16 port, uint8 flag)
{
   uint8 ret;
   if (
        ((protocol&0x0F) == Sn_MR_TCP)    || ((protocol&0x0F) == Sn_MR_UDP)    ||
        ((protocol&0x0F) == Sn_MR_IPRAW)  || ((protocol&0x0F) == Sn_MR_MACRAW) ||
        ((protocol&0x0F) == Sn_MR_PPPOE)
      )
   {
      close(s);
      //Socket n模式寄存器  0 0 0 1 写值  设置为TCP模式
      IINCHIP_WRITE(Sn_MR(s) ,protocol | flag);
      if (port != 0) {
      	 //写端口号
         IINCHIP_WRITE( Sn_PORT0(s) ,(uint8)((port & 0xff00) >> 8));
         IINCHIP_WRITE( Sn_PORT1(s) ,(uint8)(port & 0x00ff));
      } else {
         local_port++; // if don't set the source port, set local_port number.
         IINCHIP_WRITE(Sn_PORT0(s) ,(uint8)((local_port & 0xff00) >> 8));
         IINCHIP_WRITE(Sn_PORT1(s) ,(uint8)(local_port & 0x00ff));
      }
      //Socket n 配置寄存器  0x01 OPEN 打开
      IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_OPEN); 
      /* 等待命令处理*/
      while( IINCHIP_READ(Sn_CR(s)) );
      ret = 1;
   }
   else
   {
      ret = 0;
   }
   return ret;
}
uint8 listen(SOCKET s)
{
   uint8 ret;
   //Socket n 状态寄存器   0x13 SOCK_INIT
   if (IINCHIP_READ( Sn_SR(s) ) == SOCK_INIT)
   {
      //Socket n 配置寄存器  0x02 LISTEN
      IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_LISTEN);
      /* 等待命令处理 */
      while( IINCHIP_READ(Sn_CR(s) ) );
      ret = 1;
   }
   else
   {
      ret = 0;
   }
   return ret;
}
uint8 connect(SOCKET s, uint8 * addr, uint16 port)
{
    uint8 ret;
    if
        (
            ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
            ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
            (port == 0x00)
        )
    {
      ret = 0;
    }
    else
    {
        ret = 1;
        // 设置目的 IP
        IINCHIP_WRITE( Sn_DIPR0(s), addr[0]);
        IINCHIP_WRITE( Sn_DIPR1(s), addr[1]);
        IINCHIP_WRITE( Sn_DIPR2(s), addr[2]);
        IINCHIP_WRITE( Sn_DIPR3(s), addr[3]);
        //端口
        IINCHIP_WRITE( Sn_DPORT0(s), (uint8)((port & 0xff00) >> 8));
        IINCHIP_WRITE( Sn_DPORT1(s), (uint8)(port & 0x00ff));
        //设置状态 connect
        IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_CONNECT);
        /* 等待命令处理完成 */
        while ( IINCHIP_READ(Sn_CR(s) ) ) ;

        while ( IINCHIP_READ(Sn_SR(s)) != SOCK_SYNSENT )
        {
            //获取状态寄存器 0x17 SOCK_ESTABLISHED
            if(IINCHIP_READ(Sn_SR(s)) == SOCK_ESTABLISHED)
            {
                break;
            }
            //只读 超时
            if (getSn_IR(s) & Sn_IR_TIMEOUT)
            {
                IINCHIP_WRITE(Sn_IR(s), (Sn_IR_TIMEOUT));  // clear TIMEOUT Interrupt
                ret = 0;
                break;
            }
        }
    }
   return ret;
}
uint16 send(SOCKET s, const uint8 * buf, uint16 len)
{
  uint8 status=0;
  uint16 ret=0;
  uint16 freesize=0;

  if (len > getIINCHIP_TxMAX(s)) 
  	ret = getIINCHIP_TxMAX(s); // 检查不超过最大值
  else ret = len;

  // if freebuf is available, start.
  do
  {
    //get socket TX free buf size
    freesize = getSn_TX_FSR(s);
    status = IINCHIP_READ(Sn_SR(s));
    if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT))
    {
      ret = 0;
      break;
    }
  } while (freesize < ret);
  
  // copy data
  send_data_processing(s, (uint8 *)buf, ret);
  IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_SEND);
  /* 等待处理 */
  while( IINCHIP_READ(Sn_CR(s) ) );

  while ( (IINCHIP_READ(Sn_IR(s) ) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
  {
    status = IINCHIP_READ(Sn_SR(s));
    if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT) )
    {
      printf("SEND_OK Problem!!\r\n");
      close(s);
      return 0;
    }
  }
  IINCHIP_WRITE( Sn_IR(s) , Sn_IR_SEND_OK);

#ifdef __DEF_IINCHIP_INT__
   putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
#else
   IINCHIP_WRITE( Sn_IR(s) , Sn_IR_SEND_OK);
#endif

   return ret;
}
void send_data_processing(SOCKET s, uint8 *data, uint16 len)
{
  uint16 ptr =0;
  uint32 addrbsb =0;
  if(len == 0)
  {
    printf("CH: %d Unexpected1 length 0\r\n", s);
    return;
  }
  //获取要写数据的地址,存器的值,表示数据在0-FFFF里存到了多少数
  ptr = IINCHIP_READ( Sn_TX_WR0(s) );
  ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR1(s));

  addrbsb = (uint32)(ptr<<8) + (s<<5) + 0x10;//数据帧控制位00010 0 00
  wiz_write_buf(addrbsb, data, len);
  
  ptr += len;记录发送缓存区已经写到了多少,存在发送写指针寄存器中
  IINCHIP_WRITE( Sn_TX_WR0(s) ,(uint8)((ptr & 0xff00) >> 8));
  IINCHIP_WRITE( Sn_TX_WR1(s),(uint8)(ptr & 0x00ff));
}

STM32 以太网W5500_为了维护世界和平_的博客-CSDN博客

STM32F103+W5500网络通信 STM32F103+W5500网络通信一、W5500模块(一)W5500以太网模块介绍(二)模块排针功能表二、 modbus协议(一)modbus协议原理(二)Modbus 通讯方式1.Modbus三种通讯方式2.在Modbus网络上传输3.以太网(modbus tcp/ip)三、参考资料 一、W5500模块 (一)W5500以太网模块介绍 D-W5500 EVB以太网模块是一款基于WIZnet W5500芯片的以太网模块,且性价比高的以太网模块。W5500是一款全硬件TCP/IP嵌入式以太网控制器,为 阅读详情

相关推荐

w5500模块——tcp通讯

W5500 是一款全硬件 TCP/IP 嵌入式以太网控制器,为嵌入式系统提供了更加 简易的互联网连接方案。W5500 集成了 TCP/IP 协议栈,10/100M 以太网数据链路 层(MAC)及物理层(PHY),使得用户使用单芯片就能够在他们的应用中拓展网络连接。WIZnet 全硬件 TCP/IP 协议栈支持 TCP,UDP,IPv4,ICMP, ARP,IGMP 以及 PPPoE 协议。支持8个独立端口(Socket)同时通讯。W5500 内嵌 32K 字节片上缓存以供以太网包处理。

m0_73109662的博客 2657

网络知识汇总(基于W5500以太网)

本文详细介绍了以太网、互联网、IP地址、子网掩码、网关和MAC地址的基础知识,涉及网络通信原理、协议结构、地址分配及其作用,以及在智能设备联网中的应用。重点讲解了如何设置这些参数以实现设备间的通讯和信息共享。

让你爱上电路设计 7718

基于stm32之w5500以太网应用

基于stm32之w5500以太网应用 强调一下前半段为基础知识普及(这段还是很重要的。不管用什么工具开发精通协议才是王道),后半段为实战代码干货。 如上图所示,最底下的一层叫做“物理层”,也叫“PHY 层”,最上面的一层叫做“应用层”,中间的三层(自下而上)分别是“链路层”,也叫“MAC 层”、 “网络层”和“传输层”。越下面的层,越靠近硬件;越上面的层,越靠近用户。 我们一层一层讲解 一、物理层 物理层就是最基础的类似于modbus中的硬件连接是rs485的两根线。物理层由计算机和网络介质之间的实际界面

jwgdhuwdhg的博客 6951

5. w5500模块

打开ping例程,找到w5500_conf.c文件,将第13行的远端IP设置为你主机的IP,编译后下载,打开串口助手即可看到调试信息。1234567891011121314/*定义MAC地址,如果多块W5500网络适配板在同一现场工作,请使用不同的MAC地址*//*定义默认IP信息*//*定义W5500默认IP地址*//*定义W5500默认子网掩码*//*定义W5500默认网关*//*定义W5500默认DNS*//*定义本地端口*/

木牛的博客 6682

基于STM32的W5500以太网模块硬件设计深度剖析

深入解析基于STM32的W5500以太网模块硬件设计,重点剖析w5500以太网模块原理图中的关键电路与布线技巧,为嵌入式网络开发提供可靠参考。

weixin_42509888的博客 1051

W5500以太网模块SPI接口配置:STM32平台手把手教程

深入解析w5500以太网模块原理图与SPI通信机制,手把手实现STM32平台的驱动开发,帮助开发者快速掌握w5500以太网模块原理图设计要点与硬件连接逻辑。

weixin_31185473的博客 953

STM32 W5500以太网通讯

STM32 W5500以太网通讯实现 对于内含以太网MAC部分的芯片,可以外部增加以太网PHY芯片和连接器,实现以太网通讯。对于内部没有以太网MAC部分的芯片,通过W5500 SPI转Ethernet芯片实现以太网通讯是比较好的方式。采用W5500芯片,可以不占用MCU的内存部分做buffer,对于MCU业务逻辑时序紧张的场景也有使用价值。MCU和W5500可以通过SPI的DMA方式,实现较快的收发逻辑;W5500最大支持到80Mbps的SPI接口速度,实际情况根据MCU的SPI接口速率和PCB高速布线质量

Pegasus的软件博客 7547

W5500以太网模块原理图详解:STM32平台完整指南

深入解析w5500以太网模块原理图的关键设计要点,结合STM32平台实现稳定通信,帮助开发者快速掌握硬件连接与配置技巧,提升项目开发效率。

weixin_30476025的博客 1129

STM32传感器模块编程实践(二)W5500 SPI转以太网模块简介及驱动源码

本文介绍了 W5500芯片以及W5500模块,并通过STM32F103C8T6单片机驱动W5500模块实现以太网TCP/IP数据通讯。电脑作为TCP服务器,开发板作为TCP客户端,提供参考例程

光子物联科技主要介绍STM32单片机,GD32单片机以及各种传感器模块原理以及驱动,适合学生,工程师等学习单片机嵌入式开发、传感器驱动、通信协议等。 1万+

STM32CubeMX | 38-使用硬件SPI驱动以太网模块(W5500)

本篇详细的记录了如何使用STM32CubeMX配置STM32L431RCT6的硬件SPI外设与以W5500通信,驱动以太网模块。 1. 准备工作 硬件准备 开发板 首先需要准备一个开发板,这里我准备的是STM32L4的开发板(BearPi): W5500以太网模块 这里我使用常见的以太网模块W5500: W5500官网 http://www.w5500.cn/ W5500中文手册 iEthernet W5500 Datasheet 软件准备 需要安装好Keil - MDK及芯片对应的包,以

Mculover666的博客(嵌入式) 7368

STM32与W5500嵌入式以太网应用实战

W5500是硬件网络协议栈支持的以太网控制器,它基于TCP/IP协议栈实现硬件级别的网络通信。它内置了全硬化的TCP/IP协议栈,可以处理TCP, UDP, IPv4, ICMP, ARP以及IGMP协议。这种设计大大减少了MCU的负担,使得微控制器可以专注于执行其它任务。W5500拥有8个独立的socket,每一个socket能够提供独立的TCP连接。通过一个简单的网络API,用户可以配置和管理W5500,实现网络通讯功能。

weixin_28793831的博客 1154

【亲测免费】 STM32H743VIT6与W5500以太网通讯例程

STM32H743VIT6与W5500以太网通讯例程 【下载地址】STM32H743VIT6与W5500以太网通讯例程 本项目提供了基于STM32H743VIT6微控制器和W5500以太网控制芯片的通信例程。通过SPI接口,STM32H743VIT6能够有效地控制W5500执行TCP Server功能,实现设备的网络通信...

gitblog_09803的博客 899

ROS自定义地图实战:从CAD到导航的完整流程

本文详细介绍了如何将CAD图纸或手绘草图高效转换为ROS机器人可直接使用的导航地图。通过解析PGM与YAML标准格式,提供从图像处理、尺度校准到集成AMCL与move_base导航栈的完整实战流程,帮助开发者跳过繁琐的SLAM建图,实现快速、精准的自定义地图部署。

weixin_29083475的博客 492

【亲测免费】 STM32+W5500以太网模块资源介绍

STM32+W5500以太网模块资源介绍 去发现同类优质开源项目:https://gitcode.com/ 本资源文件提供了关于如何使用STM32单片机配合W5500以太网模块进行网络通信的详细教程和代码示例。通过本资源,您可以学习到以下内容: 1. W5500以太网模块介绍 W5500模块是一款基于WIZnet W5500芯片的以太网模块,具有高性能和性价比高的特点。模块支持硬件化的TCP/IP...

gitblog_06505的博客 610

紫光PG2L100H平台DDR3 IP核调试实战:从AXI接口到状态机设计的避坑指南

本文详细介绍了在紫光PG2L100H FPGA平台上调试DDR3 IP核的实战经验,重点解析了AXI接口的特殊行为和状态机设计的关键技巧。通过具体代码示例和调试方法,帮助开发者规避常见陷阱,实现高性能DDR3控制器设计,达到1.2GB/s的稳定带宽。

weixin_28717969的博客 215

Monocle2在R 4.3环境下的终极避坑指南:从安装到可视化全流程解析

本文提供了在R 4.3环境下安装和运行Monocle2的完整解决方案,重点解决了依赖包兼容性、源码修改及BEAM分析报错等关键问题。文章详细解析了从环境准备、依赖包处理、源码安装验证到从Seurat对象转换、拟时轨迹构建、高级可视化及性能优化的全流程,旨在帮助用户顺利完成单细胞拟时分析。

weixin_29206669的博客 1348

探索物联网的无限可能:STM32+W5500以太网模块资源推荐

探索物联网的无限可能:STM32+W5500以太网模块资源推荐 去发现同类优质开源项目:https://gitcode.com/ 在物联网(IoT)快速发展的今天,嵌入式系统与网络通信的结合成为了技术发展的关键。STM32与W5500以太网模块的结合,为开发者提供了一个强大且灵活的平台,能够轻松实现各种网络通信需求。本文将详细介绍这一开源项目,帮助您快速上手并应用于实际项目中。 1. 项目介绍 本...

gitblog_06589的博客 549

Cursor聊天记录迁移工具:实现跨设备AI对话同步与备份

在软件开发中,数据持久化与迁移是常见需求,尤其当工具依赖本地存储时。SQLite作为轻量级关系型数据库,因其嵌入式、零配置特性,常被用于存储应用状态与用户数据。其WAL(预写式日志)模式提升了并发性能,但也增加了数据操作复杂性。通过命令行工具与JSON序列化技术,可以实现结构化数据的提取、转换与安全迁移,这对于保障开发资产的连续性与可移植性具有重要价值。例如,在AI辅助编程场景下,开发者与AI的对话记录包含关键的问题分析、解决方案与决策逻辑,是重要的上下文资产。cursor-chat-transfer工具正

weixin_42551967的博客 526

stm32 w5500以太网模块使用

写完标题发现好像也没什么可写的. 主要是硬件的东西从来没这么顺利过,总结一下 1.买了之后送的文档,挺详细的,即便如此接线没有说 3.3v 和gnd要接.他们可能认为这是常识猪都知道, 但确实有人不知道比如搞软件的我,但我的直觉让我接上 2.有问题的时候硬件相关会很不容易找,比如我的板子开关接触不良了,但我没贴个标签在上面,所以烧录好程序后一直没电,是通过吧仿真器插在usb 这样才提供了稳定的电压 3.keil v5 是我的ide ,但示例程序是v4的,并不兼容 表现为cpu没有在我的列表里,编译好之后烧

wangduqiang747的博客 3204

飞书组织架构同步至LDAP:实现企业应用统一身份认证的实战指南

本文详细介绍了如何将飞书组织架构同步至LDAP,实现企业应用统一身份认证的实战方案。通过飞书开放平台API与LDAP服务的集成,企业可以大幅减少账号管理工作量,提升IT效率。文章涵盖技术架构设计、密码策略、详细配置步骤及自动化同步实现,特别适合需要统一认证体系的中大型企业。

weixin_29172201的博客 325

毫米波雷达之CFAR 目标检测

恒虚警率(CFAR)算法是一种广泛应用于雷达目标检测的算法,其主要目 标是减少由于杂波与回波之间强度不对称而引起的误报,以确保相对恒定的虚警 率。如图 3.4(a)所示,表示由距离单元组成的一维数据。在待测单元 D 周围选 择若干个背景杂波功率的蓝色单元构成参考滑窗,称为参考单元;而待测单元 D 相邻的若干个不用于背景估计的单元则称为保护单元。当参考单元和保护单元的 维度从一维扩展到二维时,相应的 CFAR 检测由一维 CFAR 演变为二维 CFAR 以处理参考窗口,如图 3.4 (b)所示。

m0_56120826的博客 4912

W5500以太网模块在STM32最小系统中的集成方法新手教程

详解W5500以太网模块原理图及其在STM32最小系统中的连接方式,帮助新手快速掌握硬件接口与软件配置要点,实现稳定网络通信。

weixin_35756637的博客 1049

基于Pascal VOC数据集的YOLOv8目标检测系统实现:人、鸟、猫、牛、电视、车等20类目标识别与UI界面部署全流程详解

VOC 2007、VOC 2012 两个主要版本;每个图像提供 bounding box(目标框)+ 目标类别;共计 20 类,所有图像手工标注,质量高。完整复现 Pascal VOC 20类检测任务成功训练 YOLOv8 模型实现可视化 UI + 实时检测系统支持多平台部署和演示。

YOLO 770

【亲测免费】 STM32H7与W5500以太网程序资源介绍

STM32H7与W5500以太网程序资源介绍 去发现同类优质开源项目:https://gitcode.com/ 资源文件概述 本仓库提供了一个名为“STM32H7+以太网W5500程序.rar”的资源文件,该文件结合了STM32H7系列芯片与W5500以太网模块的移植内容。资源文件中详细介绍了如何将W5500模块移植到STM32H7平台上,并提供了客户端和服务器的建立步骤,以及相关的通信实现方法。...

gitblog_09729的博客 692

PCL 循环体素滤波

本文提出了一种自动循环体素滤波算法,用于解决点云配准中分辨率差异大、参数设置复杂的问题。算法通过计算点云分辨率(公式1),采用迭代方式调整体素尺寸(公式2),逐步逼近目标分辨率。该方法在保留几何特征的同时有效精简数据量,实现了均匀分辨率的自动调整。实验通过PCL库实现,展示了原始点云与滤波结果的对比效果,验证了算法在减少数据规模方面的有效性。该方法为点云配准提供了预处理解决方案,相关成果已发表于SCI期刊。

点云侠的博客 279

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: 运算放大器的关键指标详解一(失调与偏置)
下一篇: stm32开发层次介绍(转载)
致守
博客等级 码龄15年 7万+粉丝 25原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值