打印
[应用相关]

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

[复制链接]
3133|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kzlzqi|  楼主 | 2024-3-31 23:42 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
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校验码字节。

SPI简介

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

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


使用特权

评论回复
沙发
kzlzqi|  楼主 | 2024-3-31 23:44 | 只看该作者
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])来选取。

使用特权

评论回复
板凳
kzlzqi|  楼主 | 2024-3-31 23:44 | 只看该作者
通用寄存器区配置了 W5500 的基本信息。

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

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

使用特权

评论回复
地板
kzlzqi|  楼主 | 2024-3-31 23:44 | 只看该作者
SUBR (子网掩码寄存器) [R/W] [0x0005 – 0x0008] [0x00]

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

使用特权

评论回复
5
kzlzqi|  楼主 | 2024-3-31 23:44 | 只看该作者
SHAR (源 MAC 地址寄存器) [R/W] [0x0009 – 0x000E] [0x00]

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

使用特权

评论回复
6
kzlzqi|  楼主 | 2024-3-31 23:45 | 只看该作者
SIPR (客户端地址寄存器) [R/W] [0x000F – 0x0012] [0x00]

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

使用特权

评论回复
7
kzlzqi|  楼主 | 2024-3-31 23:45 | 只看该作者
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, 配置应如下:

使用特权

评论回复
8
kzlzqi|  楼主 | 2024-3-31 23:45 | 只看该作者
Sn_DPORT (Socket n 目标端口寄存器) [R/W] [0x0010-0x0011] [0x00]

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

使用特权

评论回复
9
kzlzqi|  楼主 | 2024-3-31 23:45 | 只看该作者
CubeMx工程创建
        1. 在主界面选择File-->New Project   或者直接点击ACCEE TO MCU SELECTOR。

使用特权

评论回复
10
kzlzqi|  楼主 | 2024-3-31 23:46 | 只看该作者
出现芯片型号选择,搜索自己芯片的型号,双击型号,或者点击Start Project进入配置。在搜索栏的下面,提供的各  种查找方式,可以选择芯片内核,型号,等等,可以帮助你查找芯片。本文选取的芯片型号为:STM32F407IGTx。

使用特权

评论回复
11
kzlzqi|  楼主 | 2024-3-31 23:46 | 只看该作者
. 配置RCC,使用外部时钟源,可以不用直接去配置引脚状态,PH0和PH1引脚会自动配置时钟。

使用特权

评论回复
12
kzlzqi|  楼主 | 2024-3-31 23:46 | 只看该作者
配置调试引脚,同样可以不用直接去设置引脚,PA13和PA14引脚会自动配置为调试引脚。

使用特权

评论回复
13
kzlzqi|  楼主 | 2024-3-31 23:46 | 只看该作者
将LED对应的3个引脚(PI5,PI6,PI7)设置为GPIO_Output,参数设置参考下图,请配置完进行核对。

使用特权

评论回复
14
kzlzqi|  楼主 | 2024-3-31 23:46 | 只看该作者
配置SPI引脚模式,PA7--SPI1_MOSI,PB3--SPI1_SCK,PB4--SPI1_MISO,PA15--GPIO_Output(单独设置)。

使用特权

评论回复
15
kzlzqi|  楼主 | 2024-3-31 23:47 | 只看该作者

使用特权

评论回复
16
kzlzqi|  楼主 | 2024-3-31 23:47 | 只看该作者
.时钟源设置,选择外部高速时钟源,配置为最大主频。

使用特权

评论回复
17
kzlzqi|  楼主 | 2024-3-31 23:47 | 只看该作者
工程文件的设置, 这里就是工程的各种配置。因为涉及到文件读写,堆栈调大一些。

使用特权

评论回复
18
kzlzqi|  楼主 | 2024-3-31 23:47 | 只看该作者

使用特权

评论回复
19
kzlzqi|  楼主 | 2024-3-31 23:47 | 只看该作者
关键代码实现//主函数,多主站监听关键实现
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 */
}

使用特权

评论回复
20
kzlzqi|  楼主 | 2024-3-31 23:48 | 只看该作者
//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

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

105

主题

858

帖子

2

粉丝