学习日记——ESP8266AP模式下得UDP通信(2020.7.2)

注意:虽然UDP通信没有服务器和客户端得,在这里逻辑上将8266作为服务器

一、UDP接口

  • espconn_create
    功能:建⽴ UDP 传输。
    注意:请注意设置 remote_ip 和 remote_port 参数,请勿设置为 0。
    函数定义:sin8 espconn_create(struct espconn *espconn)
    参数:struct espconn *espconn:对应⽹络连接的结构体
    返回:
    0:成功
    其它:失败,返回错误码
    • ESPCONN_ARG:未找到参数 espconn 对应的 UDP 连接
    • ESPCONN_MEM:空间不⾜
    • ESPCONN_ISCONN:连接已经建⽴

  • espconn_sendto
    功能:UDP 发包接⼝
    函数定义:sin16 espconn_sendto(struct espconn *espconn, uint8 *psent, uint16 length)
    参数:
    struct espconn *espconn:对应⽹络连接的结构体
    uint8 *psent:待发送的数据
    uint16 length:发送的数据⻓度
    返回:
    0:成功
    其它:失败,返回错误码
    • ESPCONN_ARG:未找到参数 espconn 对应的 UDP 传输
    • ESPCONN_MEM:空间不⾜
    • ESPCONN_IF:UDP 发包失败

  • espconn_igmp_join
    功能:退出多播组
    函数定义:sint8 espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
    参数:
    ip_addr_t *host_ip:主机 IP
    ip_addr_t *multicast_ip:多播组 IP
    返回
    0:成功
    其它:失败,返回错误码 ESPCONN_MEM:空间不⾜

  • espconn_dns_setserver
    功能:设置默认 DNS server
    注意:本接口必须在 ESP8266 DHCP client 关闭 wifi_station_dhcpc_stop 的情况下使⽤。
    函数定义:void espconn_dns_setserver(uint8 numdns, ip_addr_t *dnsserver)
    参数:
    uint8 numdns:DNS server ID,⽀持设置两个 DNS server,ID 分别为 0 和 1
    ip_addr_t *dnsserver:DNS server IP
    返回 ⽆

  • espconn_dns_getserver
    功能:查询 DNS server IP
    函数定义:ip_addr_t espconn_dns_getserver(uint8 numdns)
    参数:uint8 numdns:DNS server ID,⽀持传⼊ 0 或 1
    返回:DNS server IP

二、例程1(8266在逻辑上作为服务器)

  • 首先在user_ init函数中将ESP8266初始化为AP模式,然后执行OS_ Timer_ 1_ Init_ _JX(1000, 1);1秒软件定时。执行完后结束user_ init函数。在定时回调函数当中如下:
void ICACHE_ FLASH_ ATTR OS_ Timer_ 1_ cb(void)
{
	struct ip_ info ST_ _ESP8266_ IP; // IP信息结构体
	u8 ESP8266_ IP[4];//点分十进制形式保存IP
	wifi_ get_ ip_ info (SOFTAP_ IF, &ST_ ESP8266_ IP); //查询AP模式下ESP8266的IP地址
	if(ST_ ESP8266_ IP. ip. addr != 0)// ESP8266成功获取到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地址
os_ timer_ _disarm(&OS_ Timer_ _1); // 关闭定时器
ESP8266 NetCon Init 0: // 初始化网络连接(UDP通信)
}
  • 关闭定时器后,调用ESP8266 NetCon Init 0函数,初始化网络连接,开启UDP通信。
    在调用函数之前,首先要定义一个网络连接结构体
//定义espconn型结构体(网络连接结构体)
struct espponn ST_ NetCon; //注:必须定义为全局变量,内核将会使用此变量(内存)
esp_ udp ST_ UDP; // UDP通信结构体


struct espconn
{
	enum espconn_ type type ;//连接的类型是UDP通信还是TCP通信
	enum espconn_ state state;//网络连接的状态
	union
	{
	esp_ tcp *tcp;
	esp_ udp *udp;
	}proto;//共用体,TCP通信结构体指针或者是UDP通信结构体指针
	espconn_ recv_ cal Iback recv_ callback;//回调函数
	espconn_ sent_ call back sent_ ca I Iback;
	uint8 link_ cnt;连接数量
//UDP结构体
typedef struct_ esp_ _udp
{
	int remote_ port;//远端主机的端口号
	int local_ port;//8266的端口号
	Iuint8 local_ ip[4];//8266的IP地址
	uint8 remote_ ip[4];//远端主机的IP地址
}esp udp:
  • 接下来需要将网络连接结构体赋值,这里需要设置为UDP通信(注意:上面
union
	{
	esp_ tcp *tcp;
	esp_ udp *udp;
	}proto;//

是一个共用体,是TCP结构体指针,或者是UDP结构体指针。仅仅是一个指针,所以我们需要创建一个UDP通信结构体。需要将通信结构体的指针赋值给网络连接结构体中UDP通信结构体指针的成员ST_ NetCon. proto. udp = (esp_ udp_ *)os_ zalloc (sizeof(esp_ udp)); // 申请内存
(void * os_ zalloc(size_ t size)申请一块指定大小(参数决定)的内存,并返回这块内存的首地址。这块内存申请完毕后,就不能分配给其他变量。如果申请内存的操作过多,内存将不够用。使用[os_ free(指针参数) ]来释放这块内存。)

  • 结构体赋值
ST_ NetCon. type = ESPCONN UDP;// 通信协议: UDP
ST_ NetCon. proto. udp = (esp_ udp *)os_ zal loc (s izeof (esp_ _udp)); // 申请内存
ST NetCon. proto. udp- >loca I port= 8266//设置本地端口号
  • 注册回调函数
espconn_ regist_ sentcb (&ST_ NetCon, ESP8266 WIFI Send Cb_ JX); // 注册网络数据发送成功的回调函数
espconn_ regist_ recvcb (&ST_ NetCon, ESP8266 WIFI Recv Cb JX); // 注册网络数据接收成功的回调函数
  • 初始化UDP通信
espconn_ create (&ST_ NetCon); //初始化DUP通信
  • 网络数据成功接收的回调函数
//[参数1:网络传输结构体espconn指针、 参数2:网络传输数据指针、参数3:数据长度】//
void ICACHE_ FLASH ATTR ESP8266_ WIFI_ Recv_ _Cb_ JX(void * arg. char * pdata, Jns i gned 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'|l pdata[0] == 'G') LED_ _0FF;//首字母为'g'/'G',灯灭.
os_ pr intf ("\nESP8266_ Receive_ Data = %s\n", pdata) ;//串口打印接收到的数据
  • 我们虽然可以接收到UDP发来的数据,如果想知道是谁发送的,我们可以调用一下API来调用远端主机的信息
if (espconn get connection info(T_ arg, &P_ port_ info, 0)--ESPCONN 0K) //获取远端信息,参数1是网络连接结构体指针、参数2是远端连接结构体指针的指针、参数3设置为0。
{
	T_ arg ->proto. udp->remote_ port_ = P_ port_ info->remote_ port; // 获取对方端口号
	T_ arg- >proto. udp- >r emote_ 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 0K", os_ str len("ESP8266_ WIFI Recv_ 0K")); // 向对方发送应答,参数1是网络连接结构体指针、参数2是一个字符串、参数3是字符串的长度//
}
  • 成功发送网络函数数据后会调用一个回调函数。成功后发送一个字符串
 void ICACHE_ FLASH_ ATTR ESP8266 WIFI_ Send_ Cb_ JX(void *arg)
 {
	 os_ pr intf ("\nESP8266_ _WIFI_ Send_ _0K\n");
}

以上步骤完成后即可上电调试
网络调试助手做为客户端,ESP8266做为服务器。当客户端发送语句后,,服务器可以接收到,而且可以获取客户端的地址,并且会给客户端一个应答。当客户端发送K时,服务器可以接收K的同时LED点亮。说明以上程序可以是实现。

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

  • 在user_ init章节首先执行初始化
void ICACHE_ FLASH_ ATTR user_ init(void)
{
	uart_ init (115200, 115200) ;//初始化串口波特率
	os_ delay_ us (10000)
	//OLED显示初始化
	OLED Init() ;// OLED初始化
	OLED ShowStr ing (0, 0, "ESP8266 = AP");//ESP8266模式
	OLED_ ShowStr ing(0,2, "IP:");                    //ESP8266 IP地址
	OLED ShowStr ing(0, 4, "Remote = STA"); //远端主机模式
	OLED_ ShowStr ing(0, 6, "IP");                   //远端主机IP地址
	LED Init JX():                                               // LED初始化
	ESP8266_ AP_ Init_ JX() ;                         //初始化ESP8266_ AP模式
	0S_ Timer. 1_ Init_ J030000,0); // 30秒定时(一次)(为给串口助手创建UDP通信,预留通信时间)
}
  • 在定时回调函数当中
// 定时的回调函数(查询ESP8266的IP地址, 并初始化网络连接)
{
	struct ip_ info ST_ ESP8266_ IP; // IP信息结构体
	u8 ESP8266_ IP[4]; // 点分十进制形式保存IP
	wifi_ get_ ip_ info(SOFTAP_ IF, &ST_ _ESP8266_ IP); //查询AP模式下ESP8266的IP地址
	if(ST_ ESP8266_ IP. ip. addr != 0)// ESP8266成功获取到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; //点分十进制P的第三个数<==> addr次高八位
		ESP8266_ IP[3] = ST_ ESP8266_ IP. ip. addr>>24;//点分十进制IP的第四个数<==> addr高八位
		//显示ESP8266的IP地址
		os_ timer_ _disarm(&OS_ Timer_ 1); //关闭定时器
		ESP8266_ NetCon_ Init_ JX() ;//初始化网络连接(UDP通信)
	}
		
		

初始化UDP通信

//初始化网络连接(UDP通信)
void ICACHE FLASH_ ATTR ESP8266 NetCon Init )
{
	//结构体赋值
	ST_ NetCon. type = ESPCONN _UDP;//设置通信协议为UDP
	ST_ NetCon. proto. udp = (esp_ udp *)os_ zalloc (sizeof (esp. _udp)) ;//开辟内存
	//此处需要设置目标IP/端口(ESE8266作为CI ient,需要预先知道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]=4;
	ST_ NetCon. proto. udp- >remote_ ip[3] = 2;
	espconn_ regist_ sentcb (&ST_ NetCon, ESP8266_ WIFI_ Send_ Cb_ JX); // 注册网络数据发送成功的回调函数
	espconn_ regist_ recvcb (&ST_ NetCon, ESP8266_ WIFI_ Recv_ Cb_ JX); // 注册网络数据接收成功的回调函数
	espconn_ create (&ST_ NetCon); //初始化UDP通信
	espconn send(&ST_ NetCon, "Hello, I am ESP8266", os_ strlen("Hello, I am ESP8266")); // 主动向服务器发起通信
}

如果成功接收到网络调试助手发送得数据

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' Il pdata[0] ==_ 'K') LED_ ON;//首字母为'k'/'K',灯亮
	else if (pdata[0] == 'g'|l pdata[0] == 'G') LED_ 0FF ;//首字母为'g'/'G',灯灭
	os_ pr intf ("\nESP8266_ Receive_ Data = %s\n" , pdata) ;//串口打印接收到的数据
	//获取远端信息[UDP通信是无连接的,向远端主机回应时需获取对方的IP/端口信息]
	if (espconn_ get_ connection_ info(T_ arg, &P_ port_ info, 0)==ESPCONN_ _0K) // 获取远端信息
	{
		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];
	}
	OLED_ ShowIP(24, 6, T. _arg- >proto. udp->remote_ ip); // 显示远端主机IP地址
	espconn_ send(T_ arg. "ESP8266 _WIFI_ _Recv_ _0K", os_ str len("ESP8266_ WIFI. _Recv. _0K")); // 向对方发送应答
}
  • 当8266做为客户端的时候,我们需要预先赋值服务器的IP地址和端口号才能主动的向服务器发起通信。

现象

在这里插入图片描述
由串口可得,ESP8266的模式为AP模式,并且IP地址为192.169.4.1.接下来我们将我们的电脑连接到ESP8266创建的WIFI局域网。
在这里插入图片描述
在这里插入图片描述
由此可以看到电脑的IP地址和ESP8266的IP地址
打开网络调试助手,并且新建UDP,这个时候要保持电脑与ESP8266的连接不能断,然后将本地IP设置成电脑的IP地址。将下面的地址设置成ESP8266的IP地址。
在这里插入图片描述
点击发送之后,就可以看到ESP8266会发送应答到网络调试助手。并且ESP266也可以获取到电脑的IP地址。
在这里插入图片描述
发送K可以打开ESP8266的LED灯
在这里插入图片描述
发送G可以关闭LED灯
在这里插入图片描述
并且在串口这些也可以得到打印
在这里插入图片描述

参考链接

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

热爱生活的fuyao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值