学习日记——ESP8266STA模式下得UDP通信(2020.7.31)

理论知识

关于ESP8266STA模式下得UDP通信得理论知识,我在之前得博客中有写过。
1、有关于WIFI接口API:https://blog.csdn.net/quanqueen/article/details/107143895
2、有关于UDP通信得API:
https://blog.csdn.net/quanqueen/article/details/107144842
3、ESP8266SDKAPI参考手册:
链接:https://pan.baidu.com/s/10f4ggcVaJMziVQZ7h2-SgQ
提取码:664m

例程1(ESP8266在逻辑上做为服务器)

首先此例程和之前设置ESP8266得例程只有细小得区别。
void ICACHE_FLASH_ATTR user_init(void)

{
	uart_init(115200,115200);	// 初始化串口波特率
	os_delay_us(10000);			// 等待串口稳定
	os_printf("\t Project:\t%s\r\n", ProjectName);
	os_printf("\t SDK version:\t%s", system_get_sdk_version())// OLED显示初始化
	OLED_Init();							// OLED初始化
	OLED_ShowString(0,0,"ESP8266 = STA");	// ESP8266模式
	OLED_ShowString(0,2,"IP:");				// ESP8266_IP地址
	OLED_ShowString(0,4,"Remote  = STA");	// 远端主机模式
	OLED_ShowString(0,6,"IP:");				// 远端主机IP地址
	LED_Init_JX();		// LED初始化
	ESP8266_STA_Init_JX();			// ESP8266_STA初始化
	OS_Timer_1_Init_JX(1000,1);		// 1秒定时(重复)
}

调用函数将ESP8266初始化为STA模式。

void ICACHE_FLASH_ATTR ESP8266_STA_Init_JX()
{
	struct station_config STA_Config;	// STA参数结构体
	struct ip_info ST_ESP8266_IP;		// STA信息结构体
	// 设置ESP8266的工作模式
	wifi_set_opmode(0x01);				// 设置为STA模式,并保存到Flash
	/*
	// 设置STA模式下的IP地址【ESP8266默认开启DHCP Client,接入WIFI时会自动分配IP地址】
	wifi_station_dhcpc_stop();						// 关闭 DHCP Client
	IP4_ADDR(&ST_ESP8266_IP.ip,192,168,8,88);		// 配置IP地址
	IP4_ADDR(&ST_ESP8266_IP.gw,192,168,8,1);		// 配置网关地址
	IP4_ADDR(&ST_ESP8266_IP.netmask,255,255,255,0);	// 配置子网掩码
	wifi_set_ip_info(STATION_IF,&ST_ESP8266_IP);	// 设置STA模式下的IP地址
	*///可以选择是否设置静态IP,可以选择自动获取IP地址//
	// 结构体赋值,配置STA模式参数
	os_memset(&STA_Config, 0, sizeof(struct station_config));	// STA参数结构体 = 0
	os_strcpy(STA_Config.ssid,ESP8266_STA_SSID);				// 设置WIFI名
	os_strcpy(STA_Config.password,ESP8266_STA_PASS);			// 设置WIFI密码
	wifi_station_set_config(&STA_Config);	// 设置STA参数,并保存到Flash
	// wifi_station_connect();		// ESP8266连接WIFI
}

初始化ESP8266之后设置1s定时,并且是重复定时。
定时回调函数中,判断ESP8266是否获取IP地址,如果成功获取IP地址,则打印并显示ESP8266得IP地址。之后ESP8266的LED快闪三次,并且关闭定时器。这里与设置ESP为STA模式的例程不一样之从在于。此程序想要我们初始化UDP网络连接(UDP通信)。

void ICACHE_FLASH_ATTR OS_Timer_1_cb(void)
{
	u8 C_LED_Flash = 0;				// LED闪烁计次
	struct ip_info ST_ESP8266_IP;	// ESP8266的IP信息
	u8 ESP8266_IP[4];				// ESP8266的IP地址
	// 成功接入WIFI【STA模式下,如果开启DHCP(默认),则ESO8266的IP地址由WIFI路由器自动分配】
	if( wifi_station_get_connect_status() == STATION_GOT_IP )	// 判断是否获取IP
	{
		wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP);	// 获取STA的IP信息
		ESP8266_IP[0] = ST_ESP8266_IP.ip.addr;			// IP地址高八位 == addr低八位
		ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8;		// IP地址次高八位 == addr次低八位
		ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16;		// IP地址次低八位 == addr次高八位
		ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24;		// IP地址低八位 == addr高八位

		// 显示ESP8266的IP地址
		os_printf("ESP8266_IP = %d.%d.%d.%d\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);
		OLED_ShowIP(24,2,ESP8266_IP);	// OLED显示ESP8266的IP地址
		// 接入WIFI成功后,LED快闪3次
		for(; C_LED_Flash<=5; C_LED_Flash++)
		{
			GPIO_OUTPUT_SET(GPIO_ID_PIN(4),(C_LED_Flash%2));
			delay_ms(100);
		}
		os_timer_disarm(&OS_Timer_1);	// 关闭定时器
		ESP8266_NetCon_Init_JX();		// 初始化网络连接(UDP通信)
	}
}

UDP初始化网络连接。

void ICACHE_FLASH_ATTR ESP8266_NetCon_Init_JX()
{
	// 结构体赋值
	ST_NetCon.type = ESPCONN_UDP;		// 设置通信协议为UDP
	ST_NetCon.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));	// 开辟内存
	// 此处无需设置目标IP/端口(ESP8266作为Server服务器,不需要预先知道Client客户端的IP/端口)只需要设置ESP8266的本地端口号即可
	ST_NetCon.proto.udp->local_port  = 8266 ;	// 设置本地端口
	//ST_NetCon.proto.udp->remote_port = 8888;	// 设置目标端口
	//ST_NetCon.proto.udp->remote_ip[0] = 192;	// 设置目标IP地址
	//ST_NetCon.proto.udp->remote_ip[1] = 168;
	//ST_NetCon.proto.udp->remote_ip[2] = 8;
	//ST_NetCon.proto.udp->remote_ip[3] = 47;

	// 注册回调函数
	espconn_regist_sentcb(&ST_NetCon,ESP8266_WIFI_Send_Cb_JX);	// 注册网络数据发送成功的回调函数
	espconn_regist_recvcb(&ST_NetCon,ESP8266_WIFI_Recv_Cb_JX);	// 注册网络数据接收成功的回调函数
	// 调用UDP初始化API
	//-----------------------------------------------
	espconn_create(&ST_NetCon);		// 初始化DUP通信
}

在成功接收到网络数据的回调函数中,我们依然是根据接收到数据的首字符来控制灯的亮灭。并且串口打印接收到的数据。并且调用API来获取远端主机的信息。OLED显示远端主机的IP地址,并向对方发送应答。
网络数据回调函数

// 成功接收网络数据的回调函数【参数1:网络传输结构体espconn指针、参数2:网络传输数据指针、参数3:数据长度】
void ICACHE_FLASH_ATTR ESP8266_WIFI_Recv_Cb_JX(void * arg, char * pdata, unsigned short len)
{
	struct espconn * T_arg = arg;		// 缓存网络连接结构体指针
	remot_info * P_port_info = NULL;	// 定义远端连接信息指针
	// 根据数据设置LED的亮/灭
	if(pdata[0] == 'k' || pdata[0] == 'K')	LED_ON;			// 首字母为'k'/'K',灯亮
	else if(pdata[0] == 'g' || pdata[0] == 'G')	LED_OFF;	// 首字母为'g'/'G',灯灭
	os_printf("\nESP8266_Receive_Data = %s\n",pdata);		// 串口打印接收到的数据
	// 获取远端信息【UDP通信是无连接的,向远端主机回应时需获取对方的IP/端口信息】
	if(espconn_get_connection_info(T_arg, &P_port_info, 0)==ESPCONN_OK)	// 获取远端信息
	{
		T_arg->proto.udp->remote_port  = P_port_info->remote_port;		// 获取对方端口号
		T_arg->proto.udp->remote_ip[0] = P_port_info->remote_ip[0];		// 获取对方IP地址
		T_arg->proto.udp->remote_ip[1] = P_port_info->remote_ip[1];
		T_arg->proto.udp->remote_ip[2] = P_port_info->remote_ip[2];
		T_arg->proto.udp->remote_ip[3] = P_port_info->remote_ip[3];
		//os_memcpy(T_arg->proto.udp->remote_ip,P_port_info->remote_ip,4);	// 内存拷贝
	}
	OLED_ShowIP(24,6,T_arg->proto.udp->remote_ip);	// 显示远端主机IP地址
	espconn_send(T_arg,"ESP8266_WIFI_Recv_OK",os_strlen("ESP8266_WIFI_Recv_OK"));	// 向对方发送应答
}

现象1

在这里插入图片描述
由串口打印数据可知,ESP8266成功获取到了IP地址192.168.43.130.我们来看一下ESP8266所连接的网络的IP地址192.168.43.125

在这里插入图片描述
由ESP8266OLED可得到其处于STA模式。并且ESP8266得IP地址为192.168.43.130与串口打印得数据一致。为什么没有获得网络得IP地址,是因为远端还没有给ESP8266发送数据所以ESP8266还没有获取IP地址。
在这里插入图片描述
接下来打开网络调试助手新建UDP。我们得网络调试助手做为客户端,ESP8266做为服务器。客户端要主动得向服务器发起通信。我们首先要设置客户端以及服务器得地址。ESP8266得IP地址为192.168.43.130.端口号为8266.
我们首先发送Hello。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
由图中可知,网络调试助手成功向ESP8266发送数据Hello。并且串口助手成功接收并打印,并且发送应答。网络调试助手也成功接收到ESP8266得应答。现在ESP8266也成功在OLED屏上现在了网络得IP地址。由此可得我们的ESP8266在STA模式下的通信正式成功。接下来我们将呈现LED的亮灭功能。我们用网络调试助手发送K。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
由上面图片可得。发送K,ESP8266的LED点亮。接下来我们将LED熄灭。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
由以上的图可知,网络助手成功发送G,ESP8266的LED熄灭。
由以上现象可以说明我们的ESP8266与网络调试助手成功建立UDP通信且在是STA模式下完成的。

例程2(ESP8266在逻辑上做为客户端)

在user_init当中在初始化完成之后调用函数,将ESP8266设置为STA模式,并且配置STA的相关参数。

void ICACHE_FLASH_ATTR user_init(void)
{
	uart_init(115200,115200);	// 初始化串口波特率
	os_delay_us(10000);			// 等待串口稳定
	os_printf("\t Project:\t%s\r\n", ProjectName);
	os_printf("\t SDK version:\t%s", system_get_sdk_version());
	// OLED显示初始化
	OLED_Init();							// OLED初始化
	OLED_ShowString(0,0,"ESP8266 = STA");	// ESP8266模式
	OLED_ShowString(0,2,"IP:");				// ESP8266_IP地址
	OLED_ShowString(0,4,"Remote  = STA");	// 远端主机模式
	OLED_ShowString(0,6,"IP:");				// 远端主机IP地址
	LED_Init_JX();		// LED初始化
	ESP8266_STA_Init_JX();			// ESP8266_STA初始化
	OS_Timer_1_Init_JX(1000,1);		// 1秒定时
}

配置STA的相关参数之后,进行一秒钟的定时,到现在的程序操作和之前的操作都一样。

void ICACHE_FLASH_ATTR ESP8266_STA_Init_JX()
{
	struct station_config STA_Config;	// STA参数结构体
	struct ip_info ST_ESP8266_IP;		// STA信息结构体
	// 设置ESP8266的工作模式
	wifi_set_opmode(0x01);				// 设置为STA模式,并保存到Flash
	/*
	// 设置STA模式下的IP地址【ESP8266默认开启DHCP Client,接入WIFI时会自动分配IP地址】
	wifi_station_dhcpc_stop();						// 关闭 DHCP Client
	IP4_ADDR(&ST_ESP8266_IP.ip,192,168,8,88);		// 配置IP地址
	IP4_ADDR(&ST_ESP8266_IP.gw,192,168,8,1);		// 配置网关地址
	IP4_ADDR(&ST_ESP8266_IP.netmask,255,255,255,0);	// 配置子网掩码
	wifi_set_ip_info(STATION_IF,&ST_ESP8266_IP);	// 设置STA模式下的IP地址
	*/
	// 结构体赋值,配置STA模式参数
	os_memset(&STA_Config, 0, sizeof(struct station_config));	// STA参数结构体 = 0
	os_strcpy(STA_Config.ssid,ESP8266_STA_SSID);				// 设置WIFI名
	os_strcpy(STA_Config.password,ESP8266_STA_PASS);			// 设置WIFI密码
	wifi_station_set_config(&STA_Config);	// 设置STA参数,并保存到Flash
	// wifi_station_connect();		// ESP8266连接WIFI
}

在定时回调函数当中判断是否获取IP地址,如果成功获取IP地址的话,显示ESP8266的IP地址,并且LED快闪三次,之后关闭定时器。之后调用函数来初始化网络连接,是UDP通信。注意ESP8266在逻辑上做为客户端,它必须首先向服务器主动发起通信,他们双方才可以互相通信,定时回调函数程序如下:

void ICACHE_FLASH_ATTR OS_Timer_1_cb(void)
{
	u8 C_LED_Flash = 0;				// LED闪烁计次

	struct ip_info ST_ESP8266_IP;	// ESP8266的IP信息
	u8 ESP8266_IP[4];				// ESP8266的IP地址


	// 成功接入WIFI【STA模式下,如果开启DHCP(默认),则ESO8266的IP地址由WIFI路由器自动分配】
	if( wifi_station_get_connect_status() == STATION_GOT_IP )	// 判断是否获取IP
	{
		wifi_get_ip_info(STATION_IF,&ST_ESP8266_IP);	// 获取STA的IP信息
		ESP8266_IP[0] = ST_ESP8266_IP.ip.addr;			// IP地址高八位 == addr低八位
		ESP8266_IP[1] = ST_ESP8266_IP.ip.addr>>8;		// IP地址次高八位 == addr次低八位
		ESP8266_IP[2] = ST_ESP8266_IP.ip.addr>>16;		// IP地址次低八位 == addr次高八位
		ESP8266_IP[3] = ST_ESP8266_IP.ip.addr>>24;		// IP地址低八位 == addr高八位
		// 显示ESP8266的IP地址
		os_printf("ESP8266_IP = %d.%d.%d.%d\n",ESP8266_IP[0],ESP8266_IP[1],ESP8266_IP[2],ESP8266_IP[3]);
		OLED_ShowIP(24,2,ESP8266_IP);	// OLED显示ESP8266的IP地址
		// 接入WIFI成功后,LED快闪3次
		for(; C_LED_Flash<=5; C_LED_Flash++)
		{
			GPIO_OUTPUT_SET(GPIO_ID_PIN(4),(C_LED_Flash%2));
			delay_ms(100);
		}
		os_timer_disarm(&OS_Timer_1);	// 关闭定时器
		ESP8266_NetCon_Init_JX();		// 初始化网络连接(UDP通信)
	}
}

调用函数初始化网络连接,ESP8266在逻辑上作为客户端,必须首先向服务器发起通信,他们双方才能互相通信。ESP8266必须预先知道服务器的地址和端口号。

初始化网络连接(UDP通信)
void ICACHE_FLASH_ATTR ESP8266_NetCon_Init_JX()
{
	// 结构体赋值
	ST_NetCon.type = ESPCONN_UDP;		// 设置通信协议为UDP
	ST_NetCon.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));	// 开辟内存
	// 此处需要设置目标IP/端口(ESP8266作为Client,需要预先知道Server的IP/端口)
	ST_NetCon.proto.udp->local_port  = 8266 ;	// 设置本地端口
	ST_NetCon.proto.udp->remote_port = 8888;	// 设置目标端口(服务器端口)
	ST_NetCon.proto.udp->remote_ip[0] = 192;	// 设置目标IP地址
	ST_NetCon.proto.udp->remote_ip[1] = 168;
	ST_NetCon.proto.udp->remote_ip[2] = 43;
	ST_NetCon.proto.udp->remote_ip[3] = 125;
	//u8 remote_ip[4] = {192,168,8,47};		// 目标ip地址
	//os_memcpy(ST_NetCon.proto.udp->remote_ip,remote_ip,4);	// 拷贝内存
	// 注册回调函数
	espconn_regist_sentcb(&ST_NetCon,ESP8266_WIFI_Send_Cb_JX);	// 注册网络数据发送成功的回调函数
	espconn_regist_recvcb(&ST_NetCon,ESP8266_WIFI_Recv_Cb_JX);	// 注册网络数据接收成功的回调函数
	// 调用UDP初始化API
	espconn_create(&ST_NetCon);		// 初始化DUP通信
	// 主动向Server发起通信
	espconn_send(&ST_NetCon,"Hello,I am ESP8266",os_strlen("Hello,I am ESP8266"));
}

注意:服务器的IP地址需要设置为热点的地址。
之后注册回调函数:

// 注册回调函数
	espconn_regist_sentcb(&ST_NetCon,ESP8266_WIFI_Send_Cb_JX);	// 注册网络数据发送成功的回调函数
	espconn_regist_recvcb(&ST_NetCon,ESP8266_WIFI_Recv_Cb_JX);	// 注册网络数据接收成功的回调函数

调用UDP初始化API

espconn_create(&ST_NetCon);		// 初始化DUP通信

之后主动向Server发起通信,告诉服务器,发起通信

espconn_send(&ST_NetCon,"Hello,I am ESP8266",os_strlen("Hello,I am ESP8266"));

在成功接收网络数据回调函数中,根据接收到数据的首字符控制灯的亮灭,并且串口打印接收到的数据,之后调用API来获取远端主机的IP地址。

void ICACHE_FLASH_ATTR ESP8266_WIFI_Recv_Cb_JX(void * arg, char * pdata, unsigned short len)
{
	struct espconn * T_arg = arg;		// 缓存网络连接结构体指针
	remot_info * P_port_info = NULL;	// 定义远端连接信息指针
	// 根据数据设置LED的亮/灭
	if(pdata[0] == 'k' || pdata[0] == 'K')	LED_ON;			// 首字母为'k'/'K',灯亮
	else if(pdata[0] == 'g' || pdata[0] == 'G')	LED_OFF;	// 首字母为'g'/'G',灯灭
	os_printf("\nESP8266_Receive_Data = %s\n",pdata);		// 串口打印接收到的数据
	// 获取远端信息【UDP通信是无连接的,向远端主机回应时需获取对方的IP/端口信息】
	if(espconn_get_connection_info(T_arg, &P_port_info, 0)==ESPCONN_OK)	// 获取远端信息
	{
		T_arg->proto.udp->remote_port  = P_port_info->remote_port;		// 获取对方端口号
		T_arg->proto.udp->remote_ip[0] = P_port_info->remote_ip[0];		// 获取对方IP地址
		T_arg->proto.udp->remote_ip[1] = P_port_info->remote_ip[1];
		T_arg->proto.udp->remote_ip[2] = P_port_info->remote_ip[2];
		T_arg->proto.udp->remote_ip[3] = P_port_info->remote_ip[3];
		//os_memcpy(T_arg->proto.udp->remote_ip,P_port_info->remote_ip,4);	// 内存拷贝
	}
	OLED_ShowIP(24,6,T_arg->proto.udp->remote_ip);	// 显示远端主机IP地址
	espconn_send(T_arg,"ESP8266_WIFI_Recv_OK",os_strlen("ESP8266_WIFI_Recv_OK"));	// 向对方发送应答
}

现象2

首先外面需要下载程序,,打开ESP8266,先不要着急的复位8266,因为现在我们的ESP8266做的是客户端,需要先在网络调试助手新建一个UDP通信,将端口号都改好之后启动。
在这里插入图片描述
启动成功之后复位ESP8266则网络调试助手就会接到应答。接下来我们需要更改下面的端口号,改成与ESP8266相对应的端口号,不然无法发送与接收。下面的发送数据失败就是因为我没有修改下面的端口号,修改之后即可实现数据的发送。
在这里插入图片描述
网络调试助手实现与ESP8266的通信之后,串口助手也会有响应的显示。
在这里插入图片描述
网络调试助手会向串口助手发送应答,串口助手也会向网络调试助手发送应答。一开始ESP8266的OLED显示会只有ESP8266的IP地址。
在这里插入图片描述
当网络调试助手与串口调试助手实现通信之后,ESP8266就可以获得主机的IP地址并向串口发送应答。
在这里插入图片描述通过网络调试助手向串口调试助手发送数据,首字母中有K或k则可以是LED点亮,发送G或者g就可以是LED熄灭。
在这里插入图片描述
并且串口调试助手会有相应的显示。
在这里插入图片描述
并且ESP8266也会做出相应的反映。
在这里插入图片描述
通过以上的一系列的现象就可以说明我们的程序调试成功。

参考连接

https://www.bilibili.com/video/BV1dJ411S723?p=37

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热爱生活的fuyao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值