精华内容
下载资源
问答
  • stm32 w5500 例程代码

    2018-10-26 15:55:26
    stm32 w5500 实现单片机tcp udp http 网络通讯,为单片机联网提供解决方案
  • 做了STM32 W5500联网通讯几个月了,回头总结一下 STM32 W5500 的TCP Server要注意的一些点: 1、有好用的W5500基础支持库 2、在PC的CMD命令窗口中可以PING通W5500设备。 3、在测试的时候,条件允许登录到路由器的...

    做了STM32 W5500联网通讯几个月了,回头总结一下 STM32 W5500 的TCP Server要注意的一些点:

    1、有好用的W5500基础支持库

    2、在PC的CMD命令窗口中可以PING通W5500设备

    3、在测试的时候,条件允许登录到路由器的管理页面,查看连接设备是否有W5500的有线连接(非必须)。

    满足以上几点,基本可以测通TCP Server的回环测试了。

    贴出测试的主函数代码:

    #ifndef __STM32F10X_H
    #define __STM32F10X_H
    #include "stm32f10x.h"
    #endif
    
    #ifndef __Z_UTIL_TIME_H
    #define __Z_UTIL_TIME_H
    #include "z_util_time.h"
    #endif
    
    #ifndef __Z_HARDWARE_LED_H
    #define __Z_HARDWARE_LED_H
    #include "z_hardware_led.h"
    #endif
    
    #ifndef __Z_HARDWARE_SPI_H
    #define __Z_HARDWARE_SPI_H
    #include "z_hardware_spi.h"
    #endif
    
    #include "w5500.h"
    #include "socket.h"
    #include "w5500_conf.h"
    
    uint8 buffer[2048];
    
    int main(void)
    {
    	uint8 mac[6]={0x00, 0x0C, 0x32, 0xDA, 0x07, 0x4C};
    	uint8 lip[4]={192,168,1,112};
    	uint8 sub[4]={255,255,255,0};
    	uint8 gw[4]={192,168,1,1};
    		
    	uint8 remote_ip[4] = {192,168,1,105};
    	uint16 remote_port = 9000;
    	uint16 local_port = 5000;
    	uint16 len;
    	u8 sock_status;
    	
    	init_led();
    	init_system_spi();
    	func_w5500_reset();
    		
    	setSHAR(mac);
      setSUBR(sub);
      setGAR(gw);
      setSIPR(lip);
    	
    	sysinit(txsize, rxsize);
    	setRTR(2000);
      setRCR(3);
    	setkeepalive(0);
    	
    //	socket(0,Sn_MR_UDP,local_port-1,0);
    //	buffer[0] = 0x55;
    //	buffer[1] = 0xAA;
    //	len = 2;
    //	sendto(0, buffer, len, remote_ip, remote_port);
    	
    
    	for(;;)
    	{	
    		sock_status = getSn_SR(1);
    		switch(sock_status)
    		{
    			case SOCK_CLOSED:
    				socket(1 ,Sn_MR_TCP,local_port,Sn_MR_ND);
    				break;    
    			case SOCK_INIT:
    				listen(1);
    				break;		
    			case SOCK_ESTABLISHED:		
    				if(getSn_IR(1) & Sn_IR_CON)
    				{
    					setSn_IR(1, Sn_IR_CON);
    				}
    				len=getSn_RX_RSR(1);
    				if(len>0)
    				{
    					len = recv(1, buffer, len);
    					send(1, buffer, len);
    				}
    				break;
    			case SOCK_CLOSE_WAIT:
    				close(1);
    				break;
    		}
    						
    		func_led1_on();
    		delay_ms(500);
    		func_led1_off();
    		delay_ms(500);
    		
    	}
    	
    	
    }
    
    

    通过PC的CMD命令窗口PING设备:

    回环测试的效果如下:

    W5500的库函数,可以参考 《测试工程代码00_W5500_ping.rar》

    将以上的主函数替换到工程的主函数即可。

    TCP Server的拓展应用场景,可以做一个小型的嵌入式Web网站。

    展开全文
  • 使用STM32 W5500做MQTT Client,使得数据上传broker,并接收broker传来的消息,并支持断网/拔网线再插入网线能够重新连接broker这样的功能,需要具备以下条件: 1、STM32 W5500基础入网配置,使能PC电脑端可以PING...

    使用STM32 W5500做MQTT Client,使得数据上传broker,并接收broker传来的消息,并支持断网/拔网线再插入网线能够重新连接broker这样的功能,需要具备以下条件:

    1、STM32 W5500基础入网配置,使能PC电脑端可以PING通W5500。

    2、STM32 W5500的TCP Client收发数据的回环测试没有问题。

    3、了解MQTT协议。

    关于MQTT的介绍,本文不做重点。需要了解的是MQTT协议是基于TCP协议之上封装的协议。

    关于MQTT Client依赖的MQTT支持库函数,下载地址 《MQTT C语言库函数》

    这些库函数是干嘛的?

    MQTT协议在STM32 W5500中使用的前提,首先通过TCP连接到broker指定的IP和端口。

    然后需要发送MQTT连接的指令,这个指令内容是通过 "MQTTConnectClient.c"文件中的

    int MQTTSerialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options)

    这个方法来实现组装的,返回值大于0表示组装后的数组有效内容长度,在通过W5500的send方法,发送给broker。

    broker接收到Client端发来的MQTT连接请求后,会返回一组数据,判断是否连接成功,或者各种失败(协议版本错误,用户名密码错误等)。

    MQTT Client如果想要接收到broker发来的消息,需要先订阅主题,订阅主题的指令内容是通过"MQTTSubscribeClient.c"文件中的

    int MQTTSerialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, int count,
    		MQTTString topicFilters[], int requestedQoSs[])

    这个方法来实现组装的,同样返回值大于0表示组装后的数组有效内容长度,在通过W5500的send方法,发送给broker。

    以上两个举例都是组装指令内容。

    那么接收到broker发来消息,如何解析?

    "MQTTDeserializePublish.c"这个文件的

    int MQTTDeserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName,
    		unsigned char** payload, int* payloadlen, unsigned char* buf, int buflen)

    这个方法可以实现消息内容的解析。

    总之,依赖的MQTT支持库函数几乎可以使我们不用在乎协议的具体内容,就可以实现MQTT Client的功能。

    STM32 W5500 MQTT Client端,我通过枚举类型给它定义三种状态

    enum MQTT_STATE {MQTT_INIT, MQTT_CONNOK, MQTT_SUBOK};

    MQTT_INIT - 初始状态(MQTT未连接,未订阅,注意是MQTT的,而不是TCP连接了没有

    MQTT_CONNOK - MQTT连接成功(MQTT Client端发起MQTT连接,并接收到了broker返回连接成功)

    MQTT_SUBOK - MQTT订阅成功(MQTT Client端想broker订阅消息,并受到了broker返回订阅成功)

    这几种状态的关连,在程序开始执行时,MQTT Client端处于MQTT_INIT状态,或者程序执行一段时间后,MQTT PING指令发几次broker没有回复,认为MQTT Client端处于MQTT_INIT状态。

    MQTT Client端处于MQTT_CONNOK 状态时可以发布数据到broker,但是无法接收来自broker的消息。

    MQTT Client端处于MQTT_SUBOK 状态时可以发布数据到broker,也可以接收来自broker的消息。

    如果TCP Client处于CLOSE的状态,那么MQTT Client端将处于MQTT_INIT 状态。

    做好MQTT Client端的难点在于维系 TCP socket的状态与MQTT Client的状态的关系。

    贴出我实现MQTT Client的c代码:

    impl_mqtt.c

    #ifndef __IMPL_MQTT_H
    #define __IMPL_MQTT_H
    #include "impl_mqtt.h"
    #endif
    
    int mqttstate = MQTT_INIT;
    int cnt_ping_not_response = 0;
    int cnt_sock_init = 0;
    u8 buf_pub[1024];
    u32 ping_timestamp, now_timestamp;
    
    int func_tcp_sock_send(u8 sockno, u8 *buf_mqsend, u16 len_mqsend)
    {
    	if(getSn_SR(sockno) == SOCK_ESTABLISHED)
    	{
    		return send(sockno, buf_mqsend, len_mqsend);
    	}
    	return -1;		
    }
    
    int func_tcp_sock_read(u8 sockno, u8 *buf_mqrecv, u16 len_mqrecv)
    {
    	if((getSn_SR(sockno) == SOCK_ESTABLISHED))
    	{
    		len_mqrecv = getSn_RX_RSR(sockno);
    		if(len_mqrecv > 0)
    		{
    			return recv(sockno, buf_mqrecv, len_mqrecv);
    		}
    	}
    	return -1; 
    }
    
    void func_judge_timeout_ms(u32 *timespan)
    {
    	delay_ms(1);
    	*timespan = *timespan + 1;
    }
    
    u8 func_judge_mqtt_recvmsg_package_type(u8 *buf_mqrecv, u16 len_mqrecv)
    {
    	MQTTHeader header = {0};
    	if(len_mqrecv > 0)
    	{
    		header.byte = buf_mqrecv[0];
    		return header.bits.type;
    	}
    	return 0;
    }
    
    void func_mqtt_client_dealwith_recvmsg(u8 sockno, u8 *buf_mqrecv, u16 len_mqbuf, u16 len_mqrecv)
    {
    	if(len_mqrecv > 0)
    	{
    		ping_timestamp = get_systick_timestamp();
    		// package type to deal
    		switch(func_judge_mqtt_recvmsg_package_type(buf_mqrecv, len_mqrecv))
    		{
    			case CONNACK:
    			break;
    			case PUBLISH://analysis msg
    			{
    				int rc;
    				u8 buf_recv[1024];
    				u8* payload;
    				int len_payload;
    				unsigned char retained, dup;
    				int qos;
    				unsigned short packetid; 
    				MQTTString topicrecv;
    				MQTTString topicpub;
    				payload = buf_recv;
    				rc = MQTTDeserialize_publish(&dup, &qos, &retained, &packetid, &topicrecv, &payload, &len_payload, buf_mqrecv, len_mqrecv);
    				if(rc == 1)
    				{
    					//TODO ...
    					//TEST code
    					topicpub.cstring = (char*)"mytopic";
    					memset(buf_pub, 0, sizeof(buf_pub));
    					func_run_mqtt_publish(sockno, buf_pub, sizeof(buf_pub), topicpub, payload, len_payload);
    				}
    			}			
    			break;
    			case PUBACK:
    			break;
    			case PUBREC://Qos2 msg receipt
    			case PUBREL://Qos2 msg receipt
    			case PUBCOMP://Qos2 msg receipt
    			{
    				unsigned char packettype, dup;
    				unsigned short packetid; 
    				if (MQTTDeserialize_ack(&packettype, &dup, &packetid, buf_mqrecv, len_mqbuf) == 1)
    				{
    					memset(buf_mqrecv, 0, len_mqbuf);
    					len_mqrecv = MQTTSerialize_ack(buf_mqrecv, len_mqbuf, packettype, dup, packetid);
    					if(len_mqrecv > 0)
    					{
    						func_tcp_sock_send(sockno, buf_mqrecv, len_mqrecv);
    					}
    				}
    			}
    			break;
    			case SUBACK:
    			case UNSUBACK:
    			case PINGREQ:
    			case PINGRESP:
    			case DISCONNECT:
    			break;
    			default:
    			break;
    		}
    	}
    }
    
    void func_mqtt_client_connect_broker(int *state, u8 sockno, u8 *buf_mqsend, u16 len_mqsend, MQTTPacket_connectData *conn_mqtt)
    {
    	u32 timespan;
    	int len_cont;
    	int res;
    	len_cont = MQTTSerialize_connect(buf_mqsend, len_mqsend, conn_mqtt);
    	if(len_cont > 0)
    	{
    		res = func_tcp_sock_send(sockno, buf_mqsend, len_cont);
    		if(res > 0)
    		{
    			timespan = 0;
    			memset(buf_mqsend, 0, len_mqsend);//reuse buffer
    			for(;;)
    			{
    				if((len_cont = func_tcp_sock_read(sockno, buf_mqsend, len_mqsend)) > 3)
    				{
    					if(func_judge_mqtt_recvmsg_package_type(buf_mqsend, len_cont) == CONNACK) 
    					{
    						*state = MQTT_CONNOK;
    						ping_timestamp = get_systick_timestamp();
    					}
    					break;
    				}
    				func_judge_timeout_ms(&timespan);
    				if(timespan > 500)
    				{
    					break;
    				}
    			}
    		}
    	}
    }
    
    void func_mqtt_client_ping_broker(int *state, u8 sockno, u8 *buf_mqsend, u16 len_mqsend)
    {
    	u32 timespan;
    	int len_cont;
    	int res;
    	if(get_systick_timestamp() - ping_timestamp > 5*1000)
    	{		
    		len_cont = MQTTSerialize_pingreq(buf_mqsend, len_mqsend);
    		if(len_cont > 0)
    		{
    			res = func_tcp_sock_send(sockno, buf_mqsend, len_cont);
    			if(res > 0)
    			{
    				timespan = 0;
    				memset(buf_mqsend, 0, len_mqsend);//reuse buffer
    				for(;;)
    				{
    					len_cont = func_tcp_sock_read(sockno, buf_mqsend, len_mqsend);
    					// pingrsp or others' published msg 
    					if(len_cont > 0)
    					{
    						//recv pingrsp
    						ping_timestamp = get_systick_timestamp();
    						cnt_ping_not_response = 0;
    						
    						// other type msg to deal with
    						func_mqtt_client_dealwith_recvmsg(sockno, buf_mqsend, len_mqsend, len_cont);
    						break;
    					}
    					
    					func_judge_timeout_ms(&timespan);
    					if(timespan > 10)
    					{
    						cnt_ping_not_response ++;
    						if(cnt_ping_not_response > 1)
    						{
    							*state = MQTT_INIT;
    							close(sockno);
    							cnt_ping_not_response = 0;
    						}
    						break;
    					}
    				}
    			}
    			else
    			{
    				cnt_ping_not_response ++;
    				if(cnt_ping_not_response > 2)
    				{
    					*state = MQTT_INIT;
    					close(sockno);
    					cnt_ping_not_response = 0;
    				}
    			}
    		}
    	}
    }
    
    int func_run_mqtt_publish(u8 sockno, u8 *buf_mqsend, u16 len_mqsend, MQTTString topicName, u8* payload, int payloadlen)
    {
    	int len;
    	int rc;
    	
    	if(mqttstate >= MQTT_CONNOK)
    	{
    		len = MQTTSerialize_publish(buf_mqsend, len_mqsend, 0, 0, 0, 0, topicName, payload, payloadlen);
    		if(len > 0)
    		{
    			memcpy(buf_pub, buf_mqsend, len);
    			rc = func_tcp_sock_send(sockno, buf_pub, len);
    			if(rc > 0)
    			{
    				ping_timestamp = get_systick_timestamp();
    			}
    			return rc;
    		}
    	}	
    	return 0;
    }
    
    int func_mqtt_client_subtopic_from_broker(u8 sockno, u8 *buf_mqsend, u16 len_mqsend, int count,\
    		MQTTString topicFilters[], int requestedQoSs[])
    {
    	u32 timespan;
    	int len_cont;
    	int res;
    	if(mqttstate != MQTT_SUBOK)
    	{
    		len_cont = MQTTSerialize_subscribe(buf_mqsend, len_mqsend, 0, SUBSCRIBE, count, topicFilters, requestedQoSs);
    		if(len_cont > 0)
    		{
    			res = func_tcp_sock_send(sockno, buf_mqsend, len_cont);
    			if(res > 0)
    			{
    				timespan = 0;
    				memset(buf_mqsend, 0, len_mqsend);//reuse buffer
    				for(;;)
    				{
    					if((len_cont = func_tcp_sock_read(sockno, buf_mqsend, len_mqsend)) > 0 && func_judge_mqtt_recvmsg_package_type(buf_mqsend, len_cont) == SUBACK)//nowtime, ignore other type msg 
    					{
    						mqttstate = MQTT_SUBOK;
    						ping_timestamp = get_systick_timestamp();
    						return 0;
    					}
    					func_judge_timeout_ms(&timespan);
    					if(timespan > 500)
    					{
    						return -2;
    					}
    				}
    			}
    		}
    	}
    	return -1;
    }
    
    void func_mqtt_client_recvmsg_from_broker(u8 sockno, u8 *buf_mqsend, u16 len_mqsend)
    {
    	int len_cont;
    	memset(buf_mqsend, 0, len_mqsend);
    	len_cont = func_tcp_sock_read(sockno, buf_mqsend, len_mqsend);
    	if(len_cont > 0)
    	{
    		func_mqtt_client_dealwith_recvmsg(sockno, buf_mqsend, len_mqsend, len_cont);
    	}	
    }
    
    u8 func_run_mqtt_tcpsock(u8 sockno, u8 *broker_ip, u16 broker_port, u8 *buf_mqsend, u16 len_mqsend, MQTTPacket_connectData *conn_mqtt)
    {
    	static u16 any_port = 50000;
    	u8 res;
    	
    	switch(getSn_SR(sockno))
    	{
    		case SOCK_CLOSED:
    		{
    			close(sockno);
    			socket(sockno, Sn_MR_TCP, any_port++, 0x00);
    			cnt_sock_init++;
    			if(cnt_sock_init > 30)
    			{
    				cnt_sock_init = 0;
    				close(sockno);
    				mqttstate = MQTT_INIT;
    			}
    			if(any_port > 64000)
    			{
    				any_port =50000;
    			}
    		}			
    		break;
    		case SOCK_INIT:
    		{
    			res = connect(sockno, broker_ip, broker_port);
    			if(res)
    			{
    				//mqtt connect request
    				mqttstate = func_run_mqtt_progress(mqttstate, sockno, buf_mqsend, len_mqsend, conn_mqtt);
    			}
    			else
    			{
    				if(cnt_ping_not_response > 0)
    				{
    					mqttstate = MQTT_INIT;
    				}
    			}
    		}
    		break;
    		case SOCK_ESTABLISHED:
    		{
    			//run mqtt progress
    			mqttstate = func_run_mqtt_progress(mqttstate, sockno, buf_mqsend, len_mqsend, conn_mqtt);
    		}
    		break;
    		case SOCK_CLOSE_WAIT: 
    		{
    			mqttstate = MQTT_INIT;
    			close(sockno);
    		}
    		break;
    		default:
    			break;
    	}
    	return mqttstate;
    }
    
    u8 func_run_mqtt_progress(int state, u8 sockno, u8 *buf_mqsend, u16 len_mqsend, MQTTPacket_connectData *conn_mqtt)
    {
    	switch(state)
    	{
    		case MQTT_INIT:
    		{
    			func_mqtt_client_connect_broker(&state, sockno, buf_mqsend, len_mqsend, conn_mqtt);
    		}
    		break;
    		case MQTT_CONNOK:
    		{
    			func_mqtt_client_ping_broker(&state, sockno, buf_mqsend, len_mqsend);
    			if(state > MQTT_INIT)
    			{
    //				func_mqtt_client_subtopic_from_broker(&state, sockno, buf_mqsend, len_mqsend);
    			}
    		}
    		break;
    		case MQTT_SUBOK:
    		{
    			func_mqtt_client_ping_broker(&state, sockno, buf_mqsend, len_mqsend);
    			if(state != MQTT_INIT)
    			{
    				func_mqtt_client_recvmsg_from_broker(sockno, buf_mqsend, len_mqsend);
    			}
    		}
    		break;
    		default:
    		break;
    	}
    	return state;
    }

    可能不是十分完美,但是一般工程上使用应该问题不大,我也测试了好久。

    测试的主函数,是做了MQTT的回环测试,MQTT Client端连接到broker后,发起订阅主题,并一次性订阅多个主题,分别是字符串subtopic、subtopic2、subtopic3、subtopic4。当其他客户端连接到broker后,向这四个主题发布消息,STM32 W5500 MQTT Client端接收后,会向 mytopic发布一条消息。

    #ifndef __STM32F10X_H
    #define __STM32F10X_H
    #include "stm32f10x.h"
    #endif
    
    #ifndef __Z_UTIL_TIME_H
    #define __Z_UTIL_TIME_H
    #include "z_util_time.h"
    #endif
    
    #ifndef __Z_HARDWARE_LED_H
    #define __Z_HARDWARE_LED_H
    #include "z_hardware_led.h"
    #endif
    
    #ifndef __Z_HARDWARE_SPI_H
    #define __Z_HARDWARE_SPI_H
    #include "z_hardware_spi.h"
    #endif
    
    #ifndef __W5500_H
    #define __W5500_H
    #include "w5500.h"
    #endif
    
    #ifndef __SOCKET_H
    #define __SOCKET_H
    #include "socket.h"
    #endif
    
    #ifndef __W5500_CONF_H
    #define __W5500_CONF_H
    #include "w5500_conf.h"
    #endif
    
    #ifndef __DHCP_H
    #define __DHCP_H
    #include "dhcp.h"
    #endif
    
    #ifndef __Z_HARDWARE_USART2_H
    #define __Z_HARDWARE_USART2_H
    #include "z_hardware_usart2.h"
    #endif
    
    #include "MQTTPacket.h"
    
    #ifndef __IMPL_MQTT_H
    #define __IMPL_MQTT_H
    #include "impl_mqtt.h"
    #endif
    
    
    int main(void)
    {
    	u32 dhcp_timestamp;
    	u8 ip_broker[] = {192, 168, 1, 127};
    	u16 port_broker = 1883;
    	u8 buf_mqtt_send[1024];
    	u8 mac[6]={0, };
    	DHCP_Get dhcp_get;
    	int mqtt_stat;
    	
    	MQTTString sub_topic = MQTTString_initializer;
    	MQTTString sub_topic2 = MQTTString_initializer;
    	MQTTString sub_topic3 = MQTTString_initializer;
    	MQTTString sub_topic4 = MQTTString_initializer;
    	MQTTString sub_topics[4];
    	int nums_sub_topic_qoss[4] = {0, };
    	char stpc_str[64] = {'t', 'c'};
    	
    	MQTTPacket_connectData conn_mqtt = MQTTPacket_connectData_initializer;
    	conn_mqtt.willFlag = 0;
    	conn_mqtt.MQTTVersion = 3;
    	conn_mqtt.clientID.cstring = (char*)"dev_abcdef";
    	conn_mqtt.username.cstring = (char*)"abcdef";
    	conn_mqtt.password.cstring = (char*)"123456";
    	conn_mqtt.keepAliveInterval = 60;
    	conn_mqtt.cleansession = 1;	
    	
    	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();
    	
    	memcpy(stpc_str, (char*)"subtopic", strlen("subtopic"));
    	sub_topic.cstring = stpc_str;
    	sub_topics[0] = sub_topic;
    	sub_topic2.cstring = "subtopic2";
    	sub_topics[1] = sub_topic2;
    	sub_topic3.cstring = "subtopic3";
    	sub_topics[2] = sub_topic3;
    	sub_topic4.cstring = "subtopic4";
    	sub_topics[3] = sub_topic4;
    	
    	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);
    			}
    		}
    		mqtt_stat = func_run_mqtt_tcpsock(2, ip_broker, port_broker, buf_mqtt_send, sizeof(buf_mqtt_send), &conn_mqtt);
    		if(mqtt_stat >= MQTT_CONNOK)
    		{
    			if(mqtt_stat == MQTT_CONNOK)
    			{
    				memset(buf_mqtt_send, 0, sizeof(buf_mqtt_send));
    				func_mqtt_client_subtopic_from_broker(2, buf_mqtt_send, sizeof(buf_mqtt_send), 4,	sub_topics, nums_sub_topic_qoss);
    
    			}
    			func_led1_toggle();
    		}		
    		delay_ms(500);
    				
    	}
    }

    电脑端使用MQTT.fx工具进行测试,测试效果

    目前测试还比较稳定,支持热插拔网线,以及路由器断网后再次联网,MQTT Client仍可继续连接broker。

    展开全文
  • 现在想让STM32 W5500通过HTTP Client POST...1、STM32 W5500的基础配置,使得PC和W5500在同一个局域网内,PC可以PING通W5500。 2、STM32 W5500的TCP Client可以成功发数据,HTTP协议是基于TCP协议之上封装的协议。 ...

    现在想让STM32 W5500通过HTTP Client POST的方式提交数据到远程服务器,并接收服务返回的JSON格式数据,解析和处理。

    实现以上功能,需要具备几个条件:

    1、STM32 W5500的基础配置,使得PC和W5500在同一个局域网内,PC可以PING通W5500

    2、STM32 W5500的TCP Client可以成功发数据,HTTP协议是基于TCP协议之上封装的协议。

    3、远程服务器接口可以访问,可以通过POSTMAN工具先测试。

    4、使用WireShark工具,追踪POSTMAN访问服务接口的报文数据,以及返回的报文数据。

    STM32 W5500的基础配置和TCP Client我已具备条件,下面看下远程服务器接口是否可以访问:

    Header部分:

    Request Body和Response Body

    接口返回了JSON 结构数据,说明接口是可以访问的。

    打开WireShark工具,追踪一下POSTMAN访问的流数据,以及服务器返回的响应报文数据。

    请求数据的追踪

    接口返回的报文数据追踪

    基础准备工作已经做好,那么STM32 W5500 Http Client POST请求的实现,由于一些信息比较敏感,对代码做了处理:

    httppost.c

    #ifndef __HTTPPOST_H
    #define __HTTPPOST_H
    #include "httppost.h"
    #endif
    
    u16 func_pack_httppost_body(char *buff_body, char *productId, char *deviceSn, char *deviceMac, char *devicePassword, char *hardwareVersion)
    {
    	u16 len;
    	len = sprintf(buff_body, "a=%s&b=%s&c=%s&d=%s&e=%s",\
    		productId, deviceSn, deviceMac, devicePassword, hardwareVersion);
    	return len;
    }
    
    u16 func_pack_httppost_head_body(char *buff_post, char *url_tail, u8 *host, u16 port, char *body, u16 body_len)
    {
    	u16 len;
    	len = sprintf(buff_post, "POST %s HTTP/1.1\r\n"
    		"Connection: close\r\n"
    		"User-Agent:W5500\r\n"
    		"Content-Type:application/x-www-form-urlencoded\r\n"
    		"Host: %d.%d.%d.%d:%d\r\n"
    		"Content-Length: %d\r\n\r\n"
    		"%s\r\n", url_tail, host[0], host[1], host[2], host[3], port, body_len, body
    	);
    	return len;
    }
    
    static u16 local_port = 50000;
    
    u8 func_http_post(u8 sock_no, u8 *rip, u16 port, char *buf_post, u16 len_post,char *buf_recv, u16 *len_recv, u16 timeout_ms)
    {
    	u16 cnt, len;	
    	char *body_cont;
    	cnt = 0;
    	
    	for(;;)
    	{
    		switch(getSn_SR(sock_no))
    		{
    			case SOCK_INIT:
    				connect(sock_no, rip, port);
    			break;
    			case SOCK_ESTABLISHED:
    				send(sock_no, (u8*)buf_post, len_post); 
    				if(getSn_IR(sock_no) & Sn_IR_CON)   					
    				{
    					setSn_IR(sock_no, Sn_IR_CON);
    				}
    				len = getSn_RX_RSR(sock_no);
    				if(len > 0)
    				{
    					memset(buf_recv, 0, len_post);
    					len = recv(sock_no, (u8*)buf_recv, len);
    					body_cont = strstr((char*)buf_recv, "HTTP/1.1 200");
    					if(body_cont == NULL)
    					{
    						return 2;
    					}
    					body_cont = strstr((char*)buf_recv, "\r\n\r\n");
    					if(body_cont != NULL)
    					{
    						len = strlen(body_cont) - 4;
    						memcpy(buf_recv, body_cont + 4, len);
    						buf_recv[len] = '\0';
    						*len_recv = len;
    						close(sock_no);
    						return 0;
    					}					
    				}				
    			break;
    			case SOCK_CLOSE_WAIT:
    				close(sock_no);
    			break;
    			case SOCK_CLOSED:
    				socket(sock_no, Sn_MR_TCP, local_port++, Sn_MR_ND);
    				if(local_port > 64000)
    				{
    					local_port = 50000;
    				}
    			break;
    		}
    		
    		cnt ++;
    		if(cnt >= timeout_ms)
    		{
    			close(sock_no);
    			return 1;
    		}
    		delay_ms(1);
    	}
    }
    

    测试的主函数代码:

    #ifndef __STM32F10X_H
    #define __STM32F10X_H
    #include "stm32f10x.h"
    #endif
    
    #ifndef __Z_UTIL_TIME_H
    #define __Z_UTIL_TIME_H
    #include "z_util_time.h"
    #endif
    
    #ifndef __Z_HARDWARE_LED_H
    #define __Z_HARDWARE_LED_H
    #include "z_hardware_led.h"
    #endif
    
    #ifndef __Z_HARDWARE_SPI_H
    #define __Z_HARDWARE_SPI_H
    #include "z_hardware_spi.h"
    #endif
    
    #ifndef __Z_HARDWARE_USART2_H
    #define __Z_HARDWARE_USART2_H
    #include "z_hardware_usart2.h"
    #endif
    
    #include "w5500.h"
    #include "socket.h"
    #include "w5500_conf.h"
    #include "dhcp.h"
    #include "dns.h"
    
    #ifndef __HTTPPOST_H
    #define __HTTPPOST_H
    #include "httppost.h"
    #endif
    
    char buf_send[2048];
    char buf_cont[256];
    	
    int main(void)
    {
    	DHCP_Get dhcp_get;
    //	u8 buf_recv[1536] = {0, };
    	
    	u16 len, recv_len;
    	u8 res;
    	
    	uint8 mac[6];
    	u8 remote_ip[4] = {192, 168, 1, 109};
    	u16 port = 8084;	
    	
    	init_led();
    	
    	init_system_spi();
    	func_w5500_reset();
    	
    	init_hardware_usart2_dma(115200);
    		
    	getMacByLockCode(mac);
    	setSHAR(mac);
    	
    	sysinit(txsize, rxsize);
    	setRTR(2000);
      setRCR(3);
    	
    	//USART DMA problem 2byte missing
    	func_usart2_dma_send_bytes(mac, 2);
    	delay_ms(100);
    	
    	//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);
    	}
    	
    	len = func_pack_httppost_body(buf_cont, "", "", "", "", "");
    	
    //	pack http message		
    	len = func_pack_httppost_head_body(buf_send, "/a/b/c/d/create", remote_ip, port, buf_cont, len);
    	
    //	res = func_httpc_post(0, remote_ip, port, buf_send, len, buf_send, &recv_len, 1000, 5000);
    	res = func_http_post(0, remote_ip, port, buf_send, len, buf_send, &recv_len, 1000);
    	if(res == 0)
    	{
    		func_usart2_dma_send_bytes((u8*)buf_send, recv_len);
    	}
    
    	for(;;)
    	{
    		
    		func_led1_on();
    		delay_ms(1000);
    		func_led1_off();
    		delay_ms(1000);
    		
    	}
    }
    

    测试的结果,解析报文的body,并通过串口打印出来:

    通过16进制转字符串转换一下,看看结果

     

    展开全文
  • 这两天在做STM32 W5500通过HTTP GET请求的方式下载bin文件,以实现OTA在线升级,到网上...1、STM32 W5500的基础配置,使得 电脑端的CMD命令窗口能够PING通W5500,《STM32F103RC驱动W5500入网,并可ping通》。 2、S...

    这两天在做STM32 W5500通过HTTP GET请求的方式下载bin文件,以实现OTA在线升级,到网上查了一圈,发现并没有很多有效的信息和资料。于是我就实现了一下,把思路和实现过程分享出来。

    实现W5500文件下载的几个前提:

    1、STM32 W5500的基础配置,使得 电脑端的CMD命令窗口能够PING通W5500,《STM32F103RC驱动W5500入网,并可ping通》

    2、STM32 W5500的TCP Client收发数据测试没有问题,《STM32F1 W5500 TCP Client 回环测试》

    3、一个可用的文件服务器,文件的URL地址放到浏览器的地址栏后,可以正常下载文件。

    4、对HTTP协议有基本的认识。

    文件的URL地址放到浏览器的地址栏后,通过Wireshark工具,先看看文件下载的过程,都发生可一些什么

    下载请求的header信息,包括以下几个关键信息:

    1、请求方式+接口名称+协议和协议版本(GET /file/FLASH_OPER.bin_1.1.3 HTTP/1.1\r\n)

    2、文件服务器主机IP+端口 (举例:192.168.1.105:8888\r\n)

    3、连接状态(Connection: Keep-Alive\r\n)

    4、请求端名称(User-Agent: W5500\r\n)

    5、请求端接收的编码(Accept-Encoding: gzip,deflate\r\n)

    6、请求头结束标记(\r\n)

    以上是请求的分析,文件服务器返回的信息如下:

    从文件服务器返回来的数据分析,报文和文件内容不是一次性传输的,是流的方式多次传输的。

    返回的报文,包含以下几个关键点:

    1、返回的状态码(HTTP/1.1 200\r\n)

    2、接收范围 字节流(Accept-Ranges: bytes\r\n)

    3、内容长度(Content-Length: 3904\r\n)

    4、头结束标记(\r\n)

    5、字节流Data长度和Content-Length是相等的。

    以上是基于浏览器下载文件的过程分析的,那么STM32 W5500下载文件的过程,模拟浏览器下载文件,从理论上来讲也是会实现的。

    HTTP协议是在TCP的基础上封装的协议,W5500的TCP Client端与服务端简历连接的过程在此不描述。

    STM32 W5500下载文件有几个难点:

    1、解析文件服务器返回的报文,判断返回码是否为200,只有200才代表成功;判断是否为字节流;解析出文件的大小(长度)

    2、文件字节流和返回报文的分割,以及缓存数组的数据反复搬运(毕竟W5500 一次最多可以收2Kbytes 的数据)。

    3、判断文件下载是否完成的依据。

    STM32 W5500请求和接收的过程:

    即发送一次请求报文后,不断接收文件服务器返回的信息,结果是要么接收到文件字节流和 Content-Length的相等,文件下载成功,要么各种原因失败(连接超时,读取超时,返回码不正确,不是字节流等)。

    好像该讲的都讲了,下面给出STM32 W5500 Http GET方式下载文件的代码(我测试下载 4k/13k/67k 左右的文件都可以),例程中打印了 各个分支的log信息,将文件下载的内容通过串口DMA的方式打印出来。(工程可以看我的 基础配置文章下载,再将这个主测试函数替换)

    #ifndef __STM32F10X_H
    #define __STM32F10X_H
    #include "stm32f10x.h"
    #endif
    
    #ifndef __Z_UTIL_TIME_H
    #define __Z_UTIL_TIME_H
    #include "z_util_time.h"
    #endif
    
    #ifndef __Z_HARDWARE_LED_H
    #define __Z_HARDWARE_LED_H
    #include "z_hardware_led.h"
    #endif
    
    #ifndef __Z_HARDWARE_SPI_H
    #define __Z_HARDWARE_SPI_H
    #include "z_hardware_spi.h"
    #endif
    
    #ifndef __W5500_H
    #define __W5500_H
    #include "w5500.h"
    #endif
    
    #ifndef __SOCKET_H
    #define __SOCKET_H
    #include "socket.h"
    #endif
    
    #ifndef __W5500_CONF_H
    #define __W5500_CONF_H
    #include "w5500_conf.h"
    #endif
    
    #ifndef __DHCP_H
    #define __DHCP_H
    #include "dhcp.h"
    #endif
    
    #ifndef __Z_HARDWARE_USART2_H
    #define __Z_HARDWARE_USART2_H
    #include "z_hardware_usart2.h"
    #endif
    
    #include <stdlib.h>
    
    void log_net(char *log);	
    
    void func_pack_http_get_download_header(u8* buff, u16 size_buff, u8* srv_ip, u16 srv_port, char* interface);
    u8 func_http_get_download_file(u8 sockno, u8* srv_ip, u16 srv_port, char* interface, u16 timeout_ms, u8* buff, u16 size_buff);
    u8 func_analysis_http_download_header(u8* buffer, u16 len_buf, u8 *resp_code, u8 *is_stream, u32 *cont_len);
    
    u8 buf[2048];
    int main(void)
    {
    	
    	u8 mac[6]={0, };
    	DHCP_Get dhcp_get;
    	
    	//FIXME input your server ip to download file
    	u8 srv_ip[] = {192, 168, 1, 105};
    	u16 srv_port = 8888;
    	
    	
    	systick_configuration();
    	init_led();
    	init_hardware_usart2_dma(115200);
    	
    	init_system_spi();
    	func_w5500_reset();	
    	
    	getMacByLockCode(mac);
    	setSHAR(mac);
    	
    	sysinit(txsize, rxsize);
    	setRTR(2000);
      setRCR(3);
    	
    	//USART DMA problem: 2 bytes missing
    	func_usart2_dma_send_bytes(mac, 2);
    	delay_ms(100);
    	
    	//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);
    		
    		log_net("0");
    	}
    	
    	memset(buf, 0 , sizeof(buf));
    	func_http_get_download_file(0, srv_ip, srv_port, "/file/FLASH_OPER.bin_1.1.3", 5000, buf, sizeof(buf));
    	
    	for(;;)
    	{
    		func_led1_toggle();
    		delay_ms(500);	
    	}
    }
    
    u8 func_http_get_download_file(u8 sockno, u8* srv_ip, u16 srv_port, char* interface, u16 timeout_ms, u8* buff, u16 size_buff)
    {
    	u16 local_port = 60000, len = 0, cnt = 0;
    	u8 sendok = 0, recv_start = 0;
    	
    	u8 cache[2048];
    	u16 cache_cont_len;
    	u32 cont_len, download_cont_len;
    	
    	func_pack_http_get_download_header(buff, size_buff, srv_ip, srv_port, interface);
    	
    //	setkeepalive(sockno);//auto
    	IINCHIP_WRITE(Sn_KPALVTR(sockno),0x00);//manual
    	
    	memset(cache, 0 , sizeof(cache));
    	cache_cont_len = 0;
    	
    	for(;;)
    	{
    		switch(getSn_SR(sockno))
    		{
    			case SOCK_INIT:
    					connect(sockno, srv_ip, srv_port);
    			break;
    			case SOCK_ESTABLISHED:
    			{
    				if(sendok == 0)
    				{
    					log_net("1");
    					
    					len = strlen((char *)buff);
    					send(sockno, buff, len);
    					sendok ++;
    					if(getSn_IR(sockno) & Sn_IR_CON)   					
    					{
    						setSn_IR(sockno, Sn_IR_CON);
    						break;
    					}
    				}
    				
    				len = getSn_RX_RSR(sockno);
    				if(len > 0)
    				{
    					cnt = 0;
    					
    					memset(buff, 0, size_buff);
    					len = recv(sockno, buff, len);
    					if(recv_start == 0)
    					{
    						u8 res, resp_code, isstream;
    						
    						log_net("2");
    						
    						if(cache_cont_len + len <= sizeof(cache))
    						{
    							log_net("3");
    							memcpy(cache+cache_cont_len, buff, len);
    							cache_cont_len += len;
    							
    							memset(buff, 0, size_buff);
    							len = 0;
    						}
    						else
    						{
    							u32 len_copy;
    							log_net("4");
    							
    							len_copy = sizeof(cache) - cache_cont_len;
    							memcpy(cache+cache_cont_len, buff, len_copy);
    							memcpy(buff, buff + len_copy, len - len_copy);
    							memset(buff + (len - len_copy), 0, size_buff - (len - len_copy));
    							len = len - len_copy;
    							cache_cont_len = sizeof(cache);
    							
    						}							
    						
    						res = func_analysis_http_download_header(cache, cache_cont_len, &resp_code, &isstream, &cont_len);
    						if(res == 0)
    						{
    							if(resp_code != 200 || isstream != 1)//response code 200, must be iostream
    							{
    								log_net("22");
    								return 3;// response not ok
    							}
    							recv_start++;
    							
    							//logic -> file size should be no more than 108 Kbytes
    							if(cont_len > 108*1024)
    							{
    								log_net("23");
    								return 4;
    							}
    							
    							//if download file done
    							{
    								u32 tmp_len;
    								u8* pos_header;
    								pos_header = (u8*)strstr((char*)cache, "\r\n\r\n");
    								//remove header, save file byte to cache
    								tmp_len = cache_cont_len - (pos_header + 4 - cache);
    								memcpy(cache, pos_header + 4, tmp_len);
    								memset(cache + tmp_len, 0 , sizeof(cache) - tmp_len);
    								cache_cont_len = tmp_len;
    								download_cont_len = cache_cont_len;
    								
    								if(len > 0)
    								{
    									if(cache_cont_len + len <= sizeof(cache))
    									{
    										log_net("5");
    										memcpy(cache+cache_cont_len, buff, len);
    										cache_cont_len += len;										
    										download_cont_len += len;
    										
    										memset(buff, 0, size_buff);
    										len = 0;
    									}
    									else
    									{
    										u32 len_copy;
    										log_net("6");
    										
    										len_copy = sizeof(cache) - cache_cont_len;
    										memcpy(cache+cache_cont_len, buff, len_copy);
    										memcpy(buff, buff + len_copy, len - len_copy);
    										memset(buff + (len - len_copy), 0, size_buff - (len - len_copy));
    										len = len - len_copy;
    										cache_cont_len = sizeof(cache);
    										
    										//TODO write to FLASH backup
    										func_usart2_dma_send_bytes(cache, cache_cont_len);
    										memset(cache, 0, cache_cont_len);
    										cache_cont_len = 0;
    										memcpy(cache+cache_cont_len, buff, len);
    										cache_cont_len = len;
    										download_cont_len = sizeof(cache) + cache_cont_len;
    										
    									}
    								}
    								
    								if(download_cont_len == cont_len)// small file download done
    								{
    									log_net("7");
    									func_usart2_dma_send_bytes(cache, cache_cont_len);
    									//TODO write to FLASH backup and record
    									
    									disconnect(sockno);
    									return 0;//download file done
    								}
    								
    							}								
    						}
    					}
    					else
    					{
    						IINCHIP_WRITE(Sn_CR(sockno),Sn_CR_SEND_KEEP);//keep-alive manual
    						
    						//file size is big, write to FALSH several times
    						download_cont_len += len;
    						if(cache_cont_len + len <= sizeof(cache))
    						{
    							log_net("8");
    							memcpy(cache+cache_cont_len, buff, len);
    							cache_cont_len += len;
    							memset(buff, 0, size_buff);
    							len = 0;
    						}
    						else
    						{
    							u32 len_copy;
    							log_net("9");
    							len_copy = sizeof(cache) - cache_cont_len;
    							memcpy(cache+cache_cont_len, buff, len_copy);
    							memcpy(buff, buff + len_copy, len - len_copy);
    							memset(buff + (len - len_copy), 0, size_buff - (len - len_copy));
    							len = len - len_copy;
    							cache_cont_len = sizeof(cache);
    							
    							//TODO write to FLASH backup
    							func_usart2_dma_send_bytes(cache, cache_cont_len);
    							memset(cache, 0, cache_cont_len);
    							cache_cont_len = 0;
    							memcpy(cache+cache_cont_len, buff, len);
    							cache_cont_len = len;
    						}						
    						
    						//if donwload file done
    						if(download_cont_len == cont_len)
    						{
    							log_net("10");
    							//TODO write to FLASH backup and record
    							func_usart2_dma_send_bytes(cache, cache_cont_len);
    							disconnect(sockno);
    							return 0;//download file done
    						}							
    					}
    				}
    			}			
    			break;
    			case SOCK_CLOSE_WAIT:
    					close(sockno);
    					log_net("21");
    					return 2;//read timeout
    			case SOCK_CLOSED:
    					close(sockno);
    					sendok = 0;
    					recv_start = 0;
    					if(local_port > 65400)
    					{
    						local_port = 60000;
    					}
    					socket(sockno, Sn_MR_TCP, local_port++, Sn_MR_ND);
    			break;
    		}
    		
    		cnt ++;
    		if(cnt >= timeout_ms)
    		{
    			log_net("20");
    			return 1;//connect timeout
    		}
    		delay_ms(1);
    	}
    }
    
    u8 func_analysis_http_download_header(u8* buffer, u16 len_buf, u8 *resp_code, u8 *is_stream, u32 *cont_len)
    {
    	*resp_code = 0;
    	*is_stream = 0;
    	*cont_len = 0;
    	if(strstr((char*)buffer, "\r\n\r\n") != NULL)//response header ok
    	{
    		char *p1, *p2;
    		
    		p1 = strstr((char*)buffer, "HTTP/1.1 200");	
    		if(p1 != NULL)// io stream
    		{
    			*resp_code = 200;
    		}		
    		
    		p1 = strstr((char*)buffer, "Accept-Ranges: bytes");	
    		if(p1 != NULL)// io stream
    		{
    			*is_stream = 1;
    		}
    		
    		p1 = strstr((char*)buffer, "Content-Length: ");										
    		if(p1 != NULL)
    		{
    			p2 = strstr(p1, "\r\n");
    			if(p2 != NULL)
    			{
    				char str_len[8] = {0,};
    				memcpy(str_len, p1 + strlen("Content-Length: "), p2 - p1 - strlen("Content-Length: "));
    				*cont_len = atoi(str_len);
    				return 0;
    			}
    		}
    	}
    	return 1;
    }
    
    void log_net(char *log)
    {
    	u8 logsrv_ip[] = {192, 168, 1, 105};
    	socket(2, Sn_MR_UDP, 7890, 0x00);
    	sendto(2, (u8*)log, strlen(log), logsrv_ip, 9876);
    }
    
    void func_pack_http_get_download_header(u8* buff, u16 size_buff, u8* srv_ip, u16 srv_port, char* interface)
    {
    	u8 tmp[64];
    	memset(buff, 0, size_buff);
    	//header
    	memcpy(buff, "GET ", strlen("GET "));
    	strcat((char *)buff, interface);
    	strcat((char *)buff, " HTTP/1.1\r\n");
    	memset(tmp, 0 , sizeof(tmp));
    	sprintf((char*)tmp, "Host: %d.%d.%d.%d:%d\r\n", srv_ip[0], srv_ip[1], srv_ip[2], srv_ip[3], srv_port);
    	strcat((char *)buff, (char*)tmp);
    	strcat((char *)buff, "Connection: Keep-Alive\r\n");
    	strcat((char *)buff, "User-Agent: W5500\r\n");
    	strcat((char *)buff, "Accept-Encoding: gzip,deflate\r\n");
    	strcat((char *)buff, "\r\n");
    }
    

    最后,附上我测试的效果图:

    串口打印的字节数和 Content-Length的长度一致,并和原bin文件做了对比,内容一致。

    展开全文
  • STM32通过W5500实现MQTT客户端的部署 ,对于MQTT的学习具有参考意义
  • STM32 W5500 HTTP Server 微型web服务实现

    千次阅读 热门讨论 2020-04-22 00:09:27
    嵌入式Web服务很常见,比如电脑通过WIFI接入网络,在浏览器地址栏输入 "192.168.1.1",或者其他...STM32 W5500几乎也可以实现上述的功能,但是由于STM32的RAM和FLASH储存大小是有限的,实现一个简单的web服务是没...
  • stm32W5500官方移植好的,只需改里面的spi就行,直接用MyEthe.h即可。可DHCP获取IP。
  • 基于stm32f103c8单片机运行,使用w5500模块开发的MQTT协议,支持接收与发送。下载完程序后,完成是MCU通过SPI2对w5500的读写操作,完成对IP,mac,gateway等的操作, 设置成功的话,会通过串口1把网络参数打印到串口...
  • STM32 W5500 UDP Client 发送数据

    千次阅读 2020-03-31 12:33:47
    STM32F103RC 驱动W5500,使用UDP Client主动向指定IP和端口发数据测试。 1、首先保证STM32驱动驱动W5500入网可ping通,查看文章《STM32F103RC驱动W5500入网,并可ping通》 2、设置W5500发送和接收的缓冲区大小 3...
  • STM32芯片环境下的TCP/IP开发教程,用到 W5500芯片,SPI接口!
  • 通过W5500的网络功能,到文件服务器下载STM32要更新的固件(可执行bin文件),存储到STM32片内FLASH的APP备份区中,以待bootloader拷贝到APP代码执行区,以实现OTA在线升级的功能。 我使用的芯片是STM32F103RCT6,48...
  • 硬件是STM32+W5500 ,使用http通信协议时间iap OTA 空中升级,文档讲的比较详细,也是我见过的比较好以及比较详细的IAP讲解了。我这边顺便说说为什么要用http 通信协议,因为http通讯协议协议头里面有个body 长度...
  • 通过W5500的网络功能,到文件服务器下载STM32要更新的固件(可执行bin文件),存储到STM32片内FLASH的APP备份区中,以待bootloader拷贝到APP代码执行区,以实现OTA在线升级的功能。 我使用的芯片是STM32F103RCT6,48...
  • stm32+W5500

    2015-12-28 10:24:40
    stm32+W5500完整原理图 可以实现嵌入式网关,或者裸机运行Socket通信,为智能家居设计
  • stm32 +w5500+mqtt

    2019-04-01 15:16:18
    stm32 +w5500+mqtt
  • stm32_IAP远程升级程序_STM32+W5500+IAP,现在项目正在使用,基于http的get和post两种模式。
  • MQTT_STM32_W5500

    2016-10-14 22:34:57
    MQTT_STM32_W5500
  • MQTT_STM32_W5500.zip

    2020-02-17 09:40:20
    MQTT_STM32_W5500 基于stm32f10x 的W5500通信源代码。整套代码直接可以用。
  • stm32 + w5500 + MQTT

    热门讨论 2015-08-22 10:40:23
    物联网,stm32利用w5500以太网模块连接服务器,加入了MQTT协议
  • STM32W5500驱动

    2017-12-28 09:16:06
    stm32平台上运行的外w5500驱动,其实官网也有w5500驱动下载,附件可以运行的一个简单程序,w5500类型设置成了TCPclient,使用定时器检测是否有中断出现,并实现断开连接之后自动重连, 但不建议直接集成到项目,有写...
  • stm32+W5500+rfid RC522芯片通讯 stm32基于w5500网络芯片+RC522 RFID芯片 联网刷卡管理
  • stm32-w5500历程.zip

    2019-06-19 11:19:24
    stm32平台的W5500例程,可以给他家参考,方便开发学习。资源共享;
  • STM32+W5500平台的MODBUS协议通讯。利用W5500芯片进行以太网通讯。
  • STM32+w5500 UDP通讯

    2017-08-22 09:45:33
    STM32F103工程,主要包含基于W5500的udp网络通信和简单的数据通信协议以及其CRC校验。
  • stm32_w5500_dhcp http.rar

    2020-07-29 10:42:19
    stm32通过对w5500以太网模块寄存器的读写操作,实现stm32接入以太网的功能,代码里包括通过DHCP自动获取ip的功能
  • stm32_w5500_mqtt.zip

    2020-08-17 19:52:56
    使用STM32F103+W5500作为客户端,来实现发布和订阅阿里云上的消息。 参考官方例程 封装了方便使用的接口出来
  • 文件名大小更新时间W5500_UDP\app.dep351542014-03-11W5500_UDP\app.ewd382672013-12-04W5500_UDP\app.ewp455212013-12-11W5500_UDP\app.eww1572011-10-19W5500_UDP\app.icf13402013-12-04W5500_UDP\Debug\Exe\app....
  • stm32+w5500.rar

    2020-04-02 14:30:41
    stm32F103驱动以太网模块的例程,内容包括串口,spi,以太网协议内容等。适合初学者使用。本例程是以udp为例,包含闭环收发,单端发送,单端接收功能,另外有网络助手和串口助手工具附上。
  • stm32_w5500_loopback.zip

    2019-07-17 10:21:25
    stm32F1通过SPI 接口 驱动 w5500 ,实现SOCKET 对接。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 457
精华内容 182
热门标签
关键字:

stm32w5500