这里写目录标题
- 一、W5500以太网模块
- 1.1 简介
- 1.2 模块排针功能表
- 1.3 W5500芯片资源介绍
- 1.4 接线方式
- 1.5代码调试
- 二、W5500实现modbus协议编程
- 三、W5500实现web服务协议编程
一、W5500以太网模块
1.1 简介
- NiRen_W5500模块是一款基于WIZnet W5500芯片的以太网模块,是泥人电子继 NiRen_W5100模块后设计的一块性能更好、性价比更高的以太网模块。模块集成硬件化TCP/IP协议;内部32K字节存储器作TX/RX缓存;支持10/100Mbps 的传输速率;支持8个独立端口同时运行;同时模块还支持3.3V或5V电源供电,5V供电时还可以输出3.3V电源,方便用户在不同的单片机系统中使用;模块与单片机系统的通讯方式是简单、方便的SPI通信。
1.2 模块排针功能表

1.3 W5500芯片资源介绍
- W5500芯片是一种采用全硬件TCP/IP协议栈的嵌入式以太网控制器,它能使嵌入式系统通过SPI(串行外设接口)接口轻松地连接到网络。W5500特别适合那些需要使用单片机来实现互联网功能的客户,而这就需要单片机系统具有完整的TCP/IP协议栈和10/100Mbps 以太网网络层(MAC)和物理层(PHY)。W5500是由已经通过市场考验的全硬件TCP/IP协议栈、及以太网网络层和物理层的整合而成。其全硬件的TCP/IP协议栈全程支持TCP、UDP、IPv4、ICMP、ARP、IGMP和 PPPoE协议,而且已经连续多年在各种实际应用中得以证明。W5500使用32KB缓存作为其数据通信内存。通过使用W5500,用户只需通过使用一个简单的socket程序就能实现以太网的应用,而不再需要处理一个复杂的以太网控制器了。SPI(串行外设接口)提供了轻松与外部MCU连接的接口。W5500支持高达8OMHZ的SPI 接口间通信。为了降低系统功率的消耗,W5500提供了网络唤醒和休眠模式。W5500收到原始以太网数据包形式的magic packet时将被唤醒。
1.4 接线方式

1.5代码调试
#include "stm32f10x.h"
#include "W5500.h"
#include <string.h>void RCC_Configuration(void);
void NVIC_Configuration(void);
void Timer2_Init_Config(void);
void System_Initialization(void);
void Delay(unsigned int d); unsigned int Timer2_Counter=0;
unsigned int W5500_Send_Delay_Counter=0;
void W5500_Initialization(void)
{W5500_Init(); Detect_Gateway(); Socket_Init(0);
}
void Load_Net_Parameters(void)
{Gateway_IP[0] = 192;Gateway_IP[1] = 168;Gateway_IP[2] = 0;Gateway_IP[3] = 1;Sub_Mask[0]=255;Sub_Mask[1]=255;Sub_Mask[2]=255;Sub_Mask[3]=0;Phy_Addr[0]=0x34;Phy_Addr[1]=0x4b;Phy_Addr[2]=0x50;Phy_Addr[3]=0x00;Phy_Addr[4]=0x00;Phy_Addr[5]=0x00;IP_Addr[0]=192;IP_Addr[1]=168;IP_Addr[2]=0;IP_Addr[3]=178;S0_Port[0] = 0x13;S0_Port[1] = 0x88;S0_DIP[0]=192;S0_DIP[1]=168;S0_DIP[2]=64;S0_DIP[3]=1;S0_DPort[0] = 0x17;S0_DPort[1] = 0x70;S0_Mode=TCP_CLIENT;
}
- 将代码烧录及STM32F103开发板中,打开调试工具

二、W5500实现modbus协议编程
- Modbus TCP通讯首先需要下载W5500的驱动源码,可以到WIZnet的官网下载。

- 下载FreeModbus源码,然后放到自己的工程中

- 修改porttcp中的代码
static UCHAR aucTCPBuf[MB_TCP_BUF_SIZE];
BOOL
xMBTCPPortInit( USHORT usTCPPort )
{BOOL bOkay = FALSE;socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);listen_tcp_socket(SOCK_TCP_PORT);bOkay = TRUE;return bOkay;
}
BOOL
xMBPortTCPPool( void )
{ unsigned short int us_rlen;unsigned char i;i=get_tcp_socket_state(SOCK_TCP_PORT);if(i==SOCK_ESTABLISHED_TCP){if(get_tcp_socket_irq(SOCK_TCP_PORT) & Sn_IR_CON_TCP) {clear_tcp_socket_irq(SOCK_TCP_PORT, Sn_IR_CON_TCP); }us_rlen=get_tcp_rx_buffer_size(SOCK_TCP_PORT); if(us_rlen==0) return FALSE; else{recv_tcp_socket_data(SOCK_TCP_PORT,aucTCPBuf,us_rlen); printf("receive\r\n");usTCPBufLen=us_rlen;}( void )xMBPortEventPost( EV_FRAME_RECEIVED ); }else if(i==SOCK_CLOSED_TCP) {socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);}else if(i==SOCK_INIT_TCP) {listen_tcp_socket(SOCK_TCP_PORT);}else if(i==SOCK_CLOSE_WAIT_TCP) {close_tcp_socket(SOCK_TCP_PORT);}return TRUE;
}
三、W5500实现web服务协议编程
3.1基本原理
- 实现的web服务的功能,STM32 W5500配置入网后,通过DHCP动态获取IP地址,在电脑浏览器地址栏输入这个IP地址,可以获取到一个简单form表单的页面,在表单中输入数据,提交到W5500web服务,返回一个结果。

int main(void)
{u32 dhcp_timestamp;u8 mac[6]={0, };DHCP_Get dhcp_get;u16 len;u8 buffer[BUFFER_SIZE];char http_method[16];char http_uri[64];char http_body[256];u8 res_code;systick_configuration();init_led();init_system_spi();func_w5500_reset();init_hardware_usart2_dma(9600);getMacByLockCode(mac);setSHAR(mac);sysinit(txsize, rxsize);setRTR(2000);setRCR(3);for(;func_dhcp_get_ip_sub_gw(1, mac, &dhcp_get, 500) != 0;); if(func_dhcp_get_ip_sub_gw(1, mac, &dhcp_get, 500) == 0){setSUBR(dhcp_get.sub);setGAR(dhcp_get.gw);setSIPR(dhcp_get.lip);close(1);}dhcp_timestamp = get_systick_timestamp();for(;;){if(get_systick_timestamp() - dhcp_timestamp > 59*1000){dhcp_timestamp = get_systick_timestamp();if(func_dhcp_get_ip_sub_gw(1, mac, &dhcp_get, 500) == 0){setSUBR(dhcp_get.sub);setGAR(dhcp_get.gw);setSIPR(dhcp_get.lip);close(1);}}switch(getSn_SR(SOCK_TCPS)){case SOCK_CLOSED:socket(SOCK_TCPS, Sn_MR_TCP, 80, Sn_MR_ND);break;case SOCK_INIT:listen(SOCK_TCPS);break; case SOCK_ESTABLISHED: if(getSn_IR(SOCK_TCPS) & Sn_IR_CON){setSn_IR(SOCK_TCPS, Sn_IR_CON);}len = getSn_RX_RSR(SOCK_TCPS);if(len>0){memset(buffer, 0, BUFFER_SIZE);len = recv(SOCK_TCPS, buffer, len);if(len > 0){res_code = func_analysis_http_request(buffer, len, http_method, http_uri, http_body);memset(buffer, 0, sizeof(buffer));if(res_code == 0){if(strcmp("GET", http_method) == 0 && strcmp("/", http_uri) == 0){func_package_http_response(buffer, &len, sizeof(buffer), HTML_CONTENT, strlen(HTML_CONTENT));send(SOCK_TCPS, buffer, len); }else if(strcmp("POST", http_method) == 0 && strcmp("/sn_config.action", http_uri) == 0){func_package_http_response(buffer, &len, BUFFER_SIZE, HTML_RESULT_OK, strlen(HTML_RESULT_OK));send(SOCK_TCPS, buffer, len);}else{memcpy(buffer, TEXT_TEMPLATE_ERR, strlen(TEXT_TEMPLATE_ERR));send(SOCK_TCPS, buffer, strlen(TEXT_TEMPLATE_ERR));}disconnect(SOCK_TCPS);}else{memcpy(buffer, TEXT_TEMPLATE_ERR, strlen(TEXT_TEMPLATE_ERR));send(SOCK_TCPS, buffer, strlen(TEXT_TEMPLATE_ERR));disconnect(SOCK_TCPS);}}}break;case SOCK_CLOSE_WAIT:close(SOCK_TCPS);break;}func_led1_on();delay_ms(500);func_led1_off();delay_ms(500);}
}u8 func_analysis_http_request(u8* buffer, u16 len_recv, char* method, char* uri, char* data_body)
{char chs[BUFFER_SIZE] = {0, };char *res, *end;if(len_recv > 0){memcpy(chs, buffer, 3);res = strstr(chs, "GET");if(strcmp("GET", res) == 0){memcpy(method, "GET", strlen("GET"));}else{memset(chs, 0, BUFFER_SIZE);memcpy(chs, buffer, 4);res = strstr(chs, "POST");if(strcmp("POST", res) == 0){memcpy(method, "POST", strlen("POST"));}else{return 1;}}memset(chs, 0, BUFFER_SIZE);memcpy(chs, buffer, len_recv + 1);res = strchr(chs, '/');if(res != NULL){end = strchr(res, ' ');if(end != NULL){memcpy(uri, res, end - res);} }memset(chs, 0, BUFFER_SIZE);memcpy(chs, buffer, len_recv + 1);res = strstr(chs, "\r\n\r\n");if(res != NULL){if(strlen(res) > 4){memcpy(data_body, res + 4, strlen(res) - 4);} }}return 0;
}u8 func_package_http_response(u8* buffer, u16 *len_ret, u16 len_buf, char* cont, u16 len_cont)
{memset(buffer, 0, BUFFER_SIZE);*len_ret = sprintf((char*)buffer, TEXT_TEMPLATE_OK, len_cont, cont);return 0;
}