IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32+W5500网络通信 -> 正文阅读

[嵌入式]STM32+W5500网络通信

一、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代码调试

  • 在代码中添加本地ip地址、掩码及网关。
#include "stm32f10x.h"		
#include "W5500.h"			
#include <string.h>

void RCC_Configuration(void);		//设置系统时钟为72MHZ(这个可以根据需要改)
void NVIC_Configuration(void);		//STM32中断向量表配配置
void Timer2_Init_Config(void);		//Timer2初始化配置
void System_Initialization(void);	//STM32系统初始化函数(初始化STM32时钟及外设)
void Delay(unsigned int d);			//延时函数(ms)

unsigned int Timer2_Counter=0; //Timer2定时器计数变量(ms)
unsigned int W5500_Send_Delay_Counter=0; //W5500发送延时计数变量(ms)

/*******************************************************************************
* 函数名  : W5500_Initialization
* 描述    : W5500初始货配置
* 输入    : 无
* 输出    : 无
* 返回值  : 无
* 说明    : 无
*******************************************************************************/
void W5500_Initialization(void)
{
	W5500_Init();		//初始化W5500寄存器函数
	Detect_Gateway();	//检查网关服务器 
	Socket_Init(0);		//指定Socket(0~7)初始化,初始化端口0
}

/*******************************************************************************
* 函数名  : Load_Net_Parameters
* 描述    : 装载网络参数
* 输入    : 无
* 输出    : 无
* 返回值  : 无
* 说明    : 网关、掩码、物理地址、本机IP地址、端口号、目的IP地址、目的端口号、端口工作模式
*******************************************************************************/
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地址
	IP_Addr[1]=168;
	IP_Addr[2]=0;
	IP_Addr[3]=178;

	S0_Port[0] = 0x13;//加载端口0的端口号5000 
	S0_Port[1] = 0x88;

	S0_DIP[0]=192;//加载端口0的目的IP地址
	S0_DIP[1]=168;
	S0_DIP[2]=64;
	S0_DIP[3]=1;
	
	S0_DPort[0] = 0x17;//加载端口0的目的端口号6000
	S0_DPort[1] = 0x70;

	S0_Mode=TCP_CLIENT;//加载端口0的工作模式,TCP客户端模式
}

  • 将代码烧录及STM32F103开发板中,打开调试工具
    在这里插入图片描述

二、W5500实现modbus协议编程

  • Modbus TCP通讯首先需要下载W5500的驱动源码,可以到WIZnet的官网下载
    解压目录
  • 下载FreeModbus源码,然后放到自己的工程中
    在这里插入图片描述
  • 修改porttcp中的代码
static UCHAR    aucTCPBuf[MB_TCP_BUF_SIZE];	  
BOOL
xMBTCPPortInit( USHORT usTCPPort )
{
    BOOL bOkay = FALSE;
     
    // 侦听端口 Modbus-TCP 端口
	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); 				//获取接收到的数据字节				  	         /*定义len为已接收数据的长度*/
		if(us_rlen==0)												//没有接收到数据
			return FALSE;											//返回
		else
		{
			recv_tcp_socket_data(SOCK_TCP_PORT,aucTCPBuf,us_rlen); 	//接收数据						   		         /*接收来自Server的数据*/
			printf("receive\r\n");
			usTCPBufLen=us_rlen;
		}
		( void )xMBPortEventPost( EV_FRAME_RECEIVED );			//发送已接收到新数据到Modbus-TCP状态机
	}
	else if(i==SOCK_CLOSED_TCP)									//如果socket关闭
	{
		socket_init(SOCK_TCP_PORT,Sn_MR_TCP_TCP,local_tcp_port++,Sn_MR_ND_TCP);//重新初始化
	}
	else if(i==SOCK_INIT_TCP)								//如果socket初始化完毕,监听端口
	{
		listen_tcp_socket(SOCK_TCP_PORT);
	}
	else if(i==SOCK_CLOSE_WAIT_TCP)							//如果socket等待关闭,关闭socket连接
	{
		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);
	
	//DHCP
	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)// 1 min dhcp
		{
			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);
					//analysis tcp msg, and package the feedback msg
					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;
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 23:05:40  更:2021-12-28 23:05:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 15:26:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码