STM32F103驱动W5500网络程序
- 格式:docx
- 大小:24.76 KB
- 文档页数:30
W5500问题集锦(一)发布时间:2013-11-27 阅读次数:1445 字体大小: 【小】【中】【大】在”WIZnet杯”以太网技术竞赛中,有很多参赛者在使用中对W5500有各种各样的疑问,对于这款WIZnet新推出的以太网芯片,使用中大家是不是也一样存在以下问题呢?来看一看:1.W5500不支持自动极性变换,有点失望……答:其实,只要对方支持极性变换就可以实现,现在的设备不支持极性变换的很少的。
你要是碰到个别老设备连不上,再换交叉线也不迟。
基本上2000年以后的设备都没问题的啦~原帖来自:9MCU2.W5500+STM32F0无法通信问题描述1:我现在做毕设,老师推荐买了W5500这款芯片,与STM32F0进行通信。
但是根据收集到的资料,修改的例程找不到问题所在。
对于网络这部分,本人小白一个,附上程序,希望大家指导一下!谢谢!答1:先附上W5500的例程问题描述2:如果ping 不通,TCP连接不能建立是代码的问题吗?loopback的程序步骤是怎样的答2:W5500 若想Ping通的话需要保证以下2点:1)物理信道通信正常:初步判定Link 灯及状态灯指示正常。
2)配置了W5500的IP,网关,子网掩码,MAC地址这些特殊寄存器由于W5500内部硬件逻辑电路实现了ARP协议。
所以,一旦收到ping包请求的话,会自动回复。
以上的设置不过是为了保证基本信道及通讯能够建立的而已。
反向而言,如果Ping不通,也可以先从这两方面着手。
原帖来自:9MCU3.W5500没指明接收缓冲数据格式,和W5100一样?问题描述:习惯码字和调试分离,虽然待会调试就知道了,也不妨提出来沟通下。
答:注意SPI帧的不同。
W5100:W5500:原帖来自:9MCU4.关于w5500程序的几个问题问题描述:有几个关于w5500程序的问题想请教大家:void Reset_W5500(void){WIZ_RESET_0; //低电平Delay_us(50); //这个的时间如果设为500us,貌似指示灯就全暗了??WIZ_RESET_1;Delay_ms(200);}while(( (getPHYCFGR()) & PHYCFGR_LNK_ON) == PHYCFGR_LNK_OFF); //PHYCFGR_LNK_OFF是0×00,PHYCFGR_LNK_ON是0×01。
2019年 / 第10期 物联网技术可靠传输 Reliable Transmission350 引 言小型智能家居应用系统的网关数据流量较小,接入方式多样,对成本要求较高,功能上一般比较精简。
现今市面上的网关大多采用高端嵌入式处理器加操作系统设计,预置有丰富的应用软件,配置较高,导致成本高,不太适用于小型智能家居等应用场合[1]。
本文旨在利用高性价比STM32嵌入式处理器与基于硬件TCP/IP 协议的W5500以太网芯片等多种接入模块,实现成本低廉、接入方式多样的智能家居网关。
1 技术架构智能家居网关的核心功能是路由与控制,需要通过WiFi ,蓝牙,RJ 45,RS 485等接入方式与终端产品进行数据交互,实现网络配置、路由管理、数据转发、远程控制等功能[2]。
本文设计以小型智能家居应用系统为应用对象,以低成本、快速开发、多方式接入为主要需求点。
根据功能需求,规划设计的技术架构如图1所示。
图1 网关技术架构网关硬件以STM32F103CBT6处理器为核心,外扩W5500以太网模块、ESP8266 WiFi 模块、HC-05蓝牙模块等,以便接入具有多种通信方式的智能家居终端产品,并在网关完成协议转换与数据转发。
其中,以太网模块选用W5500以太网控制器实现相应功能。
W5500是WIZnet 公司开发的一款以太网控制器,它采用全硬件TCP/IP 协议栈架构,集成了10/100 M 以太网数据链路层(MAC )及物理层(PHY ),支持TCP ,UDP ,ICMP ,ARP ,IPv4,IGMP 及PPPoE 协议,能提供8个独立的硬件Socket 通信客户端,使得用户使用单芯片就能够在应用中实现以太网连接,缩短了开发周期,减少了成本[3]。
(1)网关软件基于轻量级嵌入式操作系统μC/OS-III 实现。
(2)底层包含W5500以太网驱动、HC-05蓝牙驱动、ESP8266 WiFi 驱动,以及其他I/O 外设驱动。
W5500问题集锦(一)发布时间:2013-11-27 阅读次数:1445 字体大小: 【小】【中】【大】在”WIZnet杯”以太网技术竞赛中,有很多参赛者在使用中对W5500有各种各样的疑问,对于这款WIZnet新推出的以太网芯片,使用中大家是不是也一样存在以下问题呢?来看一看:1.W5500不支持自动极性变换,有点失望……答:其实,只要对方支持极性变换就可以实现,现在的设备不支持极性变换的很少的。
你要是碰到个别老设备连不上,再换交叉线也不迟。
基本上2000年以后的设备都没问题的啦~原帖来自:9MCU2.W5500+STM32F0无法通信问题描述1:我现在做毕设,老师推荐买了W5500这款芯片,与STM32F0进行通信。
但是根据收集到的资料,修改的例程找不到问题所在。
对于网络这部分,本人小白一个,附上程序,希望大家指导一下!谢谢!答1:先附上W5500的例程问题描述2:如果ping 不通,TCP连接不能建立是代码的问题吗?loopback的程序步骤是怎样的答2:W5500 若想Ping通的话需要保证以下2点:1)物理信道通信正常:初步判定Link 灯及状态灯指示正常。
2)配置了W5500的IP,网关,子网掩码,MAC地址这些特殊寄存器由于W5500内部硬件逻辑电路实现了ARP协议。
所以,一旦收到ping包请求的话,会自动回复。
以上的设置不过是为了保证基本信道及通讯能够建立的而已。
反向而言,如果Ping不通,也可以先从这两方面着手。
原帖来自:9MCU3.W5500没指明接收缓冲数据格式,和W5100一样?问题描述:习惯码字和调试分离,虽然待会调试就知道了,也不妨提出来沟通下。
答:注意SPI帧的不同。
W5100:W5500:原帖来自:9MCU4.关于w5500程序的几个问题问题描述:有几个关于w5500程序的问题想请教大家:void Reset_W5500(void){WIZ_RESET_0; //低电平Delay_us(50); //这个的时间如果设为500us,貌似指示灯就全暗了??WIZ_RESET_1;Delay_ms(200);}while(( (getPHYCFGR()) & PHYCFGR_LNK_ON) == PHYCFGR_LNK_OFF); //PHYCFGR_LNK_OFF是0×00,PHYCFGR_LNK_ON是0×01。
W5500以太网芯片及模块使用
一、模块介绍
是以太网转spi接口的,模块上有3个led和一个复位按钮,灯的含义是:
LINKLED
网络连接指示灯(Link LED)
显示当前连接状态:
低电平:连接建立;
高电平:未连接;
DUPLED
全/半双工指示灯(Duplex LED)
显示当前连接的双工状态:
低电平:全双工状态;
高电平:半双工状态;
ACTLED
活动状态指示灯(Active LED)
显示数据收/发活动时,物理介质子层的载波侦听活动情
况:
低电平:有物理介质子层的载波侦听信号;
高电平:无物理介质子层的载波侦听信号;
但貌似配置成全双工100M的速度也没什么增加,哪里出问题了呢?我现在使用18M的spi,使用wiz官方loopback软件测试速度为5Mb/s左右,好慢啊(/ □ \)
二、模块驱动
注意:在官网上有人共享了github的库函数驱动,不过是C99标准的,这一段Keil的c编译器支持好像有问题,而且对于是库函数很
致命,使用寄存器则无所谓
比如:ctlsocket和ctlwizchip函数的参数会因C99和C89的强转void类型定义不同,使其失效。
eg:0x0000不会错,0x0010可能会篡改成0x4e3c。
实用标准文案AP模式AP的SSID : AT+WAP=11BG,LAUVAN(SSID),CHIAP的KEY: : AT+WAKEY=WPA2PSK,AES,22222222AP模式: AT+WMODE=APAP 作服务器时的端口号:AT+NETP=TCP,SERVER,6000,192.168.1.56AP 的IP及网关:AT+LANN=192.168.1.1,255.255.255.0透传模式:AT+ENTM串口模式:/********************************************************************************** *******************名称: 变量定义*********************************************************************************** ******************/volatile uint8 UART3_RxBuf[UART3_RXBUF_SIZE];volatile uint8 UART3_TxBuf[UART3_TXBUF_SIZE];volatile uint8 UART3RxFlag; //接收标志volatile uint16 UART3_RxHead; //接收缓冲区读指针volatile uint16 UART3_RxEnd; //接收缓冲区指针volatile uint8 UART3_RxFullFlag; //接收缓冲区满标志volatile uint8 UART3_RxEmptyFlag; //接收缓冲区空标志volatile uint8 UART3TxFlag; //发送标志volatile uint16 UART3_TxHead;volatile uint16 UART3_TxEnd;volatile uint8 UART3_TxEmptyFlag; //发送缓冲区空标志volatile uint8 UART3OverTime; //超时时间volatile uint8 UART3OverFlag; //超时标志volatile uint8 UART3RxCompTime; //串口接收完成时间volatile uint8 UART3RxCompJudg; //串口接收完成判断volatile uint8 UART3RxCompFlag; //串口接收完成标志volatile uint16 Uart3OverTime;//WIFI相关参数volatile uint8 WifiStatus=0;volatile uint8 IsWifiBusy;volatile uint32 Channel_Timer_Limit;//限时器精彩文档.实用标准文案//volatile uint16 Dog_IsWifiBusy = DOG_ISGPRSBUSY;volatile uint16 Dog_IsWifiBusy = 0;volatile uint8 WifiSendBuf[512];volatile uint8 WifiRecBuf[512];volatile uint8 SetWifiParmFlag=0;volatile uint8 SetWifiUartParmFlag=0;volatile uint8 Send2BTime=0;volatile uint8 WifiOnLinkFlag=0;volatile uint8 WifiSendStartTime=0;volatile uint8 WifiHeartbeatno=0; //Wifi发送心跳次数volatile uint8 WifiSendEnterNetFlag=0; //Wifi发送登录帧标志ivolatile uint8 WifiEtherNetFlag=0; ///********************************************************************************** ******************* Function name: STM_EVAL_USART3_Init** Descriptions: 串口3中断服务函数** input parameters: 无** Output parameters:: 无** Returned value: 无*********************************************************************************** *****************/void STM_EVAL_USART3_Init(void){NVIC_InitTypeDef NVIC_InitStructure;/* Enable and set USART3 Interrupt to the 0 priority */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //嵌套优先级分组为1NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}/********************************************************************************** *********************** 初始化客户端WifiPortIOSet************************************************************************************* ******************/void WifiIOInit(void){精彩文档.实用标准文案GPIO_InitTypeDef GPIO_InitStructure;//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Pin = Reload; //定义Reload输出脚20140731GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, Reload);RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Pin = ResetTn; //定义ResetTn输出脚20140731GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, ResetTn);RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Pin = PWR_SW; //定义PWR_SW输出脚20140731GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, PWR_SW);}/********************************************************************************** ******************* 名称: USART3_Wifi()* 功能:初始化串口3* 入口参数:* 出口参数:*********************************************************************************** *******************/void USART3_Wifi(void){GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;/* config USART2 clock *///RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3 | RCC_APB2Periph_GPIOB,精彩文档.实用标准文案ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);/* USART3 GPIO config *//* Configure USART3 Tx (PB.10) as alternate function push-pull */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure USART3 Rx (PB.11) as input floating */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB, &GPIO_InitStructure);/* USART3 mode config */USART_ART_BaudRate = 115200;USART_ART_WordLength = USART_WordLength_8b;USART_ART_StopBits = USART_StopBits_1;USART_ART_Parity = USART_Parity_No ;USART_ART_HardwareFlowControl =USART_HardwareFlowControl_None;USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART3, &USART_InitStructure);/*使能串口3的发送和接收中断*/USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);USART_Cmd(USART3, ENABLE);STM_EVAL_USART3_Init(); //中断初始化WifiIOInit(); //WIFI控制脚的初始化20140731}/********************************************************************************** ************************* Function name: USART3_IRQHandler** Descriptions: 串口3中断服务函数** input parameters: 无** Output parameters:: 无** Returned value: 无*********************************************************************************** **********************/void USART3_IRQHandler(void){if(USART_GetITStatus(USART3,USART_IT_RXNE) != RESET){精彩文档.实用标准文案UART3RxCompJudg = VALID_FLAG;UART3RxCompTime = 0;Uart3OverTime = 0;if( UART3_RxFullFlag == 0){UART3_RxBuf[UART3_RxEnd++] = USART_ReceiveData(USART3); /* 保存接收到的数据 */if(UART3_RxEnd >= UART3_RXBUF_SIZE)UART3_RxEnd = 0;if(UART3_RxEnd == UART3_RxHead)UART3_RxFullFlag = 1;UART3_RxEmptyFlag = 0;}}//USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);}/********************************************************************************** ************************* Function name: HandleRFSendData** Descriptions: 发送多个字节数据** input parameters: Buffer:发送数据存储位置** NByte:发送数据个数** Output parameters:: 无** Returned value: 无*********************************************************************************** **********************/void HandleWifiSendData(unsigned char *buffer,int bufferlen){while(bufferlen>=0){USART_SendData(USART3, *buffer++);//ResetWdog();while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);bufferlen--;}//USART_Cmd(USART3, ENABLE);}/********************************************************************************** *********** 名称: HandleRFUartTimer()* 功能:处理读UART1时间* 入口参数:精彩文档.实用标准文案* 出口参数:*********************************************************************************** **********/void HandleWifiUartTimer(void){if(UART3RxCompJudg == VALID_FLAG) //接收是否完成判断{if(++UART3RxCompTime >= UART3_COMP_TIME) //判断接收中断之间超时{UART3RxCompTime = 0;UART3RxCompJudg = 0;UART3RxCompFlag = VALID_FLAG;}//NoReDataTime =0;}elseUart3OverTime++;}/********************************************************************************** ************** 名称: Uart3ReadBytes()* 功能:读取串口2字符串* 入口参数:*pBuf:读取数据存储区* 出口参数:*********************************************************************************** **************/uint16 Uart3ReadBytes(uint8 *pBuf){uint16 nEnd = 0;uint16 Size = 0;if(UART3_RxEmptyFlag == 0) //串口0接收数据缓冲区不为空{nEnd = UART3_RxEnd; //中断可能改变此值UART3_RxFullFlag = 0;if(UART3_RxHead < nEnd) //end > head{Size = nEnd - UART3_RxHead;memcpy(pBuf,(uint8 *)&UART3_RxBuf[0] + UART3_RxHead, Size);UART3_RxHead = nEnd;}精彩文档.实用标准文案else //head > end{Size = UART3_RXBUF_SIZE + nEnd - UART3_RxHead;memcpy(pBuf,(uint8 *)&UART3_RxBuf[0] + UART3_RxHead,UART3_RXBUF_SIZE- UART3_RxHead);if(nEnd > 0)memcpy(pBuf + UART3_RXBUF_SIZE - UART3_RxHead,(uint8*)&UART3_RxBuf[0],nEnd);UART3_RxHead = nEnd;}if(UART3_RxHead == UART3_RxEnd)UART3_RxEmptyFlag = 1; //接收数据缓冲区空}elseSize = 0;memset((uint8*)&UART3_RxBuf[0],0x00,512);return Size;}/********************************************************************************** *************** 名称:GetWifiMode485Data()* 功能:读出接收的数据,取出完整的一帧,放到接收BUF,* 入口参数:无* 出口参数:返回长度和数据BUF。
实用标准文案AP模式AP的SSID : AT+WAP=11BG,LAUVAN(SSID),CHIAP的KEY: : AT+WAKEY=WPA2PSK,AES,22222222AP模式: AT+WMODE=APAP 作服务器时的端口号:AT+NETP=TCP,SERVER,6000,192.168.1.56AP 的IP及网关:AT+LANN=192.168.1.1,255.255.255.0透传模式:AT+ENTM串口模式:/********************************************************************************** *******************名称: 变量定义*********************************************************************************** ******************/volatile uint8 UART3_RxBuf[UART3_RXBUF_SIZE];volatile uint8 UART3_TxBuf[UART3_TXBUF_SIZE];volatile uint8 UART3RxFlag; //接收标志volatile uint16 UART3_RxHead; //接收缓冲区读指针volatile uint16 UART3_RxEnd; //接收缓冲区指针volatile uint8 UART3_RxFullFlag; //接收缓冲区满标志volatile uint8 UART3_RxEmptyFlag; //接收缓冲区空标志volatile uint8 UART3TxFlag; //发送标志volatile uint16 UART3_TxHead;volatile uint16 UART3_TxEnd;volatile uint8 UART3_TxEmptyFlag; //发送缓冲区空标志volatile uint8 UART3OverTime; //超时时间volatile uint8 UART3OverFlag; //超时标志volatile uint8 UART3RxCompTime; //串口接收完成时间volatile uint8 UART3RxCompJudg; //串口接收完成判断volatile uint8 UART3RxCompFlag; //串口接收完成标志volatile uint16 Uart3OverTime;//WIFI相关参数volatile uint8 WifiStatus=0;volatile uint8 IsWifiBusy;volatile uint32 Channel_Timer_Limit;//限时器精彩文档.实用标准文案//volatile uint16 Dog_IsWifiBusy = DOG_ISGPRSBUSY;volatile uint16 Dog_IsWifiBusy = 0;volatile uint8 WifiSendBuf[512];volatile uint8 WifiRecBuf[512];volatile uint8 SetWifiParmFlag=0;volatile uint8 SetWifiUartParmFlag=0;volatile uint8 Send2BTime=0;volatile uint8 WifiOnLinkFlag=0;volatile uint8 WifiSendStartTime=0;volatile uint8 WifiHeartbeatno=0; //Wifi发送心跳次数volatile uint8 WifiSendEnterNetFlag=0; //Wifi发送登录帧标志ivolatile uint8 WifiEtherNetFlag=0; ///********************************************************************************** ******************* Function name: STM_EVAL_USART3_Init** Descriptions: 串口3中断服务函数** input parameters: 无** Output parameters:: 无** Returned value: 无*********************************************************************************** *****************/void STM_EVAL_USART3_Init(void){NVIC_InitTypeDef NVIC_InitStructure;/* Enable and set USART3 Interrupt to the 0 priority */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //嵌套优先级分组为1NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}/********************************************************************************** *********************** 初始化客户端WifiPortIOSet************************************************************************************* ******************/void WifiIOInit(void){精彩文档.实用标准文案GPIO_InitTypeDef GPIO_InitStructure;//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Pin = Reload; //定义Reload输出脚20140731GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, Reload);RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Pin = ResetTn; //定义ResetTn输出脚20140731GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, ResetTn);RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Pin = PWR_SW; //定义PWR_SW输出脚20140731GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA, PWR_SW);}/********************************************************************************** ******************* 名称: USART3_Wifi()* 功能:初始化串口3* 入口参数:* 出口参数:*********************************************************************************** *******************/void USART3_Wifi(void){GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;/* config USART2 clock *///RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3 | RCC_APB2Periph_GPIOB,精彩文档.实用标准文案ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);/* USART3 GPIO config *//* Configure USART3 Tx (PB.10) as alternate function push-pull */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);/* Configure USART3 Rx (PB.11) as input floating */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOB, &GPIO_InitStructure);/* USART3 mode config */USART_ART_BaudRate = 115200;USART_ART_WordLength = USART_WordLength_8b;USART_ART_StopBits = USART_StopBits_1;USART_ART_Parity = USART_Parity_No ;USART_ART_HardwareFlowControl =USART_HardwareFlowControl_None;USART_ART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART3, &USART_InitStructure);/*使能串口3的发送和接收中断*/USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);USART_Cmd(USART3, ENABLE);STM_EVAL_USART3_Init(); //中断初始化WifiIOInit(); //WIFI控制脚的初始化20140731}/********************************************************************************** ************************* Function name: USART3_IRQHandler** Descriptions: 串口3中断服务函数** input parameters: 无** Output parameters:: 无** Returned value: 无*********************************************************************************** **********************/void USART3_IRQHandler(void){if(USART_GetITStatus(USART3,USART_IT_RXNE) != RESET){精彩文档.实用标准文案UART3RxCompJudg = VALID_FLAG;UART3RxCompTime = 0;Uart3OverTime = 0;if( UART3_RxFullFlag == 0){UART3_RxBuf[UART3_RxEnd++] = USART_ReceiveData(USART3); /* 保存接收到的数据 */if(UART3_RxEnd >= UART3_RXBUF_SIZE)UART3_RxEnd = 0;if(UART3_RxEnd == UART3_RxHead)UART3_RxFullFlag = 1;UART3_RxEmptyFlag = 0;}}//USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);}/********************************************************************************** ************************* Function name: HandleRFSendData** Descriptions: 发送多个字节数据** input parameters: Buffer:发送数据存储位置** NByte:发送数据个数** Output parameters:: 无** Returned value: 无*********************************************************************************** **********************/void HandleWifiSendData(unsigned char *buffer,int bufferlen){while(bufferlen>=0){USART_SendData(USART3, *buffer++);//ResetWdog();while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);bufferlen--;}//USART_Cmd(USART3, ENABLE);}/********************************************************************************** *********** 名称: HandleRFUartTimer()* 功能:处理读UART1时间* 入口参数:精彩文档.实用标准文案* 出口参数:*********************************************************************************** **********/void HandleWifiUartTimer(void){if(UART3RxCompJudg == VALID_FLAG) //接收是否完成判断{if(++UART3RxCompTime >= UART3_COMP_TIME) //判断接收中断之间超时{UART3RxCompTime = 0;UART3RxCompJudg = 0;UART3RxCompFlag = VALID_FLAG;}//NoReDataTime =0;}elseUart3OverTime++;}/********************************************************************************** ************** 名称: Uart3ReadBytes()* 功能:读取串口2字符串* 入口参数:*pBuf:读取数据存储区* 出口参数:*********************************************************************************** **************/uint16 Uart3ReadBytes(uint8 *pBuf){uint16 nEnd = 0;uint16 Size = 0;if(UART3_RxEmptyFlag == 0) //串口0接收数据缓冲区不为空{nEnd = UART3_RxEnd; //中断可能改变此值UART3_RxFullFlag = 0;if(UART3_RxHead < nEnd) //end > head{Size = nEnd - UART3_RxHead;memcpy(pBuf,(uint8 *)&UART3_RxBuf[0] + UART3_RxHead, Size);UART3_RxHead = nEnd;}精彩文档.实用标准文案else //head > end{Size = UART3_RXBUF_SIZE + nEnd - UART3_RxHead;memcpy(pBuf,(uint8 *)&UART3_RxBuf[0] + UART3_RxHead,UART3_RXBUF_SIZE- UART3_RxHead);if(nEnd > 0)memcpy(pBuf + UART3_RXBUF_SIZE - UART3_RxHead,(uint8*)&UART3_RxBuf[0],nEnd);UART3_RxHead = nEnd;}if(UART3_RxHead == UART3_RxEnd)UART3_RxEmptyFlag = 1; //接收数据缓冲区空}elseSize = 0;memset((uint8*)&UART3_RxBuf[0],0x00,512);return Size;}/********************************************************************************** *************** 名称:GetWifiMode485Data()* 功能:读出接收的数据,取出完整的一帧,放到接收BUF,* 入口参数:无* 出口参数:返回长度和数据BUF。
基于STM32与W5500的嵌入式以太网系统摘要随着计算机通信技术和网络技术的发展,在嵌入式系统中集成以太网口,来实现与其它计算机设备之间的高速数据传输就显得更加的重要了。
越来越多的计算机系统都迫切的需要和其它计算机系统进行联网,以达到共享数据,统一管理的目的。
因此除了通常的使用PC机的内部网卡接入以太网外,许多的嵌入式系统也需要直接联入以太网,与其它联网的设备实现数据共享的目的。
采用STM32微控制器和W5500芯片搭建的网络系统,结构简单、易于实现。
本文首先介绍了目前以太网技术的日前基本情况以及以太网技术在嵌入式系统中的应用现状。
再者提供了以太网的应用模型,介绍了各个层次的网络协议。
然后结合以太网接口芯片W5500的主要特点、芯片引脚定义、内部寄存器使用说明,提出了这种芯片与嵌入式处理器的硬件接口设计和底层收发程序的编程思路。
接着针对嵌入式系统所需要完成的以太网通信的基本要求,从软件设计的角度介绍了一些必须实现的基本网络协议如TCP、UDP等协议的祯格式和主要特点。
该嵌入式以太网系统是基于STM32芯片与W5500高速以太网控制芯片的,它充分发挥了STM32 芯片的Cortex-M3 内核低成本低功耗的特性,同时该设计直接使用W5500固化的TCP/IP协议站,对系统性能有了很大提升。
关键词:以太网;以太网接口;W5500芯片ABSTRACTWith the development of computer communication technology and network technology, at the mouth of the embedded system in integrated Ethernet to achieve high-speed data transmission and other computer equipment becomes more important. More and more computer systems are urgently needed and other computer systems networking, in order to achieve data sharing and unified management. So in addition tothe usual use of PC's internal network card access Ethernet, many embedded systems also need to directly connected to the Ethernet, and other network equipment to achieve the purpose of data sharing. The structure of the network system is simple and easy to implement with the STM32 microcontroller and W5500 chip..First of all, this paper introduces the current application situation of Ethernet technology recently basic situation and Ethernet technology in embedded system. Moreover, the application of Ethernet is provided, and the network protocols are introduced.. And then combined with the main characteristic of Ethernet interface chip w5500, chip pin definition, internal register instructions for use, and put forward the idea of programming of the chip with embedded processor interface hardware design and the driver to send and receive procedures. Then for embedded systems need the basic requirement of the Ethernet communication, from the point of view of software design introduces some must achieve the basic network protocols such as TCP, UDP protocol frames format and the main characteristics.The embedded Ethernet system is based on the STM32 chip and w5500 high-speed Ethernet control chip. It makes full use of the STM32 chip Cortex-M3 low-cost low-power characteristics, at the same time the design used directly w5500 curing of the TCP / IP protocol station, the system performance has been greatly improved.Keywords: Ethernet; Ethernet interface; W5500 chip第1章绪论1.1 以太网概述以太网(Ethernet)指的是由Xerox公司创建并由Xerox、Intel和DEC公司联合开发的基带局域网规范,是当今现有局域网采用的最通用的通信协议标准。
以太网TCP在W5500上的通讯性能测试author:ANGRY_KUA_MAXQQ :2518383357Time :2018-01-12本文为原创,转载请通知作者,文中代码,请勿用于商业用途!1.概述当前以太网在嵌入式系统中使用范围越来越广,而一个性能稳定,高效率的以太网传输方式能大幅度降低产品开发周期与售后成本。
本文以作者工作环境中使用过的以太网芯片W5500(硬件协议栈)与LWIP(软件协议栈)作为测试对象,这次只测试W5500性能测试,下次再测试LWIP。
2.测试环境本次使用STM32F107搭配W5500进行带宽测试,W5500使用SPI口通讯,时钟可以跑到80M,即理论可以速率为10MB;下次也使用STM32F107搭配83848跑LWIP做(使用相同的MCU做数据分析才有对比价值,提前透漏,LWIP的性能比W5500验证测试。
要强一点,但W5500价格偏低,占用资源也少一些)STM32F107与W5500的通讯,采用SPI的DMA方式;初始化W5500为四个端口,各个收发缓存为(8K,4K,2K,2K),缓存对收发速度有影响。
测试的端口收发缓存为3.TCP测试数据3.1.W5500上传数据函数switch(getSn_SR(NET_TYPE_TCP)){case SOCK_INIT:listen(NET_TYPE_TCP);break;case SOCK_ESTABLISHED:if(getSn_IR(NET_TYPE_TCP) & Sn_IR_CON){setSn_IR(NET_TYPE_TCP, Sn_IR_CON);}len=getSn_RX_RSR(NET_TYPE_TCP);if(len>0){len = (len > NET_BUF_RXSIZE)?NET_BUF_RXSIZE:len;len = recv(NET_TYPE_TCP,net_rxbuf,len);if(len > 0){while(1) //作死的发送{send(NET_TYPE_TCP,net_rxbuf,1460); //本函数为阻塞函数,发生成功后,本函数才会返回}}}break;case SOCK_FIN_WAIT:case SOCK_CLOSING:case SOCK_TIME_WAIT:case SOCK_CLOSE_WAIT:case SOCK_LAST_ACK:close(NET_TYPE_TCP);break;case SOCK_CLOSED:socket(NET_TYPE_TCP,Sn_MR_TCP,net_sys_info->debug_save_.port,Sn_MR_ND);break;default:break;}3.2.W5500上传速率网络传输速率我们使用IPOP工具与360自带的加速球查看,其中IPOP软件以bit为单位,其实际的速度与360监测的一致(6080/8=750KB),即W5500在SPI速率为18兆位/秒的速度下测试,测试出来的通讯速度可达到750K左右,作者使用STM32F407做测试,上传速率可以达到3.5MB以上,STM32F107的通讯速率截图如下:3.3.W5500下载数据函数While(1){switch(getSn_SR(NET_TYPE_TCP)){case SOCK_INIT:listen(NET_TYPE_TCP);break;case SOCK_ESTABLISHED:if(getSn_IR(NET_TYPE_TCP) & Sn_IR_CON){setSn_IR(NET_TYPE_TCP, Sn_IR_CON);}len=getSn_RX_RSR(NET_TYPE_TCP);if(len>0){len = (len > NET_BUF_RXSIZE)?NET_BUF_RXSIZE:len;len = recv(NET_TYPE_TCP,net_rxbuf,len);if(len > 0){memcpy(net_tempbuf,net_rxbuf,len);//收到的数据保存//}}break;case SOCK_FIN_WAIT:case SOCK_CLOSING:case SOCK_TIME_WAIT:case SOCK_CLOSE_WAIT:case SOCK_LAST_ACK:close(NET_TYPE_TCP);break;case SOCK_CLOSED:socket(NET_TYPE_TCP,Sn_MR_TCP,net_sys_info->debug_save_.port,Sn_MR_ND);break;default:break;}}3.4.W5500下载速率测试出来的通讯速度可达到600K左右,但实际波动比较大,受限制与MCU的性能。
#include "W5500.h"/***************----- 网络参数变量定义-----***************/unsigned char Gateway_IP[4];//网关IP地址unsigned char Sub_Mask[4]; //子网掩码unsigned char Phy_Addr[6]; //物理地址(MAC)unsigned char IP_Addr[4]; //本机IP地址unsigned char S0_Port[2]; //端口0的端口号(5000)unsigned char S0_DIP[4]; //端口0目的IP地址unsigned char S0_DPort[2]; //端口0目的端口号(6000)unsigned char UDP_DIPR[4]; //UDP(广播)模式,目的主机IP地址unsigned char UDP_DPORT[2]; //UDP(广播)模式,目的主机端口号/***************----- 端口的运行模式-----***************/unsigned char S0_Mode =3; //端口0的运行模式,0:TCP服务器模式,1:TCP客户端模式,2:UDP(广播)模式#define TCP_SERVER 0x00 //TCP服务器模式#define TCP_CLIENT 0x01 //TCP客户端模式#define UDP_MODE 0x02 //UDP(广播)模式/***************----- 端口的运行状态-----***************/unsigned char S0_State =0; //端口0状态记录,1:端口完成初始化,2端口完成连接(可以正常传输数据)#define S_INIT 0x01 //端口完成初始化#define S_CONN 0x02 //端口完成连接,可以正常传输数据/***************----- 端口收发数据的状态-----***************/unsigned char S0_Data; //端口0接收和发送数据的状态,1:端口接收到数据,2:端口发送数据完成#define S_RECEIVE 0x01 //端口接收到一个数据包#define S_TRANSMITOK 0x02 //端口发送一个数据包完成/***************----- 端口数据缓冲区-----***************/unsigned char Rx_Buffer[2048]; //端口接收数据缓冲区unsigned char Tx_Buffer[2048]; //端口发送数据缓冲区unsigned char W5500_Interrupt; //W5500中断标志(0:无中断,1:有中断)/*外部中断4服务程序*/void EXTI4_IRQHandler(void){if(W5500_INT==0){W5500_Interrupt=1;EXTI->PR=1<<4; //清除LINE4上的中断标志位}}void SPI1_Init(void){RCC->APB2ENR|=1<<2; //PORTA时钟使能RCC->APB2ENR|=1<<12; //SPI1时钟使能RCC->APB2ENR|=1<<0;GPIOA->CRL&=0XFFF0FFFF;GPIOA->CRL|=0X00030000;//PA4通用挽推输出,输出速度50MHzGPIOA->ODR|=1<<4; //PA4上拉,设置片选引脚//这里只针对SPI口初始化GPIOA->CRL&=0X000FFFFF;GPIOA->CRL|=0XBBB00000;//PA5.6.7复用功能挽推输出,输出速度50MHzGPIOA->ODR|=0X7<<5; //PA5.6.7上拉SPI1->CR1&=~(1<<10);//全双工模式SPI1->CR1=1<<9; //外部管理NSS引脚SPI1->CR1&=~(1<<11);//8bit数据格式SPI1->CR1&=~(1<<1); //CPOL=0时空闲模式下SCK为0 CPOL=0SPI1->CR1&=~(1<<0); //数据采样从第一个时间边沿开始,CPHA=0SPI1->CR1|=1<<8;SPI1->CR1|=1<<2; //SPI主机SPI1->CR1|=0<<3; //Fsck=Fcpu/2SPI1->CR1&=~(1<<7); //MSBfirst先发送高位SPI1->CRCPR = 0X07;SPI1->CR1|=1<<6; //SPI设备使能}/****************************************************************************** ** 函数名: W5500_GPIO_Configuration* 描述: W5500 GPIO初始化配置* 输入: 无* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void W5500_GPIO_Configuration(void){RCC->APB2ENR|=1<<4; //PORTC时钟使能GPIOC->CRL&=0XFF00FFFF;GPIOC->CRL|=0X00380000;GPIOC->ODR|=3<<4; //PC4上拉,PC5输出高SPI1_Init();Ex_NVIC_Config(GPIO_C,4,FTIR); //下降沿触发MY_NVIC_Init(2,0,EXTI4_IRQChannel,2); //抢占2,子优先级0,组2}/****************************************************************************** ** 函数名: Write_W5500_1Byte* 描述: 通过SPI1向指定地址寄存器写1个字节数据* 输入: reg:16位寄存器地址,dat:待写入的数据* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void Write_W5500_1Byte(u16 reg, u8 dat){W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址SPI1_ReadWriteByte(FDM1|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,1个字节数据长度,写数据,选择通用寄存器SPI1_ReadWriteByte(dat);//写1个字节数据W5500_CS_High(); //置W5500的SCS为高电平}/****************************************************************************** ** 函数名: Write_W5500_2Byte* 描述: 通过SPI1向指定地址寄存器写2个字节数据* 输入: reg:16位寄存器地址,dat:16位待写入的数据(2个字节)* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void Write_W5500_2Byte(u16 reg, u16 dat){W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址SPI1_ReadWriteByte(FDM2|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,2个字节数据长度,写数据,选择通用寄存器SPI1_Send_Short(dat);//写16位数据W5500_CS_High(); //置W5500的SCS为高电平}/****************************************************************************** ** 函数名: Write_W5500_nByte* 描述: 通过SPI1向指定地址寄存器写n个字节数据* 输入: reg:16位寄存器地址,*dat_ptr:待写入数据缓冲区指针,size:待写入的数据长度* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void Write_W5500_nByte(u16 reg, u8 *dat_ptr, u16 size){u16 i;W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址SPI1_ReadWriteByte(VDM|RWB_WRITE|COMMON_R);//通过SPI1写控制字节,N个字节数据长度,写数据,选择通用寄存器for(i=0;i<size;i++)//循环将缓冲区的size个字节数据写入W5500{SPI1_ReadWriteByte(*dat_ptr++);//写一个字节数据}W5500_CS_High(); //置W5500的SCS为高电平/****************************************************************************** ** 函数名: Write_W5500_SOCK_1Byte* 描述: 通过SPI1向指定端口寄存器写1个字节数据* 输入: s:端口号,reg:16位寄存器地址,dat:待写入的数据* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void Write_W5500_SOCK_1Byte(SOCKET s, u16 reg, u8 dat){W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址SPI1_ReadWriteByte(FDM1|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,1个字节数据长度,写数据,选择端口s的寄存器SPI1_ReadWriteByte(dat);//写1个字节数据W5500_CS_High(); //置W5500的SCS为高电平}/****************************************************************************** ** 函数名: Write_W5500_SOCK_2Byte* 描述: 通过SPI1向指定端口寄存器写2个字节数据* 输入: s:端口号,reg:16位寄存器地址,dat:16位待写入的数据(2个字节)* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void Write_W5500_SOCK_2Byte(SOCKET s, u16 reg, u16 dat){W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址SPI1_ReadWriteByte(FDM2|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,2个字节数据长度,写数据,选择端口s的寄存器SPI1_Send_Short(dat);//写16位数据W5500_CS_High(); //置W5500的SCS为高电平/****************************************************************************** ** 函数名: Write_W5500_SOCK_4Byte* 描述: 通过SPI1向指定端口寄存器写4个字节数据* 输入: s:端口号,reg:16位寄存器地址,*dat_ptr:待写入的4个字节缓冲区指针* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void Write_W5500_SOCK_4Byte(SOCKET s, u16 reg, u8 *dat_ptr){W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址SPI1_ReadWriteByte(FDM4|RWB_WRITE|(s*0x20+0x08));//通过SPI1写控制字节,4个字节数据长度,写数据,选择端口s的寄存器SPI1_ReadWriteByte(*dat_ptr++);//写第1个字节数据SPI1_ReadWriteByte(*dat_ptr++);//写第2个字节数据SPI1_ReadWriteByte(*dat_ptr++);//写第3个字节数据SPI1_ReadWriteByte(*dat_ptr++);//写第4个字节数据W5500_CS_High(); //置W5500的SCS为高电平}/****************************************************************************** ** 函数名: Read_W5500_1Byte* 描述: 读W5500指定地址寄存器的1个字节数据* 输入: reg:16位寄存器地址* 输出: 无* 返回值: 读取到寄存器的1个字节数据* 说明: 无******************************************************************************* /u8 Read_W5500_1Byte(u16 reg){u8 i;W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址i=SPI1_ReadWriteByte(FDM1|RWB_READ|COMMON_R);//通过SPI1写控制字节,1个字节数据长度,读数据,选择通用寄存器// i=Read_W5500_1Byte(0x00);// SPI1_Send_Byte(0x00);//发送一个哑数据i=SPI1_ReadWriteByte(0x00);//读取1个字节数据W5500_CS_High();//置W5500的SCS为高电平return i;//返回读取到的寄存器数据}/****************************************************************************** ** 函数名: Read_W5500_SOCK_1Byte* 描述: 读W5500指定端口寄存器的1个字节数据* 输入: s:端口号,reg:16位寄存器地址* 输出: 无* 返回值: 读取到寄存器的1个字节数据* 说明: 无******************************************************************************* /u8 Read_W5500_SOCK_1Byte(SOCKET s, u16 reg){u8 i;W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址i=SPI1_ReadWriteByte(FDM1|RWB_READ|(s*0x20+0x08));//通过SPI1写控制字节,1个字节数据长度,读数据,选择端口s的寄存器// i=SPI_I2S_ReceiveData(SPI1);// SPI1_Send_Byte(0x00);//发送一个哑数据i=SPI1_ReadWriteByte(0X00);//读取1个字节数据W5500_CS_High();//置W5500的SCS为高电平return i;//返回读取到的寄存器数据}/****************************************************************************** ** 函数名: Read_W5500_SOCK_2Byte* 描述: 读W5500指定端口寄存器的2个字节数据* 输入: s:端口号,reg:16位寄存器地址* 输出: 无* 返回值: 读取到寄存器的2个字节数据(16位)* 说明: 无******************************************************************************* /u16 Read_W5500_SOCK_2Byte(SOCKET s, u16 reg){u16 i;W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(reg);//通过SPI1写16位寄存器地址i=SPI1_ReadWriteByte(FDM2|RWB_READ|(s*0x20+0x08));//通过SPI1写控制字节,2个字节数据长度,读数据,选择端口s的寄存器// i=SPI_I2S_ReceiveData(SPI1);// SPI1_Send_Byte(0x00);//发送一个哑数据i=SPI1_ReadWriteByte(0x00);//读取高位数据// SPI1_Send_Byte(0x00);//发送一个哑数据i*=256;i+=SPI1_ReadWriteByte(0x00);//读取低位数据W5500_CS_High();//置W5500的SCS为高电平return i;//返回读取到的寄存器数据}/****************************************************************************** ** 函数名: Read_SOCK_Data_Buffer* 描述: 从W5500接收数据缓冲区中读取数据* 输入: s:端口号,*dat_ptr:数据保存缓冲区指针* 输出: 无* 返回值: 读取到的数据长度,rx_size个字节* 说明: 无******************************************************************************* /u16 Read_SOCK_Data_Buffer(SOCKET s, u8 *dat_ptr){u16 rx_size;u16 offset, offset1;u16 i;u8 j;rx_size=Read_W5500_SOCK_2Byte(s,Sn_RX_RSR);if(rx_size==0) return 0;//没接收到数据则返回if(rx_size>1460) rx_size=1460;offset=Read_W5500_SOCK_2Byte(s,Sn_RX_RD);offset1=offset;offset&=(S_RX_SIZE-1);//计算实际的物理地址W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(offset);//写16位地址j=SPI1_ReadWriteByte(VDM|RWB_READ|(s*0x20+0x18));//写控制字节,N个字节数据长度,读数据,选择端口s的寄存器// j=SPI_I2S_ReceiveData(SPI1);if((offset+rx_size)<S_RX_SIZE)//如果最大地址未超过W5500接收缓冲区寄存器的最大地址{for(i=0;i<rx_size;i++)//循环读取rx_size个字节数据{// SPI1_Send_Byte(0x00);//发送一个哑数据j=SPI1_ReadWriteByte(0X00);//读取1个字节数据*dat_ptr=j;//将读取到的数据保存到数据保存缓冲区dat_ptr++;//数据保存缓冲区指针地址自增1}}else//如果最大地址超过W5500接收缓冲区寄存器的最大地址{offset=S_RX_SIZE-offset;for(i=0;i<offset;i++)//循环读取出前offset个字节数据{// SPI1_Send_Byte(0x00);//发送一个哑数据j=SPI1_ReadWriteByte(0X00);//读取1个字节数据*dat_ptr=j;//将读取到的数据保存到数据保存缓冲区dat_ptr++;//数据保存缓冲区指针地址自增1}W5500_CS_High(); //置W5500的SCS为高电平W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(0x00);//写16位地址j=SPI1_ReadWriteByte(VDM|RWB_READ|(s*0x20+0x18));//写控制字节,N个字节数据长度,读数据,选择端口s的寄存器// j=SPI_I2S_ReceiveData(SPI1);for(;i<rx_size;i++)//循环读取后rx_size-offset个字节数据{// SPI1_Send_Byte(0x00);//发送一个哑数据j=SPI1_ReadWriteByte(0X00);//读取1个字节数据*dat_ptr=j;//将读取到的数据保存到数据保存缓冲区dat_ptr++;//数据保存缓冲区指针地址自增1}}W5500_CS_High(); //置W5500的SCS为高电平offset1+=rx_size;//更新实际物理地址,即下次读取接收到的数据的起始地址Write_W5500_SOCK_2Byte(s, Sn_RX_RD, offset1);Write_W5500_SOCK_1Byte(s, Sn_CR, RECV);//发送启动接收命令return rx_size;//返回接收到数据的长度}/****************************************************************************** ** 函数名: Write_SOCK_Data_Buffer* 描述: 将数据写入W5500的数据发送缓冲区* 输入: s:端口号,*dat_ptr:数据保存缓冲区指针,size:待写入数据的长度* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void Write_SOCK_Data_Buffer(SOCKET s, u8 *dat_ptr, u16 size){u16 offset,offset1;u16 i;//如果是UDP模式,可以在此设置目的主机的IP和端口号if((Read_W5500_SOCK_1Byte(s,Sn_MR)&0x0f) != SOCK_UDP)//如果Socket打开失败{UDP_DIPR[0] = Flash_Tab[2]; //UDP(广播)模式,目的主机IP地址UDP_DIPR[1] = Flash_Tab[3];UDP_DIPR[2] = Flash_Tab[4];UDP_DIPR[3] = Flash_Tab[5];//UDP_DPORT[0] = Flash_Tab[8]; //UDP(广播)模式,目的主机端口号UDP_DPORT[1] = Flash_Tab[7];Write_W5500_SOCK_4Byte(s, Sn_DIPR, UDP_DIPR);//设置目的主机IPWrite_W5500_SOCK_2Byte(s, Sn_DPORTR, UDP_DPORT[0]*256+UDP_DPORT[1]);//设置目的主机端口号}offset=Read_W5500_SOCK_2Byte(s,Sn_TX_WR);offset1=offset;offset&=(S_TX_SIZE-1);//计算实际的物理地址W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(offset);//写16位地址SPI1_ReadWriteByte(VDM|RWB_WRITE|(s*0x20+0x10));//写控制字节,N个字节数据长度,写数据,选择端口s的寄存器if((offset+size)<S_TX_SIZE)//如果最大地址未超过W5500发送缓冲区寄存器的最大地址{for(i=0;i<size;i++)//循环写入size个字节数据{SPI1_ReadWriteByte(*dat_ptr++);//写入一个字节的数据}}else//如果最大地址超过W5500发送缓冲区寄存器的最大地址{offset=S_TX_SIZE-offset;for(i=0;i<offset;i++)//循环写入前offset个字节数据{SPI1_ReadWriteByte(*dat_ptr++);//写入一个字节的数据}W5500_CS_High(); //置W5500的SCS为高电平W5500_CS_Low();//置W5500的SCS为低电平SPI1_Send_Short(0x00);//写16位地址SPI1_ReadWriteByte(VDM|RWB_WRITE|(s*0x20+0x10));//写控制字节,N个字节数据长度,写数据,选择端口s的寄存器for(;i<size;i++)//循环写入size-offset个字节数据{SPI1_ReadWriteByte(*dat_ptr++);//写入一个字节的数据}}W5500_CS_High(); //置W5500的SCS为高电平offset1+=size;//更新实际物理地址,即下次写待发送数据到发送数据缓冲区的起始地址Write_W5500_SOCK_2Byte(s, Sn_TX_WR, offset1);Write_W5500_SOCK_1Byte(s, Sn_CR, SEND);//发送启动发送命令}/****************************************************************************** ** 函数名: W5500_Hardware_Reset* 描述: 硬件复位W5500* 输入: 无* 输出: 无* 返回值: 无* 说明: W5500的复位引脚保持低电平至少500us以上,才能重围W5500******************************************************************************* /void W5500_Hardware_Reset(void){W5500_RST_Low();//复位引脚拉低delay_ms(50);W5500_RST_High();//复位引脚拉高delay_ms(200);// while((Read_W5500_1Byte(PHYCFGR)&LINK)==0);//等待以太网连接完成}/****************************************************************************** ** 函数名: W5500_Init* 描述: 初始化W5500寄存器函数* 输入: 无* 输出: 无* 返回值: 无* 说明: 在使用W5500之前,先对W5500初始化******************************************************************************* /void W5500_Init(void){u8 i=0;Write_W5500_1Byte(MR, RST);//软件复位W5500,置1有效,复位后自动清0delay_ms(10);//延时10ms,自己定义该函数//设置网关(Gateway)的IP地址,Gateway_IP为4字节unsigned char数组,自己定义//使用网关可以使通信突破子网的局限,通过网关可以访问到其它子网或进入Internet Write_W5500_nByte(GAR, Gateway_IP, 4);//设置子网掩码(MASK)值,SUB_MASK为4字节unsigned char数组,自己定义//子网掩码用于子网运算Write_W5500_nByte(SUBR,Sub_Mask,4);//设置物理地址,PHY_ADDR为6字节unsigned char数组,自己定义,用于唯一标识网络设备的物理地址值//该地址值需要到IEEE申请,按照OUI的规定,前3个字节为厂商代码,后三个字节为产品序号//如果自己定义物理地址,注意第一个字节必须为偶数Write_W5500_nByte(SHAR,Phy_Addr,6);//设置本机的IP地址,IP_ADDR为4字节unsigned char数组,自己定义//注意,网关IP必须与本机IP属于同一个子网,否则本机将无法找到网关Write_W5500_nByte(SIPR,IP_Addr,4);//设置发送缓冲区和接收缓冲区的大小,参考W5500数据手册for(i=0;i<8;i++){Write_W5500_SOCK_1Byte(i,Sn_RXBUF_SIZE, 0x02);//Socket Rx memory size=2kWrite_W5500_SOCK_1Byte(i,Sn_TXBUF_SIZE, 0x02);//Socket Tx mempry size=2k }//设置重试时间,默认为2000(200ms)//每一单位数值为100微秒,初始化时值设为2000(0x07D0),等于200毫秒Write_W5500_2Byte(RTR, 0x07d0);//设置重试次数,默认为8次//如果重发的次数超过设定值,则产生超时中断(相关的端口中断寄存器中的Sn_IR 超时位(TIMEOUT)置“1”)Write_W5500_1Byte(RCR,8);//启动中断,参考W5500数据手册确定自己需要的中断类型//IMR_CONFLICT是IP地址冲突异常中断,IMR_UNREACH是UDP通信时,地址无法到达的异常中断//其它是Socket事件中断,根据需要添加Write_W5500_1Byte(IMR,IM_IR7 | IM_IR6);Write_W5500_1Byte(SIMR,S0_IMR);Write_W5500_SOCK_1Byte(0, Sn_IMR, IMR_SENDOK | IMR_TIMEOUT | IMR_RECV | IMR_DISCON | IMR_CON);}/****************************************************************************** ** 函数名: Detect_Gateway* 描述: 检查网关服务器* 输入: 无* 输出: 无* 返回值: 成功返回TRUE(0xFF),失败返回FALSE(0x00)* 说明: 无******************************************************************************* /u8 Detect_Gateway(void){u8 ip_adde[4];ip_adde[0]=IP_Addr[0]+1;ip_adde[1]=IP_Addr[1]+1;ip_adde[2]=IP_Addr[2]+1;ip_adde[3]=IP_Addr[3]+1;//检查网关及获取网关的物理地址Write_W5500_SOCK_4Byte(0,Sn_DIPR,ip_adde);//向目的地址寄存器写入与本机IP不同的IP值Write_W5500_SOCK_1Byte(0,Sn_MR,MR_TCP);//设置socket为TCP模式Write_W5500_SOCK_1Byte(0,Sn_CR,OPEN);//打开Socketdelay_ms(5);//延时5msif(Read_W5500_SOCK_1Byte(0,Sn_SR) != SOCK_INIT)//如果socket打开失败{Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);//打开不成功,关闭Socketreturn FALSE;//返回FALSE(0x00)}Write_W5500_SOCK_1Byte(0,Sn_CR,CONNECT);//设置Socket为Connect模式do{u8 j=0;j=Read_W5500_SOCK_1Byte(0,Sn_IR);//读取Socket0中断标志寄存器if(j!=0)Write_W5500_SOCK_1Byte(0,Sn_IR,j);delay_ms(5);//延时5msif((j&IR_TIMEOUT) == IR_TIMEOUT){return FALSE;}else if(Read_W5500_SOCK_1Byte(0,Sn_DHAR) != 0xff){Write_W5500_SOCK_1Byte(0,Sn_CR,CLOSE);//关闭Socketreturn TRUE;}}while(1);}/****************************************************************************** ** 函数名: Socket_Init* 描述: 指定Socket(0~7)初始化* 输入: s:待初始化的端口* 输出: 无* 返回值: 无* 说明: 无******************************************************************************* /void Socket_Init(SOCKET s){//设置分片长度,参考W5500数据手册,该值可以不修改Write_W5500_SOCK_2Byte(0, Sn_MSSR, 1460);//最大分片字节数=1460(0x5b4)//设置指定端口switch(s){case 0://设置端口0的端口号Write_W5500_SOCK_2Byte(0, Sn_PORT, S0_Port[0]*256+S0_Port[1]);break;case 1:break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 7:break;default:break;}}/****************************************************************************** ** 函数名: Socket_Connect* 描述: 设置指定Socket(0~7)为客户端与远程服务器连接* 输入: s:待设定的端口* 输出: 无* 返回值: 成功返回TRUE(0xFF),失败返回FALSE(0x00)* 说明: 当本机Socket工作在客户端模式时,引用该程序,与远程服务器建立连接* 如果启动连接后出现超时中断,则与服务器连接失败,需要重新调用该程序连接* 该程序每调用一次,就与服务器产生一次连接******************************************************************************* /unsigned char Socket_Connect(SOCKET s){Write_W5500_SOCK_1Byte(s,Sn_MR,MR_TCP);//设置socket为TCP模式Write_W5500_SOCK_1Byte(s,Sn_CR,OPEN);//打开Socketdelay_ms(5);//延时5msif(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_INIT)//如果socket打开失败{Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//打开不成功,关闭Socketreturn FALSE;//返回FALSE(0x00)}Write_W5500_SOCK_1Byte(s,Sn_CR,CONNECT);//设置Socket为Connect模式return TRUE;//返回TRUE,设置成功}/****************************************************************************** ** 函数名: Socket_Listen* 描述: 设置指定Socket(0~7)作为服务器等待远程主机的连接* 输入: s:待设定的端口* 输出: 无* 返回值: 成功返回TRUE(0xFF),失败返回FALSE(0x00)* 说明: 当本机Socket工作在服务器模式时,引用该程序,等等远程主机的连接* 该程序只调用一次,就使W5500设置为服务器模式******************************************************************************* /unsigned char Socket_Listen(SOCKET s){Write_W5500_SOCK_1Byte(s,Sn_MR,MR_TCP);//设置socket为TCP模式Write_W5500_SOCK_1Byte(s,Sn_CR,OPEN);//打开Socketdelay_ms(5);//延时5msif(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_INIT)//如果socket打开失败{Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//打开不成功,关闭Socketreturn FALSE;//返回FALSE(0x00)}Write_W5500_SOCK_1Byte(s,Sn_CR,LISTEN);//设置Socket为侦听模式delay_ms(5);//延时5msif(Read_W5500_SOCK_1Byte(s,Sn_SR)!=SOCK_LISTEN)//如果socket设置失败{Write_W5500_SOCK_1Byte(s,Sn_CR,CLOSE);//设置不成功,关闭Socketreturn FALSE;//返回FALSE(0x00)}return TRUE;//至此完成了Socket的打开和设置侦听工作,至于远程客户端是否与它建立连接,则需要等待Socket中断,//以判断Socket的连接是否成功。