ESP8266入门学习之UDP和TCP通信


关于TCP/IP详细说明可参考《计算机网络(第7版)-谢希仁》

1、UDP通信:ESP8266作为客户端,手机作为服务器

代码

在工程中创建 user_udp.c、 user_udp.h文件


/*
 * user_udp.c
 *
 *  Created on: 2021年2月23日
 *      Author: Administrator
 */

#include "osapi.h"
#include "os_type.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"

#include "user_udp.h"


struct espconn user_udp_espconn;
os_timer_t checkTimer_wifistate;

void ICACHE_FLASH_ATTR
user_udp_sent_cb(void *arg)   //发送
{
	os_printf("\r\n ESP8266发送成功!\r\n");

}

void ICACHE_FLASH_ATTR
user_udp_recv_cb(void *arg,  char *pdata, unsigned short len)
{
	os_printf("接收数据:%s", pdata);

	//每次发送数据确保端口参数不变
	user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));
	user_udp_espconn.type = ESPCONN_UDP;
	user_udp_espconn.proto.udp->local_port = 2000;    //本地端口,即ESP8266的端口
	user_udp_espconn.proto.udp->remote_port = 10500;  //目标端口,即测试手机中调试助手APP的端口
	const char udp_remote_ip[4] = { 192, 168, 1, 107 }; //目标IP地址(广播),即测试手机中调试助手APP的IP地址
	os_memcpy(user_udp_espconn.proto.udp->remote_ip, udp_remote_ip, 4);

	espconn_send((struct espconn *) arg, "ESP8266已经收到数据!", strlen("ESP8266已经收到数据!"));
}

void ICACHE_FLASH_ATTR
Check_WifiState(void)
{

	uint8 getState = wifi_station_get_connect_status();

	//如果状态正确,证明已经连接
	if (getState == STATION_GOT_IP) {

		os_printf("WIFI连接成功!");
		os_timer_disarm(&checkTimer_wifistate);

		wifi_set_broadcast_if(0x01);	 //设置 ESP8266 发送 UDP广播包时,从 station 接口发送
		user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));//分配空间
		user_udp_espconn.type = ESPCONN_UDP;	 		  //设置类型为UDP协议
		user_udp_espconn.proto.udp->local_port = 2000;	  //本地端口,即ESP8266的端口
		user_udp_espconn.proto.udp->remote_port = 10500;  //目标端口,即测试手机中调试助手APP的端口
		const char udp_remote_ip[4] = { 192, 168, 1, 107 };	 	//目标IP地址(广播),即测试手机中调试助手APP的IP地址
		os_memcpy(user_udp_espconn.proto.udp->remote_ip, udp_remote_ip, 4);

		espconn_regist_recvcb(&user_udp_espconn, user_udp_recv_cb);	 		//注册接收回调函数
		espconn_regist_sentcb(&user_udp_espconn, user_udp_sent_cb);	 		//注册发送回调函数
		espconn_create(&user_udp_espconn);	 		  //建立 UDP 传输
		espconn_send(&user_udp_espconn, "ESP8266成功连接服务器", strlen("ESP8266成功连接服务器"));

	}
}

void ICACHE_FLASH_ATTR
udp_client_init(void)   // 在 user_init 函数中调用
{
	wifi_set_opmode(0x01); //设置为STATION模式
	struct station_config stationConf;
	os_strcpy(stationConf.ssid, "TP-LINK_4607");   //测试手机连接的WIFI名
	os_strcpy(stationConf.password, "weijing418"); //测试手机连接的wifi密码

	wifi_station_set_config(&stationConf);	  //设置WiFi station接口配置,并保存到 flash
	wifi_station_connect();	  //连接路由器
	os_timer_disarm(&checkTimer_wifistate);	  //取消定时器定时
	os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,	NULL);	  //设置定时器回调函数
	os_timer_arm(&checkTimer_wifistate, 500, 1);	  //启动定时器,单位:毫秒
}

实验分析

ESP8266串口数据
在这里插入图片描述
手机端数据
在这里插入图片描述
注意:
1、手机端使用的测试软件是“网络助手”,在应用市场可以搜索到
在这里插入图片描述
2、注意程序中要改为自己测试中实际的IP地址和端口号;
3、ESP8266的IP地址是系统自动分配的;

2、UDP通信:ESP8266作为服务器,手机作为客户端

代码

#include "osapi.h"
#include "os_type.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"

#include "user_udp.h"

struct espconn user_udp_espconn;

static void ICACHE_FLASH_ATTR
user_udp_receive_cb(void *arg, char *pdata, unsigned short len)
{
	os_printf("收到数据:%s\r\n", pdata); // %s,用来输出一个字符串
	espconn_send((struct espconn *) arg, "已经收到", strlen("已经收到"));

}
static void ICACHE_FLASH_ATTR
user_udp_send_cb(void *arg)
{
	os_printf("\r\n已发送\r\n");
}
void ICACHE_FLASH_ATTR
user_udp_config(void)
{
	user_udp_espconn.proto.udp = (esp_udp *) os_zalloc(sizeof(esp_udp));  //分配空间
	user_udp_espconn.type = ESPCONN_UDP;  //设置类型为UDP协议
	user_udp_espconn.proto.udp->local_port = 2000;  //本地端口
	user_udp_espconn.proto.udp->remote_port = 10500;  //目标端口

	espconn_regist_recvcb(&user_udp_espconn, user_udp_receive_cb);  //注册接收回调函数
	espconn_regist_sentcb(&user_udp_espconn, user_udp_send_cb);     //注册发送回调函数
	espconn_create(&user_udp_espconn);  //建立UDP传输

}

void ICACHE_FLASH_ATTR
user_wifi_init(void) {
	struct softap_config apConfig;

	wifi_set_opmode(0x02);  //设置为AP模式,并保存到 flash

	apConfig.ssid_len = 10;				        //设置ssid长度
	os_strcpy(apConfig.ssid, "HuaWei");	        //设置ssid名字,此名字是8266发射出来的WIfi
	os_strcpy(apConfig.password, "12345678");	//设置密码
	apConfig.authmode = 3;                      //设置加密模式
	apConfig.beacon_interval = 100;             //信标间隔时槽100 ~ 60000 ms
	apConfig.channel = 1;                       //通道号1 ~ 13
	apConfig.max_connection = 4;                //最大连接数
	apConfig.ssid_hidden = 0;                   //隐藏SSID

	wifi_softap_set_config(&apConfig);		//设置 WiFi soft-AP 接口配置,并保存到 flash
}
void ICACHE_FLASH_ATTR
udp_services_init(void)		//在 user_init 函数中调用
{
	os_printf("\r\n udp_services_init ... \r\n");
	user_wifi_init();
	user_udp_config();
}

测试步骤

手机连接ESP8266的WIFI
在这里插入图片描述

实验分析

ESP8266串口数据
在这里插入图片描述
手机端的网络助手数据
在这里插入图片描述
注意:
手机端没有收到ESP8266反馈的数据“已经收到”,原因?

3、TCP通信:ESP8266作为服务器,手机作为客户端

代码

/*
 * user_tcp.c
 *
 *  Created on: 2021年2月23日
 *      Author: Administrator
 */

#include "osapi.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"
#include "gpio.h"

/*-----------------------TCP test ESP8266 is server----------------------------------------------------------------------------------------*/

struct espconn user_tcp_espconn;
static void ICACHE_FLASH_ATTR
server_recv_cb(void *arg, char *pdata, unsigned short len) {
	os_printf("收到手机发来的数据:%s \r\n", pdata);
	espconn_send((struct espconn *) arg, "ESP8266已经收到数据", strlen("ESP8266已经收到数据"));

}
static void ICACHE_FLASH_ATTR
server_sent_cb(void *arg) {
	os_printf("ESP8266数据发送成功!\r\n");
}
static void ICACHE_FLASH_ATTR
server_discon_cb(void *arg) {
	os_printf("连接已经断开!\r\n");
}

static void ICACHE_FLASH_ATTR
server_listen_cb(void *arg)  //注册 TCP 连接成功建立后的回调函数
{
	struct espconn *pespconn = arg;
	espconn_regist_recvcb(pespconn, server_recv_cb);  //接收
	espconn_regist_sentcb(pespconn, server_sent_cb);  //发送
	espconn_regist_disconcb(pespconn, server_discon_cb);  //断开
}
static void ICACHE_FLASH_ATTR
server_recon_cb(void *arg, sint8 err) //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
{
	os_printf("连接错误,错误代码为:%d \r\n", err); //%d,用来输出十进制整数
}

static void ICACHE_FLASH_ATTR
user_tcp_config(void)
{
	user_tcp_espconn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp)); //分配空间
	user_tcp_espconn.type = ESPCONN_TCP; //设置类型为TCP协议
	user_tcp_espconn.proto.tcp->local_port = 2000; //本地端口,即ESP8266的端口

	espconn_regist_connectcb(&user_tcp_espconn, server_listen_cb); //注册 TCP 连接成功建立后的回调函数
	espconn_regist_reconcb(&user_tcp_espconn, server_recon_cb); //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
	espconn_accept(&user_tcp_espconn); //创建 TCP server,建立侦听
	espconn_regist_time(&user_tcp_espconn, 180, 0); //设置超时断开时间 单位:秒,最大值:7200 秒

}

static void ICACHE_FLASH_ATTR
tcp_wifi_init(void)
{
	struct softap_config apConfig;
	wifi_set_opmode(0x02);    //设置为AP模式,并保存到 flash
	apConfig.ssid_len = 10;						//设置ssid长度
	os_strcpy(apConfig.ssid, "mate40pro");	    //设置wifi名字,注意这个是8266发出来的热点
	os_strcpy(apConfig.password, "12345678");	//设置密码
	apConfig.authmode = 3;                      //设置加密模式
	apConfig.beacon_interval = 100;            //信标间隔时槽100 ~ 60000 ms
	apConfig.channel = 1;                      //通道号1 ~ 13
	apConfig.max_connection = 4;               //最大连接数
	apConfig.ssid_hidden = 0;                  //隐藏SSID

	wifi_softap_set_config(&apConfig);		//设置 WiFi soft-AP 接口配置,并保存到 flash
}

void ICACHE_FLASH_ATTR
tcp_service_init(void)		//在 user_init 函数中调用
{
	tcp_wifi_init();
	user_tcp_config();		
}

操作步骤

手机连接ESP8266的WIFI
在这里插入图片描述

实验分析

ESP8266串口数据
在这里插入图片描述
手机网络助手
在这里插入图片描述

4、TCP通信:ESP8266作为客户端,手机作为服务器

代码

/*
 * user_tcp.c
 *
 *  Created on: 2021年2月23日
 *      Author: Administrator
 */

#include "osapi.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"
#include "gpio.h"

os_timer_t checkTimer_wifistate;
struct espconn user_tcp_conn;

void ICACHE_FLASH_ATTR
user_tcp_sent_cb(void *arg)  //发送
{
	os_printf("ESP8266发送数据成功!\r\n");
}
void ICACHE_FLASH_ATTR
user_tcp_discon_cb(void *arg)  //断开
{
	os_printf("断开连接成功!\r\n");
}
void ICACHE_FLASH_ATTR
user_tcp_recv_cb(void *arg,  //接收
		char *pdata, unsigned short len) {

	os_printf("ESP8266收到数据:%s\r\n", pdata);
	espconn_send((struct espconn *) arg, "ESP8266已经收到数据", strlen("ESP8266已经收到数据"));

}
void ICACHE_FLASH_ATTR
user_tcp_recon_cb(void *arg, sint8 err) //注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
{
	os_printf("连接错误,错误代码为%d\r\n", err);
	espconn_connect((struct espconn *) arg);
}
void ICACHE_FLASH_ATTR
user_tcp_connect_cb(void *arg)  //注册 TCP 连接成功建立后的回调函数
{
	struct espconn *pespconn = arg;
	espconn_regist_recvcb(pespconn, user_tcp_recv_cb);  //注册接收回调函数
	espconn_regist_sentcb(pespconn, user_tcp_sent_cb);  //注册发送回调函数
	espconn_regist_disconcb(pespconn, user_tcp_discon_cb);  //注册断开回调函数
	espconn_sent(pespconn, "ESP8266连接成功", strlen("ESP8266连接成功"));

}

void ICACHE_FLASH_ATTR
my_station_init(struct ip_addr *remote_ip,
		struct ip_addr *local_ip, int remote_port) {
	user_tcp_conn.proto.tcp = (esp_tcp *) os_zalloc(sizeof(esp_tcp));  //分配空间
	user_tcp_conn.type = ESPCONN_TCP;  //设置类型为TCP协议
	os_memcpy(user_tcp_conn.proto.tcp->local_ip, local_ip, 4);
	os_memcpy(user_tcp_conn.proto.tcp->remote_ip, remote_ip, 4);
	user_tcp_conn.proto.tcp->local_port = espconn_port();  //本地端口
	user_tcp_conn.proto.tcp->remote_port = remote_port;  //目标端口
	//注册连接成功回调函数和重新连接回调函数
	espconn_regist_connectcb(&user_tcp_conn, user_tcp_connect_cb);//注册 TCP 连接成功建立后的回调函数
	espconn_regist_reconcb(&user_tcp_conn, user_tcp_recon_cb);//注册 TCP 连接发生异常断开时的回调函数,可以在回调函数中进行重连
	espconn_connect(&user_tcp_conn);
}

void ICACHE_FLASH_ATTR
Check_WifiState(void) {
	uint8 getState;
	getState = wifi_station_get_connect_status();
	//查询 ESP8266 WiFi station 接口连接 AP 的状态
	if (getState == STATION_GOT_IP) {
		os_printf("WIFI连接成功!\r\n");
		os_timer_disarm(&checkTimer_wifistate);
		struct ip_info info;
		const char remote_ip[4] = { 192, 168, 1, 107 };//目标IP地址,必须要先从手机获取,否则连接失败.
		wifi_get_ip_info(STATION_IF, &info);	//查询 WiFi模块的 IP 地址
		my_station_init((struct ip_addr *) remote_ip, &info.ip, 10500);//连接到目标服务器的10500端口
 }
}

void ICACHE_FLASH_ATTR
tcp_client_init(void)	//在 user_init 函数中调用
{

	wifi_set_opmode(0x01);	//设置为STATION模式

	struct station_config stationConf;
	os_strcpy(stationConf.ssid, "TP-LINK_4607");	  //改成你自己的   路由器的用户名
	os_strcpy(stationConf.password, "weijing418"); //改成你自己的   路由器的密码
	wifi_station_set_config(&stationConf);	//设置WiFi station接口配置,并保存到 flash
	wifi_station_connect();	//连接路由器

	os_timer_disarm(&checkTimer_wifistate);	//取消定时器定时
	os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,	NULL);	//设置定时器回调函数
	os_timer_arm(&checkTimer_wifistate, 500, 1);	//启动定时器,单位:毫秒
}

操作步骤

ESP8266和手机连接在同一个WIFI下

实验分析

ESP8266串口数据
在这里插入图片描述
手机网络助手
在这里插入图片描述

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
抱歉,作为AI语言模型,我无法提供代码的功能。但是,我可以为您提供一些ESP8266与Keil5通信的基础知识和方法。 ESP8266是一款基于WiFi的芯片,可以通过串口与MCU进行通信。Keil5是一款嵌入式开发工具,可用于编写和调试MCU的代码。下面是ESP8266与Keil5通信的基础知识和方法: 1. 确定ESP8266的串口通信参数,如波特率、数据位、校验位、停止位等。通常情况下,ESP8266默认的串口通信参数为115200bps、8数据位、无校验位、1停止位。 2. 在Keil5中,需要使用串口库函数来进行ESP8266与MCU之间的通信。常用的串口库函数包括:USART_Init()、USART_SendData()、USART_ReceiveData()等。 3. 在使用串口库函数之前,需要先初始化串口,包括设置波特率、数据位、校验位、停止位等参数。可以使用USART_Init()函数进行初始化。 4. 在使用ESP8266时,需要先发送AT指令来进行初始化和配置,如发送AT+RST指令进行重启,发送AT+CWMODE指令设置WiFi模式等。 5. 在使用ESP8266进行WiFi连接时,需要先发送AT+CWJAP指令进行连接,然后通过AT+CIPSTART指令建立TCPUDP连接,最后通过AT+CIPSEND指令发送数据。 6. 在接收ESP8266返回的数据时,可以使用串口中断方式或轮询方式进行。使用中断方式时,需要先开启串口中断,并在中断处理函数中读取串口接收缓冲区的数据。 7. 在调试ESP8266与MCU之间的通信时,可以使用串口调试助手等软件进行数据的查看和调试。可以将ESP8266返回的数据打印到串口调试助手中进行查看。 希望这些基础知识和方法对您有所帮助。如果您需要更具体的帮助,可以参考ESP8266官方文档和Keil5的使用手册。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值