写在前面:
上一篇ESP8266_09---------------AP_UDP_Client介绍了ESP8266设置为AP模式,作为Client,以UDP的方式与野火串口模拟出的server进行通信。
本篇ESP8266要作为server端,与野火串口模拟出的client进行通信。
大致流程:
一、相关的API:
1.设置 WiFi 的工作模式:
bool wifi_set_opmode (uint8 opmode)
//opmode:
//0x01: Station 模式;
//0x02:SoftAP 模式;
//0x03:Station+SoftAP 模式
//返回值:true:成功;false:失败;
2.设置 WiFi SoftAP 模式,并保存到 flash:
bool wifi_softap_set_config(struct softap_config *config)
/*
参数结构体如下:
struct softap_config
{
uint8 ssid[32];//WiFi名称
uint8 password[64]; //密码
uint8 ssid_len; //WiFi名长度
uint8 channel; //通道号1 ~ 13
AUTH_MODE authmode;//加密方,softAP模式不支持AUTH_WEP加密方式。
uint8 ssid_hidden; //是否隐藏 WiFi,默认为 0 不隐藏网络
uint8 max_connection; //最大连接设备数,最大设备数为 4
uint16 beacon_interval;//信标间隔时间,支持 100-60000ms(信标间隔时间即
SSID 广播包发送的间距),默认为 100ms
}
返回值:true:成功;false:失败;
注意:使用此函数前必须设置 ESP8266 为 AP 模式;此函数其实是在内核中
完成的,不会调用立即生效;注意配置的 WiFi 密码不少于 8 位!!!
*/
3.查询 WiFi Station 模式或者 AP 模式的 IP 地址,确认模式是否配置成功:
bool wifi_get_ip_info(uint8 if_index, struct ip_info *info)
/*
uint8 if_index:选择是查询 AP 模式的还是 Station 模式的,0x00:Station 模
式;0x01:AP 模式,我们也可以使用宏,在 SDK 包内定义了两个宏:
#define STATION_IF 0x00
#define SOFTAP_IF 0x01
struct ip_info *info:用于存储获取到的 IP 信息结构体;
返回值:true:成;false:失败。
*/
4. 创建 UDP 通讯 :
sin8 espconn_create(struct espconn *espconn)
/*
参数:struct espconn *espconn 为对应网络连接的结构体,UDP 连接和
TCP 连接共用这一个结构体。
struct espconn {
enum espconn_type type;
//连接类型,可以是 UDP 和 TCP
enum espconn_state state;
//连接状态
union {
esp_tcp *tcp;
esp_udp *udp;
} proto;
//一个共用体,包含了一个 tcp 连接参数结构体和 udp
//连接参数结构体
espconn_recv_callback recv_callback; //接收成功的回调函数
espconn_sent_callback sent_callback; //发送成功的回调函数
uint8 link_cnt;
//连接数量
void *reverse;
//指针变量,可用来存储相关需要的数据
};
返回值:0:成功,其他:失败,返回对应的错误码
ESPCONN_ ARG:未找到参数 espconn 对应的 UDP 连接
ESPCONN_MEM:空间不足
ESPCONN_ ISCONN:连接已经建立
注意:定义的网络结构体必须是全局变量。
例:struct espconn ESPConnect_Struct; //定义网络连接结构体,全局变量
esp_udp udp_Struct;
ESPConnect_Struct.type=ESPCONN_UDP;
ESPConnect_Struct.proto.udp=(esp_udp*)os_malloc(sizeof(esp_udp));
ESPConnect_Struct.proto.udp->local_port=9999;
ESPConnect_Struct.sent_callback=ESP8266_UDP_Sen d_Cb;
ESPConnect_Struct.recv_callback=ESP8266_UDP_Receive_Cb;
espconn_create(&ESPConnect_Struct);
*/
5. 通过无线网络发送数据:
sint8 espconn_send(struct espconn *espconn,uint8 *psent,uint16 length)
/*
struct espconn *espconn:远端网络信息结构体,
uint8 *psent:需要发送的数据内容;
uint16 length:需要发送的数据长度。
例:
espconn_send(&ESPConnect_Struct,"Hello!",os_strlen("Hello!"));
*/
6. 查询某个 TCP 连接或者 UDP 传输的远端信息,此函数一般在接收成功的回调函数中调用。
sint8 espconn_get_connection_info(struct espconn *espconn, remot_info
**pcon_info,uint8 typeflags)
/*
参数:struct espconn *espconn:对应网络连接的结构体
remot_info **pcon_info:连接 client 信息,如 IP 地址,端口号等等,注
意是指针的指针;
uint8 typeflags:0:正常 server,1:SSL server
返回值:0:成功;其他:失败,返回错误码 ESPCONN_ARG:未找到参
数 espconn 对应的 TCP 连接
二、程序的编写:
程序的功能:
将我们的ESP8266设置为AP模式,充当UDP_Server,用野火串口模拟UDP_Client进行通信。
我们直接拷贝软件定时器的工程,然后新建wifi.c和wifi.h文件,然后将他们分别添加到app/driver和app/include/driver下,刷新工程。
!!!为了方便大家理解程序的运行流程,我按照程序的执行流程来粘贴代码
1.我们要先将ESP8266设为AP模式,主函数中调用WIFI_AP_MODE_Init()
//主程序
void ICACHE_FLASH_ATTR user_init(void)
{
uart_init(9600,9600);
os_printf("\r\nESP8266——AP_UDP_TEST\r\n");
WIFI_AP_MODE_Init();//AP模式初始化
OS_Timer_Init(1000,1);//1s,重装载
}
2.设置好AP模式后,我们打开了定时器,每隔1s进入定时器回调函数OS_Timer_1_Cb(),查询AP模式下ESP8266的IP地址,若查到了,即AP模式就设置好了,然后关闭定时器,调用WIFI_UDP_Init()初始化网络连接(UDP通信)。
//软件定时器回调函数
void 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]);
//-----------------------------------------------------------------------------------------------
os_timer_disarm(&os_timer_1); // 关闭定时器
WIFI_UDP_Init(); // 初始化网络连接(UDP通信)
}
}
//UDP通信初始化
void ICACHE_FLASH_ATTR WIFI_UDP_Init(void)
{
ESPConnect_Struct.type=ESPCONN_UDP;//UDP通信
ESPConnect_Struct.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
ESPConnect_Struct.proto.udp->local_port=8266; //本地端口号
espconn_regist_sentcb(&ESPConnect_Struct,ESP8266_UDP_Send_Cb); // 注册网络数据发送成功的回调函数
espconn_regist_recvcb(&ESPConnect_Struct,ESP8266_UDP_Receive_Cb); // 注册网络数据接收成功的回调函数
espconn_create(&ESPConnect_Struct);//创建连接
}
//接收成功回调函数
void ICACHE_FLASH_ATTR ESP8266_UDP_Receive_Cb(void *arg,char *pdata,unsigned short len)
{
struct espconn * pesp_conn=arg;
remot_info *premot=NULL;//远端结构体信息
os_printf("接收到数据:%s",pdata);
if(os_strcmp(pdata,"ledon")==0)
{
LED_ON;
os_printf("LED已打开😀\n");
}
if(os_strcmp(pdata,"ledoff")==0)
{
LED_OFF;
os_printf("LED已打开😔\n");
}
if(espconn_get_connection_info(pesp_conn,&premot,0)==0)//获取远端设备信息
{
pesp_conn->proto.udp->remote_port=premot->remote_port;//端口
pesp_conn->proto.udp->remote_ip[0]=premot->remote_ip[0];//IP
pesp_conn->proto.udp->remote_ip[1]=premot->remote_ip[1];
pesp_conn->proto.udp->remote_ip[2]=premot->remote_ip[2];
pesp_conn->proto.udp->remote_ip[3]=premot->remote_ip[3];
}
espconn_send(pesp_conn,"hello\n",os_strlen("hello\n"));//向远端发送数据
//os_free(premot);//释放内存
}
//发送成功回调函数
void ICACHE_FLASH_ATTR ESP8266_UDP_Send_Cb(void *arg)
{
os_printf("数据已成功发送!\n");
}
3. 我们的电脑要先去连接到ESP8266的热点,然后我们打开串口调试助手,模拟一个UDP_Client,就能进行通信了。
以上就是核心的代码。
(可能会有一些注释不太对,请大家自行理解)
三、串口的配置
我们将代码烧入ESP8266后,电脑连接到ESP8266热点后,去配置串口为:UDP_Client
烧写代码:
连接热点:
配置串口:
打开串口,打印出ESP8266的IP地址,端口号在程序中设置为8266
以上就是本篇文章的全部内容了,如果感觉有帮助的话,欢迎大家订阅点赞😘😘😘