基于STM32的Modbus TCP多主站数据监测

Modbus TCP多主站数据监测要实现的功能为:两个及以上的TCP客户端同时访问STM32服务器的传感器数据。

文章目录

  • 一、实验原理
  • 二、CubeMx工程创建
  • 三、关键代码实现
  • 四、完整工程代码链接

一、原理介绍

1. Modbus简介 

      Modbus是一种串行通讯协议,已广泛应用与当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其他设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。其通讯遵循以下的过程:

  • 主设备向从设备发送请求;
  • 从设备分析并处理主设备的请求,然后向主设备发送结果;
  • 如果出现任何差错,从设备将返回一个异常功能码。

       Modbus通信协议具有多个变种,其具有支持串口(主要是RS-485总线),以太网多个版本。其中Modbus RTU与Modbus ASCII均为支持RS-485总线的通信协议,其中Modbus RTU由于其采用二进制表现形式以及紧凑数据结构。而Modbus ASCII由于采用ASCII码传输,并利用特殊字符作为其字节的开始与结束标识。而Modbus TCP协议则是在RTU协议上加一个MBAP报文头,由于TCP是基于可靠连接的服务,不再需要CRC校验,简单的说就是:Modbus TCP协议就是Modbus RTU协议在前面加上五个0以及一个6,然后去掉两个CRC校验码字节。

       Modbus TCP协议的相关介绍可参考博客:

       带你玩转modbusTCP通信_modbustcp协议数据格式-优快云博客

 2. SPI简介

       SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供空间,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议。SPI的通信原理很简单,它以主动方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,它们是SDI(数据传输)、SDO(数据输出)、SCLK(时钟)、CS(片选)。

  • MISO:主设备数据输入,从设备数据输出。
  • MOSI:主设备数据输出,从设备数据输入。
  • SCLK:时钟信号,由主设备产生。
  • CS:从设备片选信号,由主设备控制。

       SPI通信的相关介绍可参考博客: 

       一文搞懂SPI通信协议_spi协议-优快云博客

 3. STM32F407IGT6 W5500以太网驱动简介

      iCore3开发板带有W5500嵌入式以太网控制器,支持实现MODBUS TCP功能。W5500是一款全硬件TCP/IP嵌入式以太网控制器,为嵌入式系统提供了更加简易的互联网连接方案。W5500集成了TCP/IP协议栈,10/100M以太网数据链路层(MAC)及物理层(PHY),使得用户使用单芯片就能够在他们的应用中拓展网络连接。久经市场考验的WIZnet全硬件TCP/IP协议栈支持TCP,UDP,IPv4,ICMP,ARP,IGMP 以及PPPoE协议。W5500内嵌32K字节片上缓存以供以太网包处理。如果你使用W5500,你只需要一些简单的Socket编程就能实现以太网应用。这将会比其他嵌入式以太网方案更加快捷、简便。用户可以同时使用8个硬件Socket独立通讯。W5500提供了SPI(外设串行接口)从而能够更加容易与外设MCU整合。而且,W5500使用了新的高效SPI协议支持80MHz速率,从而能够更好的实现高速网络通讯。Mobus是开放协议,IANA给协议赋予TCP端口502,iCore3的IP地址为192.168.0.1,PC1的IP地址为192.168.0.2,PC2的IP地址为192.168.0.3,在建立完客户端与服务器之间的TCP连接后,Modbus即可通信。W5500工作原理图如下图所示: 

       W5500 有 1 个通用寄存器, 8 个 Socket 寄存器区,以及对应每个 Socket 的收发缓存区。每个区域均通过 SPI 数据帧的区域选择位(BSB[4:0])来选取。

(1)通用寄存器区配置了 W5500 的基本信息。

     1)GAR (网关 IP 地址寄存器) [R/W] [0x0001 0x0004] [0x00]

      该寄存器用来设置默认网关地址,例如: “192.168.0.1

2)SUBR (子网掩码寄存器) [R/W] [0x0005 0x0008] [0x00]

      该寄存器用来设置子网掩码地址,例如“255.255.255.0”。

 3)SHAR ( MAC 地址寄存器) [R/W] [0x0009 0x000E] [0x00]

 该寄存器用来设置源 MAC 地址。例如: “00.08.DC.01.02.03”。

  4)SIPR (客户端地址寄存器) [R/W] [0x000F 0x0012] [0x00]

   该寄存器用来设置服务器 IP 地址。例如: “192.168.0.2”。

(2)Socket 端口寄存器

   1)Sn_DIPR (Socket 目标 IP 地址寄存器) [R/W] [0x000C-0x000F] [0x00000000]

      Sn_DIPR配置或指示的为 Socket n 的客户端 IP 地址,在 TCP/UDP 模式下生效。在 TCP 客户端模式下,在 CONNECT 配置命令前,该寄存器设置新增粉丝了 TCP 服务器的 IP 地址。例如: Socket 0 的目标 IP 地址= 192.168.0.11, 配置应如下:

      2)Sn_DPORT (Socket n 目标端口寄存器) [R/W] [0x0010-0x0011] [0x00]

Sn_DPORT 配置或指示了 Socket n 的目标主机端口号,在 TCP/UDP 模式下生效。在 TCP 客户端模式下,在 CONNET 配置命令前,该寄存器配置了 TCP Server监听的端口号。例如: Socket 0 的目标端口号 = 5000,配置应如下:

二、CubeMx工程创建


        1. 在主界面选择File-->New Project   或者直接点击ACCEE TO MCU SELECTOR。

        2. 出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置。在搜索栏的下面,提供的各  种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本文选取的芯片型号为:STM32F407IGTx。

        3. 配置RCC,使用外部时钟源,可以不用直接去配置引脚状态,PH0和PH1引脚会自动配置时钟。

        4. 配置调试引脚,同样可以不用直接去设置引脚,PA13和PA14引脚会自动配置为调试引脚。

        5. 将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output,参数设置参考下图,请配置完进行核对。

     6. 配置SPI引脚模式,PA7--SPI1_MOSI,PB3--SPI1_SCK,PB4--SPI1_MISO,PA15--GPIO_Output(单独设置)。

          7.时钟源设置,选择外部高速时钟源,配置为最大主频。

          8. 工程文件的设置, 这里就是工程的各种配置。因为涉及到文件读写,堆栈调大一些。

三、关键代码实现

//主函数,多主站监听关键实现
int main(void)
{
  /* USER CODE BEGIN 1 */
	int receive_length;
	int i;
	short int data;
  /* USER CODE END 1 */
  
  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_ADC3_Init();
  MX_SPI1_Init();
  MX_UART4_Init();
  /* USER CODE BEGIN 2 */
	LED_GREEN_ON;
	
	adc1.initialize();
	spi1.initialize();
	w5500.initialize();
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

    /* USER CODE BEGIN 3 */
		for(i = 0;i < 5;i++){
			adc1.read(i);                        //读ADC的值
		}
		/*将数据存放在寄存器中*/
		data = adc1.value[0] * 1000 * 6;
		hold_reg[0] = data >> 8;
		hold_reg[1] = data & 0xff;

		data = adc1.value[1] * 1000 / 2;
		hold_reg[2] = data >> 8;
		hold_reg[3] = data & 0xff;
		
		data = adc1.value[2] * 1000;
		hold_reg[4] = data >> 8;
		hold_reg[5] = data & 0xff;

		data = adc1.value[3] * 1000 * 2;
		hold_reg[6] = data >> 8;
		hold_reg[7] = data & 0xff;

		data = adc1.value[4] * 1000 * 2;
		hold_reg[8] = data >> 8;
		hold_reg[9] = data & 0xff;
		
		//2024/1/9 Add
	LED_GREEN_OFF;
	LED_RED_ON;

		switch(getSn_SR(0))                   //获取socket0的状态
		{
			 case SOCK_INIT:                    //socket初始化完成
				 listen(0);                       //监等待连接
				 break;
			 case SOCK_ESTABLISHED:             //socket连接建立
				 if(getSn_IR(0) & Sn_IR_CON)
				 {
					 setSn_IR(0, Sn_IR_CON);        //Sn_IR的第0位置1
					}
				 receive_length=getSn_RX_RSR(0);  //获取已接收数据大小
				 if(receive_length>0)
				 {
					 recv(0,buffer,12);             //接收数据
					 modbus_tcp.process();          //modbus数据处理
					 LED_RED_OFF;
					}
				 break;
			 case SOCK_CLOSE_WAIT:              //socket等待关闭状态
				 disconnect(0);
				 break;
			 case SOCK_CLOSED:                  //socket关闭
				 socket(0,Sn_MR_TCP,30000,Sn_MR_ND);//打开socket0的一个端口
				 break;
		}		
		
		switch(getSn_SR(1))                   //获取socket1的状态
		{
			 case SOCK_INIT:                    //socket初始化完成
				 listen(1);                       //监听等待连接
				 break;
			 case SOCK_ESTABLISHED:             //socket连接建立
				 if(getSn_IR(1) & Sn_IR_CON)
				 {
					 setSn_IR(1, Sn_IR_CON);        //Sn_IR的第1位置1
					}
				 receive_length=getSn_RX_RSR(1);  //获取已接收数据大小
				 if(receive_length>0)
				 {
					 recv(1,buffer,12);             //接收数据
					 modbus_tcp.process();          //modbus数据处理
					 LED_RED_OFF;
					}
				 break;
			 case SOCK_CLOSE_WAIT:              //socket等待关闭状态
				 disconnect(1);
				 break;
			 case SOCK_CLOSED:                  //socket关闭
				 socket(1,Sn_MR_TCP,60000,Sn_MR_ND);//打开socket1的一个端口
				 break;
		}			
  }
  /* USER CODE END 3 */
}
//socket 实现
/*
*
@file    socket.c
@brief   setting chip register for socket
      last update : 2013. Nov
*
*/
#include "stdio.h"
#include "w5500.h"
#include "socket.h"

static uint16 local_port;
extern uint16 sent_ptr;

/**
@brief   This Socket function initialize the channel in perticular mode, and set the port and wait for W5200 done it.
@return  1 for sucess else 0.
*/
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);
      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));
      }
      IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_OPEN); // run sockinit Sn_CR

      /* wait to process the command... */
      while( IINCHIP_READ(Sn_CR(s)));			
      /* ------- */
      ret = 1;
//			if( (IINCHIP_READ(Sn_SR(s)) & 0xff ) != SOCK_INIT){
//			IINCHIP_WRITE(Sn_CR(s), Sn_CR_CLOSE);
//			}

//			IINCHIP_WRITE(Sn_CR(s) , Sn_CR_LISTEN);
//	
//			while(IINCHIP_READ(Sn_CR(s)) != 0);
//	
//			if( (IINCHIP_READ(Sn_SR(s)) &0XFF )!= SOCK_LISTEN){		
//			IINCHIP_WRITE(Sn_CR(s), Sn_CR_CLOSE);			
//			}			
   }
   else
   {
      ret = 0;
   }
   return ret;
}


/**
@brief   This function close the socket and parameter is "s" which represent the socket number
*/
void close(SOCKET s)
{

   IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_CLOSE);

   /* wait to process the command... */
   while( IINCHIP_READ(Sn_CR(s)) );	 
   /* ------- */
        /* all clear */
   IINCHIP_WRITE( Sn_IR(s) , 0xFF);
}


/**
@brief   This function established  the connection for the channel in passive (server) mode. This function waits for the request from the peer.
@return  1 for success else 0.
*/
uint8 listen(SOCKET s)
{
   uint8 ret;
   if (IINCHIP_READ( Sn_SR(s) ) == SOCK_INIT)
   {
      IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_LISTEN);
      /* wait to process the command... */
      while( IINCHIP_READ(Sn_CR(s) ) )
         ;
      /* ------- */
      ret = 1;
   }
   else
   {
      ret = 0;
   }
   return ret;
}


/**
@brief   This function established  the connection for the channel in Active (client) mode.
      This function waits for the untill the connection is established.

@return  1 for success else 0.
*/
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;
        // set destination 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));
        IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_CONNECT);
        /* wait for completion */
        while ( IINCHIP_READ(Sn_CR(s) ) ) ;
				
        while ( IINCHIP_READ(Sn_SR(s)) != SOCK_SYNSENT )
        {			
            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;
}


/**
@brief   This function used for disconnect the socket and parameter is "s" which represent the socket number
@return  1 for success else 0.
*/
void disconnect(SOCKET s)
{
   IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_DISCON);

   /* wait to process the command... */
   while( IINCHIP_READ(Sn_CR(s) ) )
      ;
   /* ------- */
}


/**
@brief   This function used to send the data in TCP mode
@return  1 for success else 0.
*/
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); // check size not to exceed MAX size.
  else ret = len;

  // if freebuf is available, start.
  do
  {
    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);

  /* wait to process the command... */
  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) )
    {
//      uart4.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;
}



/**
@brief   This function is an application I/F function which is used to receive the data in TCP mode.
      It continues to wait for data as much as the application wants to receive.

@return  received data size for success else -1.
*/
uint16 recv(SOCKET s, uint8 * buf, uint16 len)
{
   uint16 ret=0;
   if ( len > 0 )
   {
      recv_data_processing(s, buf, len);
      IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_RECV);
      /* wait to process the command... */
      while( IINCHIP_READ(Sn_CR(s) ));
      /* ------- */
      ret = len;
   }
   return ret;
}


/**
@brief   This function is an application I/F function which is used to send the data for other then TCP mode.
      Unlike TCP transmission, The peer's destination address and the port is needed.

@return  This function return send data size for success else -1.
*/
uint16 sendto(SOCKET s, const uint8 * buf, uint16 len, uint8 * addr, uint16 port)
{
   uint16 ret=0;

   if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
   else ret = len;

   if( ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || ((port == 0x00)) )//||(ret == 0) )
   {
      /* added return value */
      ret = 0;
   }
   else
   {
      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));
      // copy data
      send_data_processing(s, (uint8 *)buf, ret);
      IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_SEND);
      /* wait to process the command... */
      while( IINCHIP_READ( Sn_CR(s) ) )
         ;
      /* ------- */

      while( (IINCHIP_READ( Sn_IR(s) ) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
      {
         if (IINCHIP_READ( Sn_IR(s) ) & Sn_IR_TIMEOUT)
         {
            /* clear interrupt */
            IINCHIP_WRITE( Sn_IR(s) , (Sn_IR_SEND_OK | Sn_IR_TIMEOUT)); /* clear SEND_OK & TIMEOUT */
            return 0;
         }
      }
      IINCHIP_WRITE( Sn_IR(s) , Sn_IR_SEND_OK);
   }
   return ret;
}


/**
@brief   This function is an application I/F function which is used to receive the data in other then
   TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well.

@return  This function return received data size for success else -1.
*/
uint16 recvfrom(SOCKET s, uint8 * buf, uint16 len, uint8 * addr, uint16 *port)
{
   uint8 head[8];
   uint16 data_len=0;
   uint16 ptr=0;
   uint32 addrbsb =0;
   if ( len > 0 )
   {
      ptr     = IINCHIP_READ(Sn_RX_RD0(s) );
      ptr     = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_RX_RD1(s));
      addrbsb = (uint32)(ptr<<8) +  (s<<5) + 0x18;
      
      switch (IINCHIP_READ(Sn_MR(s) ) & 0x07)
      {
      case Sn_MR_UDP :
        wiz_read_buf(addrbsb, head, 0x08);        
        ptr += 8;
        // read peer's IP address, port number.
        addr[0]  = head[0];
        addr[1]  = head[1];
        addr[2]  = head[2];
        addr[3]  = head[3];
        *port    = head[4];
        *port    = (*port << 8) + head[5];
        data_len = head[6];
        data_len = (data_len << 8) + head[7];

        addrbsb = (uint32)(ptr<<8) +  (s<<5) + 0x18;
        wiz_read_buf(addrbsb, buf, data_len);                
        ptr += data_len;

        IINCHIP_WRITE( Sn_RX_RD0(s), (uint8)((ptr & 0xff00) >> 8));
        IINCHIP_WRITE( Sn_RX_RD1(s), (uint8)(ptr & 0x00ff));
        break;

      case Sn_MR_IPRAW :
        wiz_read_buf(addrbsb, head, 0x06);        
        ptr += 6;
        addr[0]  = head[0];
        addr[1]  = head[1];
        addr[2]  = head[2];
        addr[3]  = head[3];
        data_len = head[4];
        data_len = (data_len << 8) + head[5];

        addrbsb  = (uint32)(ptr<<8) +  (s<<5) + 0x18;
        wiz_read_buf(addrbsb, buf, data_len);        
        ptr += data_len;

        IINCHIP_WRITE( Sn_RX_RD0(s), (uint8)((ptr & 0xff00) >> 8));
        IINCHIP_WRITE( Sn_RX_RD1(s), (uint8)(ptr & 0x00ff));
        break;

      case Sn_MR_MACRAW :
        wiz_read_buf(addrbsb, head, 0x02);
        ptr+=2;
        data_len = head[0];
        data_len = (data_len<<8) + head[1] - 2;
        if(data_len > 1514)
        {
//           uart4.printf("data_len over 1514\r\n");
           while(1);
        }

        addrbsb  = (uint32)(ptr<<8) +  (s<<5) + 0x18;
        wiz_read_buf(addrbsb, buf, data_len);
        ptr += data_len;

        IINCHIP_WRITE( Sn_RX_RD0(s), (uint8)((ptr & 0xff00) >> 8));
        IINCHIP_WRITE( Sn_RX_RD1(s), (uint8)(ptr & 0x00ff));
        break;

      default :
            break;
      }
      IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_RECV);

      /* wait to process the command... */
      while( IINCHIP_READ( Sn_CR(s)) ) ;
      /* ------- */
   }
   return data_len;
}

#ifdef __MACRAW__
void macraw_open(void)
{
  uint8 sock_num;
  uint16 dummyPort = 0;
  uint8 mFlag = 0;
  sock_num = 0;


  close(sock_num); // Close the 0-th socket
  socket(sock_num, Sn_MR_MACRAW, dummyPort,mFlag);  // OPen the 0-th socket with MACRAW mode
}


uint16 macraw_send( const uint8 * buf, uint16 len )
{
   uint16 ret=0;
   uint8 sock_num;
   sock_num =0;


   if (len > getIINCHIP_TxMAX(sock_num)) ret = getIINCHIP_TxMAX(sock_num); // check size not to exceed MAX size.
   else ret = len;

   send_data_processing(sock_num, (uint8 *)buf, len);

   //W5500 SEND COMMAND
   IINCHIP_WRITE(Sn_CR(sock_num),Sn_CR_SEND);
   while( IINCHIP_READ(Sn_CR(sock_num)) );
   while ( (IINCHIP_READ(Sn_IR(sock_num)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK );
   IINCHIP_WRITE(Sn_IR(sock_num), Sn_IR_SEND_OK);

   return ret;
}

uint16 macraw_recv( uint8 * buf, uint16 len )
{
   uint8 sock_num;
   uint16 data_len=0;
   uint16 dummyPort = 0;
   uint16 ptr = 0;
   uint8 mFlag = 0;
   sock_num = 0;

   if ( len > 0 )
   {

      data_len = 0;

      ptr = IINCHIP_READ(Sn_RX_RD0(sock_num));
      ptr = (uint16)((ptr & 0x00ff) << 8) + IINCHIP_READ( Sn_RX_RD1(sock_num) );
      //-- read_data(s, (uint8 *)ptr, data, len); // read data
      data_len = IINCHIP_READ_RXBUF(0, ptr);
      ptr++;
      data_len = ((data_len<<8) + IINCHIP_READ_RXBUF(0, ptr)) - 2;
      ptr++;

      if(data_len > 1514)
      {
         uart4.printf("data_len over 1514\r\n");
         uart4.printf("\r\nptr: %X, data_len: %X", ptr, data_len);
         //while(1);
         /** recommand : close and open **/
         close(sock_num); // Close the 0-th socket
         socket(sock_num, Sn_MR_MACRAW, dummyPort,mFlag);  // OPen the 0-th socket with MACRAW mode
         return 0;
      }

      IINCHIP_READ_RXBUF_BURST(sock_num, ptr, data_len, (uint8*)(buf));
      ptr += data_len;

      IINCHIP_WRITE(Sn_RX_RD0(sock_num),(uint8)((ptr & 0xff00) >> 8));
      IINCHIP_WRITE(Sn_RX_RD1(sock_num),(uint8)(ptr & 0x00ff));
      IINCHIP_WRITE(Sn_CR(sock_num), Sn_CR_RECV);
      while( IINCHIP_READ(Sn_CR(sock_num)) ) ;
   }

   return data_len;
}

#endif

//w5500驱动  参考银杏科技
/*
 * FILE						: w5500.c
 * DESCRIPTION		: This file is iCore3 files.
 * Author					: ysloveivy
 * Copyright			:
 *
 * History
 * --------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * --------------------
 */
 
//--------------------------- Include ---------------------------//

#include "spi1.h"
#include "gpio.h"
#include "spi.h"
#include "w5500.h"
#include "main.h"
#include "socket.h"

//--------------------- Function Prototype ----------------------//
static void delay(int ms);
static int initialize(void);
static int setup(SOCKET s, unsigned char protocol, unsigned short int port, unsigned char flag);
//--------------------------- Variable --------------------------//
W5500_T w5500={
	.initialize=initialize,
	.setup=setup
};
static unsigned short int local_port;
unsigned char txsize[MAX_SOCK_NUM] = {2,2,2,2,2,2,2,2};
unsigned char rxsize[MAX_SOCK_NUM] = {2,2,2,2,2,2,2,2};
static unsigned char I_STATUS[MAX_SOCK_NUM];
static unsigned short int SSIZE[MAX_SOCK_NUM];                             /**< Max Tx buffer size by each channel */
static unsigned short int RSIZE[MAX_SOCK_NUM];                             /**< Max Rx buffer size by each channel */

//--------------------------- Function --------------------------//
/*
 * Name						: getISR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned char getISR(unsigned char s)
{
  return I_STATUS[s];
}
/*
 * Name						: putISR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void putISR(unsigned char s, unsigned char val)
{
   I_STATUS[s] = val;
}
/*
 * Name						: getIINCHIP_RxMAX
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned short int getIINCHIP_RxMAX(unsigned char s)
{
   return RSIZE[s];
}
/*
 * Name						: getIINCHIP_TxMAX
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned short int getIINCHIP_TxMAX(unsigned char s)
{
   return SSIZE[s];
}
/*
 * Name						: IINCHIP_CSoff
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void IINCHIP_CSoff(void)
{
	SPI1_CS_OFF;
}
/*
 * Name						: IINCHIP_CSon
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void IINCHIP_CSon(void)
{
	SPI1_CS_ON;
}
/*
 * Name						: IINCHIP_SpiSendData
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned char  IINCHIP_SpiSendData(unsigned char dat)
{
   return(spi1.send_data(dat));
}
/*
 * Name						: IINCHIP_WRITE
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void IINCHIP_WRITE( unsigned long int addrbsb,  unsigned char data)
{
   SPI1_CS_OFF;
   spi1.send_data( (addrbsb & 0x00FF0000)>>16);                                // Address byte 1
   spi1.send_data( (addrbsb & 0x0000FF00)>> 8);                                // Address byte 2
   spi1.send_data( (addrbsb & 0x000000F8) + 4);                                // Data write command and Write data length 1
   spi1.send_data(data);                                                       // Data write (write 1byte data)
	 SPI1_CS_ON;
}
/*
 * Name						: IINCHIP_READ
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned char IINCHIP_READ(unsigned long int addrbsb)
{
   unsigned char data = 0;

   SPI1_CS_OFF;
   spi1.send_data( (addrbsb & 0x00FF0000)>>16);                                // Address byte 1
   spi1.send_data( (addrbsb & 0x0000FF00)>> 8);                                // Address byte 2
   spi1.send_data( (addrbsb & 0x000000F8))    ;                                // Data read command and Read data length 1
   data = spi1.send_data(0x00);                                                // Data read (read 1byte data)
	 SPI1_CS_ON;

   return data;  
}
/*
 * Name						: wiz_write_buf
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned short int wiz_write_buf(unsigned long int addrbsb,unsigned char* buf,unsigned short int len)
{
	 unsigned short int idx = 0;
	 
   SPI1_CS_OFF;
   spi1.send_data( (addrbsb & 0x00FF0000)>>16);                                // Address byte 1
   spi1.send_data( (addrbsb & 0x0000FF00)>> 8);                                // Address byte 2
   spi1.send_data( (addrbsb & 0x000000F8) + 4);                                // Data write command and Write data length 1
   for(idx = 0; idx < len; idx++)                                              // Write data in loop
   {
     spi1.send_data(buf[idx]);
   }
	 SPI1_CS_ON;
   return len; 
}
/*
 * Name						: wiz_read_buf
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned short int wiz_read_buf(unsigned long int addrbsb, unsigned char* buf,unsigned short int len)
{
  unsigned short int idx = 0;

  SPI1_CS_OFF;
	spi1.send_data( (addrbsb & 0x00FF0000)>>16);                                 // Address byte 1
  spi1.send_data( (addrbsb & 0x0000FF00)>> 8);                                 // Address byte 2
  spi1.send_data( (addrbsb & 0x000000F8));                                     // Data write command and Write data length 1
  for(idx = 0; idx < len; idx++)                                               // Write data in loop
  {
    buf[idx] = spi1.send_data(0x00);
  }
	SPI1_CS_ON;
	
  return len;
}

/*
 * Name						: iinchip_init
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void iinchip_init(void)
{
  setMR( MR_RST );
}
/*
 * Name						: sysinit
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void sysinit( unsigned char * tx_size, unsigned char * rx_size  )
{
  short int i;
  short int ssum,rsum;
  ssum = 0;
  rsum = 0;

  for (i = 0 ; i < MAX_SOCK_NUM; i++)                      // Set the size, masking and base address of Tx & Rx memory by each channel
  {
		IINCHIP_WRITE( (Sn_TXMEM_SIZE(i)), tx_size[i]);
		IINCHIP_WRITE( (Sn_RXMEM_SIZE(i)), rx_size[i]);
          
    SSIZE[i] = (int16)(0);
    RSIZE[i] = (int16)(0);


    if (ssum <= 16384)
    {
         switch( tx_size[i] )
      {
      case 1:
        SSIZE[i] = (int16)(1024);
        break;
      case 2:
        SSIZE[i] = (int16)(2048);
        break;
      case 4:
        SSIZE[i] = (int16)(4096);
        break;
      case 8:
        SSIZE[i] = (int16)(8192);
        break;
      case 16:
        SSIZE[i] = (int16)(16384);
      break;
      default :
        RSIZE[i] = (int16)(2048);
        break;
      }
    }

   if (rsum <= 16384)
    {
         switch( rx_size[i] )
      {
      case 1:
        RSIZE[i] = (int16)(1024);
        break;
      case 2:
        RSIZE[i] = (int16)(2048);
        break;
      case 4:
        RSIZE[i] = (int16)(4096);
        break;
      case 8:
        RSIZE[i] = (int16)(8192);
        break;
      case 16:
        RSIZE[i] = (int16)(16384);
        break;
      default :
        RSIZE[i] = (int16)(2048);
        break;
      }
    }
    ssum += SSIZE[i];
    rsum += RSIZE[i];

  }
}

/*
 * Name						: setGAR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setGAR(unsigned char * addr)
{
    wiz_write_buf(GAR0, addr, 4);
}

/*
 * Name						: getGWIP
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void getGWIP(unsigned char * addr)
{
    wiz_read_buf(GAR0, addr, 4);
}

/*
 * Name						: setSUBR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setSUBR(unsigned char * addr)
{   
    wiz_write_buf(SUBR0, addr, 4);
}
/*
 * Name						: setSHAR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setSHAR(unsigned char * addr)
{
  wiz_write_buf(SHAR0, addr, 6);  
}

/*
 * Name						: setSIPR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setSIPR(unsigned char * addr)
{
    wiz_write_buf(SIPR0, addr, 4);  
}
/*
 * Name						: getGAR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void getGAR(unsigned char * addr)
{
    wiz_read_buf(GAR0, addr, 4);
}
/*
 * Name						: getSUBR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void getSUBR(unsigned char * addr)
{
    wiz_read_buf(SUBR0, addr, 4);
}
/*
 * Name						: getSHAR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void getSHAR(unsigned char * addr)
{
    wiz_read_buf(SHAR0, addr, 6);
}
/*
 * Name						: getSIPR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void getSIPR(unsigned char * addr)
{
    wiz_read_buf(SIPR0, addr, 4);
}
/*
 * Name						: setMR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setMR(unsigned char val)
{
  IINCHIP_WRITE(MR,val);
}
/*
 * Name						: getIR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned char getIR( void )
{
   return IINCHIP_READ(IR);
}
/*
 * Name						: setRTR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setRTR(unsigned short int timeout)
{
  IINCHIP_WRITE(RTR0,(unsigned char)((timeout & 0xff00) >> 8));
  IINCHIP_WRITE(RTR1,(unsigned char)(timeout & 0x00ff));
}
/*
 * Name						: setRCR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setRCR(unsigned char retry)
{
  IINCHIP_WRITE(WIZ_RCR,retry);
}
/*
 * Name						: clearIR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void clearIR(unsigned char mask)
{
  IINCHIP_WRITE(IR, ~mask | getIR() ); // must be setted 0x10.
}
/*
 * Name						: setSn_MSS
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setSn_MSS(SOCKET s, unsigned short int Sn_MSSR)
{
  IINCHIP_WRITE( Sn_MSSR0(s), (unsigned char)((Sn_MSSR & 0xff00) >> 8));
  IINCHIP_WRITE( Sn_MSSR1(s), (unsigned char)(Sn_MSSR & 0x00ff));
}
/*
 * Name						: setSn_TTL
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setSn_TTL(SOCKET s, unsigned char ttl)
{    
   IINCHIP_WRITE( Sn_TTL(s) , ttl);
}
/*
 * Name						: getSn_IR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned char getSn_IR(SOCKET s)
{
   return IINCHIP_READ(Sn_IR(s));
}
/*
 * Name						: getSn_SR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned char getSn_SR(SOCKET s)
{
   return IINCHIP_READ(Sn_SR(s));
}
/*
 * Name						: getSn_TX_FSR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned short int getSn_TX_FSR(SOCKET s)
{
  unsigned short int val=0,val1=0;
  do
  {
    val1 = IINCHIP_READ(Sn_TX_FSR0(s));
    val1 = (val1 << 8) + IINCHIP_READ(Sn_TX_FSR1(s));
      if (val1 != 0)
    {
        val = IINCHIP_READ(Sn_TX_FSR0(s));
        val = (val << 8) + IINCHIP_READ(Sn_TX_FSR1(s));
    }
  } while (val != val1);
   return val;
}
/*
 * Name						: getSn_RX_RSR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
unsigned short int getSn_RX_RSR(SOCKET s)
{
  unsigned short int val=0,val1=0;
  do
  {
    val1 = IINCHIP_READ(Sn_RX_RSR0(s));
    val1 = (val1 << 8) + IINCHIP_READ(Sn_RX_RSR1(s));
    if(val1 != 0)
    {
        val = IINCHIP_READ(Sn_RX_RSR0(s));
        val = (val << 8) + IINCHIP_READ(Sn_RX_RSR1(s));
    }
  } while (val != val1);
   return val;
}
/*
 * Name						: send_data_processing
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void send_data_processing(SOCKET s, unsigned char *data, unsigned short int len)
{
  unsigned short int ptr = 0;
  unsigned long int addrbsb = 0;
  ptr = IINCHIP_READ( Sn_TX_WR0(s) );
  ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR1(s));

  addrbsb = ((uint32)ptr<<8) + (s<<5) + 0x10;
  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));
}
/*
 * Name						: recv_data_processing
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void recv_data_processing(SOCKET s, unsigned char *data, unsigned short int len)
{
  unsigned short int ptr = 0;
  unsigned long int addrbsb = 0;
  
  ptr = IINCHIP_READ( Sn_RX_RD0(s) );
  ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ( Sn_RX_RD1(s) );

  addrbsb = ((uint32)ptr<<8) + (s<<5) + 0x18;
  wiz_read_buf(addrbsb, data, len);
  ptr += len;

  IINCHIP_WRITE( Sn_RX_RD0(s), (uint8)((ptr & 0xff00) >> 8));
  IINCHIP_WRITE( Sn_RX_RD1(s), (uint8)(ptr & 0x00ff));
}
/*
 * Name						: setSn_IR
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
void setSn_IR(unsigned char s, unsigned char val)
{
    IINCHIP_WRITE(Sn_IR(s), val);
}
/*
 * Name						: initialize
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
static int initialize(void)                                   //初始化设置
{
  unsigned char mac[6]={0x00,0x98,0xdc,0x42,0x61,0x11};
  unsigned char lip[4]={192,168,0,10};
  unsigned char sub[4]={255,255,255,0};
  unsigned char gw[4]={192,168,0,1};	
	
	delay(2000);
	while((IINCHIP_READ(PHYCFGR)& LINK)==0);                    //等待以太网连接完成
	
	setMR( MR_RST );
	delay(100);	
	
	setSHAR(mac);
	setSUBR(sub);
	setGAR(gw);
	setSIPR(lip);

  sysinit(txsize,rxsize);	
	
	setRTR(2000);                                              /*设置溢出时间值*/
	setRCR(8);                                                 /*设置最大重新发送次数*/
	
	IINCHIP_WRITE( IMR,IM_IR7 | IM_IR6); 
	IINCHIP_WRITE( SIMR, S0_IMR);  
	IINCHIP_WRITE( Sn_IMR(0), IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);

	return 0;
}
/*
 * Name						: setup
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
static int setup(SOCKET s, uint8 protocol, uint16 port, uint8 flag)
{

	if(s > 7)return -1;
	
	w5500.flag[s].send_ok=1;
 	
	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);
      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));
      }
      IINCHIP_WRITE( Sn_CR(s) ,Sn_CR_OPEN);                                 // run sockinit Sn_CR

      /* wait to process the command... */
      while( IINCHIP_READ(Sn_CR(s))!= 0);			
      /* ------- */
      ret = 1;
			if( (IINCHIP_READ(Sn_SR(s)) & 0xff ) != SOCK_INIT){
			IINCHIP_WRITE(Sn_CR(s), Sn_CR_CLOSE);
			}

			IINCHIP_WRITE(Sn_CR(s) , Sn_CR_LISTEN);
	
			while(IINCHIP_READ(Sn_CR(s)) != 0);
	
			if( (IINCHIP_READ(Sn_SR(s)) &0XFF )!= SOCK_LISTEN){		
			IINCHIP_WRITE(Sn_CR(s), Sn_CR_CLOSE);			
			}		
   }
   else
   {
      ret = 0;
   }
   return ret;
}
/*
 * Name						: delay
 * Description		: ---
 * Author					: ysloveivy.
 *
 * History
 * ----------------------
 * Rev						: 0.00
 * Date						: 12/20/2015
 *
 * create.
 * ----------------------
 */
static void delay(int ct) //ms
{
	int i, j;

	for (i = 0; i < ct; i++) 
	{
		for (j = 0; j < 10000; j++) ;
	}
}

//Modbus TCP代码
/*
 * FILE                 : modbus_tcp.c
 * DESCRIPTION          :--
 * Author               : ysloveivy.
 * Copyright            :
 *
 * History
 * --------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * --------------------
 */
//-----------------Include files-------------------------//

#include "modbus_tcp.h"
#include "main.h"
#include "socket.h"
#include "w5500.h"

#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
//---------------------- Define ---------------------//

//---------------- Function prototype ---------------//
static char process(void);

static int mb_rsq_pdu(unsigned char *receive_buffer_temp,int cnt);
static int mb_excep_rsq_pdu(unsigned char *receive_buffer_temp,int error_code);
static int function_1(unsigned char *receive_buffer_temp);
static int function_2(unsigned char *receive_buffer_temp);
static int function_3(unsigned char *receive_buffer_temp);
static int function_4(unsigned char *receive_buffer_temp);
static int function_5(unsigned char *receive_buffer_temp,int cnt);
static int function_6(unsigned char *receive_buffer_temp,int cnt);
static int broadcast(unsigned char *receive_buffer_temp);

//---------------- varitable -----------------------//
MODBUS_TCP_T modbus_tcp = {
  .process = process,
};

char discrete_input[32] = {0x55,0x55,0x55};         
char coil[32] = {0x55,0x55,0x55};                   
char input_reg[20] = {0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10};  
char hold_reg[512] = {0};
unsigned char receive_buffer_temp[100];

//---------------- Function ------------------------//
/*
 * Name                 : process
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
static char process(void)
{
  memcpy(receive_buffer_temp,buffer,12);
  memset(buffer,0,12);
	mb_rsq_pdu(receive_buffer_temp,12);
	
  return 0;
}
/*
 * Name                 : mb_rsq_pdu
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
 static int mb_rsq_pdu(unsigned char *receive_buffer_temp,int counter_temp)
 {
   if(receive_buffer_temp[0 + 6] == 0x01){
     switch(receive_buffer_temp[1 + 6]){
       case 1:
               function_1(receive_buffer_temp);
               break;
       case 2:
               function_2(receive_buffer_temp);
               break;
       case 3:
               function_3(receive_buffer_temp);
               break;
       case 4:
               function_4(receive_buffer_temp);
               break;
       case 5:
               function_5(receive_buffer_temp,counter_temp);
               break;
       case 6:
               function_6(receive_buffer_temp,counter_temp);
               break;
       default :
               mb_excep_rsq_pdu(receive_buffer_temp,1);
               break;
     }
  }else if(receive_buffer_temp[0 + 6] == 0){
      broadcast(receive_buffer_temp);
    }
  return 0;
 }
/*
 * Name                 : function_1
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
static int function_1(unsigned char *receive_buffer_temp)
{
  int i;
  unsigned short cnt;
  unsigned short coil_num;
  unsigned short start_address;
	int temp = 0;

  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];

  coil_num = receive_buffer_temp[4 + 6] << 8| receive_buffer_temp[5 + 6];
  
  if((start_address + coil_num) > 255){
    mb_excep_rsq_pdu(receive_buffer_temp,2);
    return 1;
  }

  receive_buffer_temp[2 + 6] = ((coil_num % 8 )? (coil_num / 8 + 1) : (coil_num / 8));
  cnt = receive_buffer_temp[2 + 6] + 5 - 2;
  if(coil_num % 8){
    if(coil_num < 8){
      for(i = 0;i < coil_num;i ++)temp |= 1 << i;
      receive_buffer_temp[3 + 6] = ((coil[start_address / 8]) >> (start_address % 8) | (coil[start_address / 8 + 1]) << (8 - (start_address % 8))) & temp;
    }else {
      for(i = 0;i < receive_buffer_temp[2 + 6] - 1;i++)receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8]) >> (start_address % 8) | (coil[i + start_address / 8 + 1]) << (8 - (start_address % 8));
      receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8] << ((8 - (coil_num % 8 - start_address % 8) % 8)) & 0xff) >> (8 - (coil_num % 8));
    }
  }else {
      for(i = 0;i < receive_buffer_temp[2 + 6];i++)receive_buffer_temp[3 + i + 6] = (coil[i + start_address / 8]) >> (start_address % 8) | (coil[i + start_address / 8 + 1]) << (8 - (start_address % 8));
  }
	
	receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
	receive_buffer_temp[5] = (cnt & 0x00ff);
	cnt = cnt + 6;
  send(0,receive_buffer_temp,cnt);

  return 0;
}
/*
 * Name                 : function_2
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
static int function_2(unsigned char *receive_buffer_temp)
{
  int i;
  unsigned short cnt;
  unsigned short discrete_num;
  unsigned short start_address;
	int temp = 0;

  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];

  discrete_num = receive_buffer_temp[4 + 6] << 8| receive_buffer_temp[5 + 6];

  if((start_address + discrete_num) > 255){
    mb_excep_rsq_pdu(receive_buffer_temp,2);
    return 1;
  }

  receive_buffer_temp[2 + 6] = ((discrete_num % 8 )? (discrete_num / 8 + 1) : (discrete_num / 8));
  cnt = receive_buffer_temp[2 + 6] + 5 - 2;
  if(discrete_num % 8){
    if(discrete_num < 8){
      for(i = 0;i < discrete_num;i ++)temp |= 1 << i;
      receive_buffer_temp[3 + 6] = ((discrete_input[start_address / 8]) >> (start_address % 8) | (discrete_input[start_address / 8 + 1]) << (8 - (start_address % 8))) & temp;
    }else {
      for(i = 0;i < receive_buffer_temp[2 + 6] - 1;i++)receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8]) >> (start_address % 8) | (discrete_input[i + start_address / 8 + 1]) << (8 - (start_address % 8));
      receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8] << ((8 - (discrete_num % 8 - start_address % 8) % 8)) & 0xff) >> (8 - (discrete_num % 8));
    }
  }else {
      for(i = 0;i < receive_buffer_temp[2 + 6];i++)receive_buffer_temp[3 + i + 6] = (discrete_input[i + start_address / 8]) >> (start_address % 8) | (discrete_input[i + start_address / 8 + 1]) << (8 - (start_address % 8));
  }
	
	receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
	receive_buffer_temp[5] = (cnt & 0x00ff);
	cnt = cnt + 6;
  send(0,receive_buffer_temp,cnt);

  return 0;
}
/*
 * Name                 : function_3
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
static int function_3(unsigned char *receive_buffer_temp)
{  
  int i;
  int cnt;
  unsigned short int start_address;

  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];

  receive_buffer_temp[2 + 6] = receive_buffer_temp[5 + 6] * 2;
  
  if(receive_buffer_temp[2 + 6] > 48){ 
    mb_excep_rsq_pdu(receive_buffer_temp,2);
    return 1;
  }

  if((start_address * 2 + receive_buffer_temp[2]) > 512){
    mb_excep_rsq_pdu(receive_buffer_temp,2);
    return 1;
  }

  cnt = receive_buffer_temp[2 + 6] + 5 - 2;
  for(i = 0;i < receive_buffer_temp[2 + 6];i++)receive_buffer_temp[i + 3 + 6] = hold_reg[start_address * 2 + i];

	receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
	receive_buffer_temp[5] = (cnt & 0x00ff);
	
	cnt = cnt + 6;
  send(0,receive_buffer_temp,cnt);
  send(1,receive_buffer_temp,cnt);
  return 0;
}
/*
 * Name                 : function_4
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create. 
 * ----------------------
 */
static int function_4(unsigned char *receive_buffer_temp)
{
  int i;
  int cnt;
  unsigned short int start_address;

  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];

  receive_buffer_temp[2 + 6] = receive_buffer_temp[5 + 6] * 2;

  if((start_address * 2 + receive_buffer_temp[2 + 6]) > 20){
    mb_excep_rsq_pdu(receive_buffer_temp,2);
    return 1;
  }

  cnt = receive_buffer_temp[2] + 5 - 2;
  for(i = 0;i < receive_buffer_temp[2 + 6];i++)receive_buffer_temp[i + 3 + 6] = input_reg[start_address * 2 + i];

	receive_buffer_temp[4] = (cnt & 0xff00) >> 8;
	receive_buffer_temp[5] = (cnt & 0x00ff);
	cnt = cnt + 6;
  send(0,receive_buffer_temp,cnt);
  return 0;
}
/*
 * Name                 : function_5
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
static int function_5(unsigned char *receive_buffer_temp,int counter_temp)
{
  unsigned short start_address;

  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];

  if(start_address > 255){
    mb_excep_rsq_pdu(receive_buffer_temp,2);
    return 1;
  }

  if((receive_buffer_temp[4 + 6] == 0xff) && (receive_buffer_temp[5 + 6] == 0x00)){
     coil[(start_address / 8)] |= 1 << start_address % 8;
  }else if((receive_buffer_temp[4 + 6] == 0x00) && (receive_buffer_temp[5 + 6] == 0x00)){
     coil[(start_address / 8)] &= ~(1 << start_address % 8);
  }else {
     mb_excep_rsq_pdu(receive_buffer_temp,3);
  }

	receive_buffer_temp[4] = (6 & 0xff00) >> 8;
	receive_buffer_temp[5] = (6 & 0x00ff);
	
	send(0,receive_buffer_temp,counter_temp);
  return 0;
}
/*
 * Name                 : function_6
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
static int function_6(unsigned char *receive_buffer_temp,int counter_temp)
{
  unsigned short start_address;

  start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];

  if(start_address > 255){
    mb_excep_rsq_pdu(receive_buffer_temp,2);
    return 1;
  }

  hold_reg[start_address * 2] = receive_buffer_temp[4 + 6];
  hold_reg[start_address * 2 + 1] = receive_buffer_temp[5 + 6];

	receive_buffer_temp[4] = (6 & 0xff00) >> 8;
	receive_buffer_temp[5] = (6 & 0x00ff);
  send(0,receive_buffer_temp,counter_temp);
  return 0;
}
/*
 * Name                 : mb_excep_rsq_pdu
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
 static int mb_excep_rsq_pdu(unsigned char *receive_buffer_temp,int error_code)
 {
   receive_buffer_temp[1 + 6] |= 0x80; 
   switch(error_code) {
     case 1:
             receive_buffer_temp[2 + 6] = 1;
             break;
     case 2:
             receive_buffer_temp[2 + 6] = 2;
             break;
     case 3:
             receive_buffer_temp[2 + 6] = 3;
             break;
     case 4:
             receive_buffer_temp[2 + 6] = 4;
             break;
     default :
             break;
   }
   
		
	receive_buffer_temp[4] = (3 & 0xff00) >> 8;
	receive_buffer_temp[5] = (3 & 0x00ff);
	
	send(0,receive_buffer_temp,9);
	return 0;
 }
/*
 * Name                 : broadcast
 * Description          : ---
 * Author               : ysloveivy.
 *
 * History
 * ----------------------
 * Rev                  : 1.00
 * Date                 : 12/20/2015
 *
 * create.
 * ----------------------
 */
 static int broadcast(unsigned char *receive_buffer_temp)
 {
   int start_address;
   switch(receive_buffer_temp[1 + 6]){
     case 5: 
             start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
             if(start_address > 255){
                return 1;
             }
             if((receive_buffer_temp[4 + 6] == 0xff) && (receive_buffer_temp[5 + 6] == 0x00)){
                coil[(start_address / 8)] |= 1 << start_address % 8;
             }else if((receive_buffer_temp[4 + 6] == 0x00) && (receive_buffer_temp[5 + 6] == 0x00)){
                coil[(start_address / 8)] &= ~(1 << start_address % 8);
             }
             break;
    case 6:	
            start_address = (receive_buffer_temp[2 + 6] << 8) | receive_buffer_temp[3 + 6];
            if(start_address > 255){
               return 1;
            }
            hold_reg[start_address * 2] = receive_buffer_temp[4 + 6];
            hold_reg[start_address * 2 + 1] = receive_buffer_temp[5 + 6]; 
            break;
    } 
   return 0;
 }

四、完整工程代码链接

          https://download.youkuaiyun.com/download/hyp12347/88760880

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值