一、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;
}
|