---
title: "基于STM32和W5500的Modbus TCP通?"
url: "https://maker.wiznet.io/chen/projects/STM32W5500Modbus-TCP/"
markdown_url: "https://maker.wiznet.io/chen/projects/STM32W5500Modbus-TCP/md"
type: "UCC: User Created Content"
author: "chen"
author_url: "https://maker.wiznet.io/chen/"
original_author: "chen"
original_url: "https://www.cnblogs.com/foxclever/p/5717844.html"
published: "2021-07-06"
language: "zh"
likes: 0
views: 850
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# 基于STM32和W5500的Modbus TCP通?

> 基于STM32和W5500的Modbus TCP通?

Original author: chen (source: https://www.cnblogs.com/foxclever/p/5717844.html)

## Article

在最近的一??目中需要??Modbus TCP通?，而?用的硬件平台?是STM32F103和W5500，?件平台??用IAR EWAR6.4???。

1、移植千的准?工作 ?了??Modbus TCP通?首先需要下?W5500的??源?，可以到WIZnet的官?下?： http://wizwiki.net/wiki/doku.php?id=products:w5500:driver 下?下?的??包，解?后如下?： ![](https://images2015.cnblogs.com/blog/564295/201607/564295-20160729114752841-719576789.png) 需要?ethernet文件?拷?到我?的?目目?中： ![](https://images2015.cnblogs.com/blog/564295/201607/564295-20160729114809169-1986001505.png) ?在IAR的?目下添加相?的文件和路?，主要是socket.c、w5500.c、wizchip_.conf.c三?文件。?三?文件分???socket、硬件??及相?通?配置功能，具?可以?看相?的源??手?。 ![](https://images2015.cnblogs.com/blog/564295/201607/564295-20160729114822419-993322247.png) ?在如下?所示的?目???置中添加Ethernet和EthernetW5500目?。 ![](https://images2015.cnblogs.com/blog/564295/201607/564295-20160729114832169-356279444.png)![](https://images2015.cnblogs.com/blog/564295/201607/564295-20160729114838825-1064665033.png) 2、移植?程和代??? 在完成以上工作后就可以?始?正地移植工作了。具?步?如下：

- 硬件配置及初始化。

- 以太?通?配置的初始化。

- ??具?的通??程。

2.1、硬件的配置及初始化 由于W5500通?SPI接口?STM32通?，所以硬件配置和初始化是非常??的，?W5500??上?有?系，使一些通用的操作。事?上就是STM32F103的SPI接口初始化的?程，需要??RCC、GPIO以及SPI的初始化就可以了。?于?部分可以?看ST的例程。 2.2、以太?通?配置的初始化 以太?通?配置的初始化主要有三?方面的?容：

- 注?TCP通?相?的回?函?? RegisterFunction();

- 初始化芯片??? ChipParametersConfiguration();

- 初始化??通???? NetworkParameterConfiguration()

三?函?的具????容如下：

![?制代?](https://common.cnblogs.com/images/copycode.gif)

```
//函?注?，首先,?由用???SPI注?回?函????WIZCHIP
void RegisterFunction(void)
{  
  //?界?回?函?
  reg_wizchip_cris_cbfunc(SPI_CrisEnter, SPI_CrisExit);    //注??界?函?
  //片?回?函?
#if   _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_
  reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);//注?SPI片?信?函?
#elif _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_FDM_
  reg_wizchip_cs_cbfunc(SPI_CS_Select, SPI_CS_Deselect);  // CS必??低?平.
#else
   #if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SIP_) != _WIZCHIP_IO_MODE_SIP_
      #error "Unknown _WIZCHIP_IO_MODE_"
   #else
      reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
   #endif
#endif
  //SPI的??回?函?
  reg_wizchip_spi_cbfunc(SPI_ReadByte, SPI_WriteByte);    //注???函?
}
```

![?制代?](https://common.cnblogs.com/images/copycode.gif)

注?函???上就是函?指?的?用，可?考C?言函?指?部分?容。?于以上注?的函?，SPI_WriteByte需要?明一下，无?是用可函??是直接操作寄存器，在?完之后都需要再?一下（?色部分），否?就?在客?端出??接TCPServer超?的?警，?明白什?原因。

![?制代?](https://common.cnblogs.com/images/copycode.gif)

```
//?1字??据到SPI??

void SPI_WriteByte(uint8_t TxData)

{                       

//  while((SPI2->SR&SPI_I2S_FLAG_TXE)==0);        //等待?送?空              

//  SPI2->DR=TxData;                              //?送一?byte

//  while((SPI2->SR&SPI_I2S_FLAG_RXNE)==0);       //等待接收完一?byte 

//  SPI2->DR;

  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);        //等待?送?空

  SPI_I2S_SendData(SPI2,TxData);                                        //?送一?byte

  while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) == RESET);        //等待接收完一?byte

  SPI_I2S_ReceiveData(SPI2);                                            //返回接收的?据

}
```

![?制代?](https://common.cnblogs.com/images/copycode.gif)

初始化芯片??：

![?制代?](https://common.cnblogs.com/images/copycode.gif)

```
//初始化芯片??

void ChipParametersConfiguration(void)

{

  uint8_t tmp;

  uint8_t memsize[2][8] = {{2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2}};

  //WIZCHIP SOCKET?存?初始化

  if(ctlwizchip(CW_INIT_WIZCHIP,(void*)memsize) == -1){

    //printf("WIZCHIP Initialized fail.rn");

  while(1);

  }

 

  //PHY物理??接????

  do{

    if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1){

      //printf("Unknown PHY Link stauts.rn");

    }

  }while(tmp == PHY_LINK_OFF);

}
```

![?制代?](https://common.cnblogs.com/images/copycode.gif)

以上????物理?的配置。 初始化WIZCHIP中的????信息：

![?制代?](https://common.cnblogs.com/images/copycode.gif)

```
//初始化WIZCHIP中的????信息

void NetworkParameterConfiguration(void)

{

  uint8_t tmpstr[6];

  ctlnetwork(CN_SET_NETINFO, (void*)&gWIZNETINFO);

  ctlnetwork(CN_GET_NETINFO, (void*)&gWIZNETINFO);

 

  ctlwizchip(CW_GET_ID,(void*)tmpstr);

}
```

![?制代?](https://common.cnblogs.com/images/copycode.gif)

其中gWIZNETINFO是一?wiz_NetInfo?型的????量，????在wizchip_conf.h中定?，用于?置mac地址、IP地址等????，具?如下：

![?制代?](https://common.cnblogs.com/images/copycode.gif)

```
typedef struct wiz_NetInfo_t

{

   uint8_t mac[6];  ///< Source Mac Address

   uint8_t ip[4];   ///< Source IP Address

   uint8_t sn[4];   ///< Subnet Mask

   uint8_t gw[4];   ///< Gateway IP Address

   uint8_t dns[4];  ///< DNS server IP Address

   dhcp_mode dhcp;  ///< 1 - Static, 2 - DHCP

}wiz_NetInfo;
```

![?制代?](https://common.cnblogs.com/images/copycode.gif)

至此??部分的初始化就已完成。 2.3、具?通??程的?? ??前面的配置??已?可以ping通了，下面可以??具?的?用。?于我???目就是可是??Modbus TCP的??了。 ??TCP Server，?部分有?多?料，直接附代?：

![?制代?](https://common.cnblogs.com/images/copycode.gif)

```
//TCP服?器?据通?

int32_t TCPServer(uint8_t sn, uint16_t port)

{

  int32_t ret;

  uint8_t socketStatus=getSn_SR(sn);

 

  switch(socketStatus)

  {

    case SOCK_ESTABLISHED :

      {

        if(getSn_IR(sn) & Sn_IR_CON)

        {

          setSn_IR(sn,Sn_IR_CON);

        }

        uint16_t size=0;

        if((size = getSn_RX_RSR(sn)) > 0)

        {

          if(size > DATA_BUFFER_SIZE)

          {

            size = DATA_BUFFER_SIZE;

          }

          uint8_t rxBuffer[DATA_BUFFER_SIZE];

          ret = recv(sn,rxBuffer,size);

          if(ret <= 0)

          {

            return ret;

          }

          //添加?据解析及??的函?

          uint8_t txBuffer[DATA_BUFFER_SIZE];

          uint16_t length=ReceivedDataParsing(rxBuffer,txBuffer);

         

          uint16_t sentsize=0;

          while(length != sentsize)

          {

            ret = send(sn,txBuffer+sentsize,length-sentsize);

            if(ret < 0)

            {

              close(sn);

              return ret;

            }

            sentsize += ret; // 不用管SOCKERR_BUSY, 因??是零.

          }

        }

        break;

      }

    case SOCK_CLOSE_WAIT :

      if((ret=disconnect(sn)) != SOCK_OK)

      {

        return ret;

      }

      break;

    case SOCK_INIT :

      if( (ret = listen(sn)) != SOCK_OK)

      {

        return ret;

      }

      break;

    case SOCK_CLOSED:

      if((ret=socket(sn,Sn_MR_TCP,port,0x00)) != sn)

      {

        return ret;

      }

      break;

    default:

      break;

  }

  return 1;

}
```

![?制代?](https://common.cnblogs.com/images/copycode.gif)

其中ReceivedDataParsing(rxBuffer,txBuffer)??具?的Modbus??，根据具?的需求而定。 通?Modscan?接??，?果正?。 ![](https://images2015.cnblogs.com/blog/564295/201607/564295-20160729114902825-295143239.png)

---

Source: https://maker.wiznet.io/chen/projects/STM32W5500Modbus-TCP/
