esp8266学习笔记(5)——连接wifi、AP、UDP通信

2023-11-12

终于开始接触网络了,基础不行,这个摸索了有点久,还好网上资料多,有些细节还是没有怎么吃透。哈哈,开始联网了。
ESP8266有三种模式:

  • station模式:0x01
  • soft-AP模式:0x02
  • soft-AP&station模式:0x03

简单的介绍一下这三个模式:

  1. station模式
    只能连接其他的路由器,不能被其他设备连接(自己可以连别人,别人不能连自己,简称‘攻’)
  2. soft-AP模式
    这个模式可以看做是一个路由器,只能让其他设备连接本模块,自己不能去连其他路由器(别人可以连自己,自己不能连别人,简称‘受’)
  3. soft-AP&station模式
    顾名思义,这个模式即可以连其他设备,也可以被其他设备连,一般用得最多的就是这个模式(自己连别人,别人连自己都ok,这个就不可描述了=_=凸)

连接wifi

根据手册(手册是个好东西呀)总体思路是这样的:

  1. 将8266设置为soft-AP&station模式,默认是soft-AP模式,有一点要注意一下,不过现在0.9.2以前版本基本没人用了吧。在这里插入图片描述
wifi_set_opmode(0x03);//设置为soft-AP兼station模式
  1. 用wifi_station_scan获取AP信息,扫描wifi,我这里是扫描所有可用AP信息。
    在这里插入图片描述
void to_scan(void)  {
     wifi_station_scan(NULL,scan_done); 
 }
  1. 用wifi_station_connect连接wifi
    在这里插入图片描述
wifi_station_connect();//在非user_init()入口函数中连接WiFi,需要调用这个函数

上代码

// 头文件引用
//==================================================================================
#include "user_config.h"		// 用户配置
#include "driver/uart.h"  		// 串口
#include "c_types.h"			// 变量类
#include "eagle_soc.h"			// GPIO函数、宏定义
#include "ets_sys.h"			// 回调函数
#include "os_type.h"			// os_XXX
#include "osapi.h"  			// os_XXX、软件定时器
#include "user_interface.h" 	// 系统接口、system_param_xxx接口、WIFI、RateContro
#include "pwm.h"
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"
#include "smartconfig.h"
#include "airkiss.h"

//==================================================================================
ETSTimer connect_timer;
void ICACHE_FLASH_ATTR Wifi_conned(void *arg)
{
    static uint8 count = 0;
    uint8 status;
    os_timer_disarm(&connect_timer);
    count++;
    status = wifi_station_get_connect_status();
    if (status == STATION_GOT_IP)
    {
        os_printf("Wifi connect success!");
        return;
    }
    else
    {
        if (count >= 7)
        {
            os_printf("Wifi connect fail!");
            return;
        }
    }
    os_timer_arm(&connect_timer, 2000, false);
}

void ICACHE_FLASH_ATTR scan_done(void *arg, STATUS status)
{
    uint8 ssid[33];
    char temp[128];
    struct station_config stationConf;
    if (status == OK)
    {
        struct bss_info *bss_link = (struct bss_info *)arg;
        bss_link = bss_link->next.stqe_next;

        while (bss_link != NULL)
        {
            os_memset(ssid, 0, 33);
            if (os_strlen(bss_link->ssid) <= 32)
            {
                os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
            }
            else
            {
                os_memcpy(ssid, bss_link->ssid, 32);
            }
            os_sprintf(temp, "+CWLAP:(%d,\"%s\",%d,\"" MACSTR "\",%d)\r\n",
                       bss_link->authmode, ssid, bss_link->rssi,
                       MAC2STR(bss_link->bssid), bss_link->channel);
            os_printf("%s", temp);
            bss_link = bss_link->next.stqe_next;
        }
        //扫描完成以后就开始连接WiFi了
        os_memcpy(&stationConf.ssid, "aaaaa", 32);         //wifi名
        os_memcpy(&stationConf.password, "123456789", 64); //wifi密码
        wifi_station_set_config_current(&stationConf);
        wifi_station_connect();
        os_timer_setfn(&connect_timer, (ETSTimerFunc *)(Wifi_conned), NULL); //调用WiFi连接函数
        os_timer_arm(&connect_timer, 2000, false);
    }
    else
    {
        os_printf("connect error!\n");
    }
}
void to_scan(void) { wifi_station_scan(NULL, scan_done); }

void user_init()
{
    uint8 opmode;
    uart_init(115200, 115200);
    wifi_set_opmode(0x03);              //设置为soft-AP兼station模式
    opmode = wifi_get_opmode_default(); //获取当前工作模式
    os_printf("\r\n当前的工作模式:%d\r\n", opmode);
    system_init_done_cb(to_scan); //注册系统初始化函数,等待系统初始化完成后扫描wifi
}

uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map)
    {
    case FLASH_SIZE_4M_MAP_256_256:
        rf_cal_sec = 128 - 5;
        break;

    case FLASH_SIZE_8M_MAP_512_512:
        rf_cal_sec = 256 - 5;
        break;

    case FLASH_SIZE_16M_MAP_512_512:
    case FLASH_SIZE_16M_MAP_1024_1024:
        rf_cal_sec = 512 - 5;
        break;

    case FLASH_SIZE_32M_MAP_512_512:
    case FLASH_SIZE_32M_MAP_1024_1024:
        rf_cal_sec = 1024 - 5;
        break;

    case FLASH_SIZE_64M_MAP_1024_1024:
        rf_cal_sec = 2048 - 5;
        break;
    case FLASH_SIZE_128M_MAP_1024_1024:
        rf_cal_sec = 4096 - 5;
        break;
    default:
        rf_cal_sec = 0;
        break;
    }

    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR user_rf_pre_init(void) {}

AP配置

  1. 设置模式为station+soft-AP模式
  2. 使用wifi_softap_get_config获取当前ap配置
  3. 更改配置参数ssid和password,8266的wifi名和密码,看个人喜好设。
  4. 使用wifi_softap_set_config设置ap参数
 void ICACHE_FLASH_ATTR user_init(void)
{

    struct softap_config config;
    uint8 opmode;
    uart_init(115200, 115200);
    wifi_set_opmode(0x03); //设置为AP模式
    opmode = wifi_get_opmode_default();
    os_printf("\r\n当前的工作模式:%d\r\n", opmode);

    wifi_softap_get_config(&config);
    os_memcpy(config.ssid, "ESP8266", strlen("ESP8266"));
    os_memcpy(config.password, "12345678", strlen("12345678"));
    config.ssid_len = strlen("ESP8266");
    wifi_softap_set_config(&config);
}

现在就可以搜到“ESP8266”的wifi了。

UDP通信

  1. 设置远程ip为“255.255.255.255”
  2. 设置远程端口:1234
  3. 设置本地端口:2333
  4. 注册接受回调函数
  5. 注册发送回调函数
  6. 建立udp通信
  7. 获取mac地址
  8. 发数据
    配置udp,修改wifi连接的代码即可。
void ICACHE_FLASH_ATTR Wifi_conned(void *arg)
{
    static uint8 count = 0;
    uint8 status;
    os_timer_disarm(&connect_timer);
    count++;
    status = wifi_station_get_connect_status();
    if (status == STATION_GOT_IP)
    {
        os_printf("Wifi connect success!"); //连接WiFi成功

        wifi_set_broadcast_if(STATIONAP_MODE); //设置UDP广播的发送接口station+soft-AP模式发送
        user_udp_espconn.type = ESPCONN_UDP;
        user_udp_espconn.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
        user_udp_espconn.proto.udp->local_port = 2333;//本地端口
        user_udp_espconn.proto.udp->remote_port = 1234;//远程端口

        const char udp_remote_ip[4] = {255, 255, 255, 255}; //用于存放远程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连接
        user_udp_send();                                            //发送出去
        return;
    }
    else
    {
        if (count >= 7)
        {
            os_printf("Wifi connect fail!");
            return;
        }
    }
    os_timer_arm(&connect_timer, 2000, false);
}

配置发送和接收函数

void ICACHE_FLASH_ATTR user_udp_sent_cb(void *arg) //发送回调函数
{
    os_printf("\r\nUDP发送成功!\r\n");
    os_timer_disarm(&test_timer); 
    os_timer_setfn(&test_timer, (ETSTimerFunc *)(user_udp_send), NULL);
    os_timer_arm(&test_timer, 1000, false); //每秒钟发送一次
}

void ICACHE_FLASH_ATTR user_udp_recv_cb(void *arg, char *pdata, unsigned short len) //接收回调函数
{
    os_printf("UDP已经接收数据:%s", pdata); //UDP接收到的数据打印出来
}

注册udp函数,广播本机mac地址

void ICACHE_FLASH_ATTR user_udp_send(void) //UDP发送函数
{
    char yladdr[6];
    char DeviceBuffer[40] = {0};                                              //将获取的MAC地址格式化输出到一个buffer里面
    wifi_get_macaddr(STATION_IF, yladdr);                                     //查询MAC地址
    os_sprintf(DeviceBuffer, "设备地址为" MACSTR "!!!\r\n", MAC2STR(yladdr)); //格式化MAC地址
    espconn_sent(&user_udp_espconn, DeviceBuffer, os_strlen(DeviceBuffer));
}

完整代码

// 头文件引用
//==================================================================================
#include "user_config.h"		// 用户配置
#include "driver/uart.h"  		// 串口
#include "c_types.h"			// 变量类
#include "eagle_soc.h"			// GPIO函数、宏定义
#include "ets_sys.h"			// 回调函数
#include "os_type.h"			// os_XXX
#include "osapi.h"  			// os_XXX、软件定时器
#include "user_interface.h" 	// 系统接口、system_param_xxx接口、WIFI、RateContro
#include "pwm.h"
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"
#include "smartconfig.h"
#include "airkiss.h"

//==================================================================================

struct espconn user_udp_espconn;

ETSTimer connect_timer;
ETSTimer test_timer;
// 毫秒延时函数
//===========================================
void ICACHE_FLASH_ATTR delay_ms(u32 C_time)
{
    for (; C_time > 0; C_time--)
        os_delay_us(1000);
}
//===========================================

void ICACHE_FLASH_ATTR user_udp_send(void) //UDP发送函数
{
    char yladdr[6];
    char DeviceBuffer[40] = {0};                                              //将获取的MAC地址格式化输出到一个buffer里面
    wifi_get_macaddr(STATION_IF, yladdr);                                     //查询MAC地址
    os_sprintf(DeviceBuffer, "设备地址为" MACSTR "!!!\r\n", MAC2STR(yladdr)); //格式化MAC地址
    espconn_sent(&user_udp_espconn, DeviceBuffer, os_strlen(DeviceBuffer));
}

void ICACHE_FLASH_ATTR user_udp_sent_cb(void *arg) //发送回调函数
{
    os_printf("\r\nUDP发送成功!\r\n");
    os_timer_disarm(&test_timer); //定个时发送
    os_timer_setfn(&test_timer, (ETSTimerFunc *)(user_udp_send), NULL);
    os_timer_arm(&test_timer, 1000, false); //定1秒钟发送一次
}

void ICACHE_FLASH_ATTR user_udp_recv_cb(void *arg, char *pdata, unsigned short len) //接收回调函数
{
    os_printf("UDP已经接收数据:%s", pdata); //UDP接收到的数据打印出来
}

void ICACHE_FLASH_ATTR Wifi_conned(void *arg)
{
    static uint8 count = 0;
    uint8 status;
    os_timer_disarm(&connect_timer);
    count++;
    status = wifi_station_get_connect_status();
    if (status == STATION_GOT_IP)
    {
        os_printf("Wifi connect success!"); //连接WiFi成功

        wifi_set_broadcast_if(STATIONAP_MODE); //设置UDP广播的发送接口station+soft-AP模式发送
        user_udp_espconn.type = ESPCONN_UDP;
        user_udp_espconn.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp));
        user_udp_espconn.proto.udp->local_port = 2333;
        user_udp_espconn.proto.udp->remote_port = 1234;

        const char udp_remote_ip[4] = {255, 255, 255, 255}; //用于存放远程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连接
        user_udp_send();                                            //发送出去
        return;
    }
    else
    {
        if (count >= 7)
        {
            os_printf("Wifi connect fail!");
            return;
        }
    }
    os_timer_arm(&connect_timer, 2000, false);
}

void ICACHE_FLASH_ATTR scan_done(void *arg, STATUS status)
{

    uint8 ssid[33];
    char temp[128];
    struct station_config stationConf;
    if (status == OK)
    {
        struct bss_info *bss_link = (struct bss_info *)arg;
        bss_link = bss_link->next.stqe_next; //ignore first

        while (bss_link != NULL)
        {
            os_memset(ssid, 0, 33);
            if (os_strlen(bss_link->ssid) <= 32)
            {
                os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
            }
            else
            {
                os_memcpy(ssid, bss_link->ssid, 32);
            }
            os_sprintf(temp, "+CWLAP:(%d,\"%s\",%d,\"" MACSTR "\",%d)\r\n",
                       bss_link->authmode, ssid, bss_link->rssi,
                       MAC2STR(bss_link->bssid), bss_link->channel);
            os_printf("%s", temp);
            bss_link = bss_link->next.stqe_next;
        }
        os_memcpy(&stationConf.ssid, "aaaaa", 32);
        os_memcpy(&stationConf.password, "12345678", 64);
        wifi_station_set_config_current(&stationConf);
        wifi_station_connect();
        os_timer_setfn(&connect_timer, Wifi_conned, NULL);
        os_timer_arm(&connect_timer, 2000, false);
    }
    else
    {
        os_printf("connect error!\n");
    }
}
void to_scan(void) { wifi_station_scan(NULL, scan_done); }

void ICACHE_FLASH_ATTR user_init(void)
{

    struct softap_config config;
    uint8 opmode;
    uart_init(115200, 115200);
    wifi_set_opmode(0x03); //设置为AP模式
    opmode = wifi_get_opmode_default();
    os_printf("\r\n当前的工作模式:%d\r\n", opmode);

    wifi_softap_get_config(&config);
    os_memcpy(config.ssid, "ESP8266", strlen("ESP8266"));
    os_memcpy(config.password, "123456789", strlen("123456789"));
    config.ssid_len = strlen("ESP8266");
    wifi_softap_set_config(&config);

    system_init_done_cb(to_scan); //扫描WiFi需要系统初始化完成之后
}
//=================================================================================================

/******************************************************************************
 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABCCC
 *                A : rf cal
 *                B : rf init data
 *                C : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map)
    {
    case FLASH_SIZE_4M_MAP_256_256:
        rf_cal_sec = 128 - 5;
        break;

    case FLASH_SIZE_8M_MAP_512_512:
        rf_cal_sec = 256 - 5;
        break;

    case FLASH_SIZE_16M_MAP_512_512:
    case FLASH_SIZE_16M_MAP_1024_1024:
        rf_cal_sec = 512 - 5;
        break;

    case FLASH_SIZE_32M_MAP_512_512:
    case FLASH_SIZE_32M_MAP_1024_1024:
        rf_cal_sec = 1024 - 5;
        break;

    case FLASH_SIZE_64M_MAP_1024_1024:
        rf_cal_sec = 2048 - 5;
        break;
    case FLASH_SIZE_128M_MAP_1024_1024:
        rf_cal_sec = 4096 - 5;
        break;
    default:
        rf_cal_sec = 0;
        break;
    }

    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR user_rf_pre_init(void) {}

效果演示
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

esp8266学习笔记(5)——连接wifi、AP、UDP通信 的相关文章

  • java Excel文件上传 解析入库

    ApiOperation 上传文件 RequestMapping value uploadFile method RequestMethod POST public BusinessResult uploadFile RequestPara
  • 贪心算法之背包问题

    贪心算法之背包问题 背包问题是算法的经典问题 分为部分背包和0 1背包 主要区别如下 部分背包 某件物品是一堆 可以带走其一部分 0 1背包 对于某件物品 要么被带走 选择了它 要么不被带走 没有选择它 不存在只带走一部分的情况 部分背包问

随机推荐

  • Linux下的命令学习--dd命令

    Linux dd 命令用于读取 转换并输出数据 dd 可从标准输入或文件中读取数据 根据指定的格式来转换数据 再输出到文件 设备或标准输出 使用方法 dd if xx of xx bs xx count xx skip xx seek xx
  • AcWing 482. 合唱队形

    N位同学站成一排 音乐老师要请其中的 N K 位同学出列 使得剩下的K位同学排成合唱队形 合唱队形是指这样的一种队形 设K位同学从左到右依次编号为1 2 K 他们的身高分别为T1 T2 TKT1 T2 TK 则他们的身高满足T1 lt
  • c语言中e的n次方怎么打,C语言中N次方怎么打

    满意答案 lawq0364t 2020 05 11 采纳率 52 等级 7 已帮助 2761人 有两个函数可以实现 double pow double x double y double pow10 int p 下面是这两个函数的使用方法
  • Codeium的使用

    官网 CodeiumCodeium offers best in class AI code completion search all for free It supports over 40 languages and integrat
  • 连续型随机变量密度函数与累积密度函数

    1 连续性随机变量的概率密度函数 注意 f x 是非负的可积函数 以及在负无穷到正无穷区间内的累积概率为1 累积概率的取值区间是从负无穷到正无穷 但是概率密度函数的取值并不是从负无穷到正无穷 尤其是在实际问题中 比如说报童模型中的报纸订购量
  • Python异常值预警

    coding utf 8 基于3sigma的异常值检测 import numpy as np import pandas as pd import matplotlib pyplot as plt 导入绘图库 n 3 n sigma cat
  • Hive---分区表和分桶表

    分区表和分桶表区别如下 1 分区使用的是表外字段 需要指定字段类型 分桶使用的是表内字段 已经知道字段类型 不需要再指定 2 分区通过关键字partitioned by partition name string 声明 分桶表通过关键字cl
  • 「硬见小百科」10分钟详细图解MOS管的结构原理

    什么是MOS管 MOS管是金属 metal 氧化物 oxide 半导体 semiconductor 场效应晶体管 或者称是金属 绝缘体 insulator 半导体 MOS管的source和drain是可以对调的 他们都是在P型backgat
  • AndroidSweetSheet类库的使用

    普通的弹框多以dialog的形式弹出 这个类库是以布局的形式弹出来的 以下是作者的源类库中的包定义 SweetSheet class 代码中主要使用的类 在初始化时候需要传入依附的父布局 以后弹出的view就是要加入到这个view中的 Sw
  • 微信小程序wx.getLocation()报错以及解决方法

    问题介绍 使用wx getLocation 来获取当前地理位置的经纬度 主要代码如下 wx getLocation success function res 经度 let lat res longitude 纬度 let lng res l
  • RK3568 GPIO 按键事件响应

    目录 adb shell getevent查看事件 设备树添加事件驱动 cat查看事件详细内容 author daisy skye的博客 CSDN博客 嵌入式 Qt Linux领域博主 adb shell getevent查看事件 130
  • 【Java基础】计算机程序语言发展史

    程序语言发展史 第一代 机器语言 指令以二进制代码形式存在 第二代 汇编语言 使用助记符表示一条机器指令 第三代 高级语言 C Pascal Fortran等面向过程的语言 C 面向过程 面向对象 Java 跨平台的纯面向对象的语言 NET
  • nginx配置文件之“location ~ .*\. (js

    nginx里面的location配置语法 location url 选项参数匹配 表示精准匹配 表示uri以某个常规字符串开头 理解为匹配 url路径即可 nginx不对url做编码 因此请求为 static 20 aa 可以被规则 sta
  • Proteus仿真STM32的课设实例4——stm32简易测频率

    本教程是基于STM32的嵌入式仿真大作业 源文件链接 https pan baidu com s 1fU4isp7UXTtUFHwpt76zzw pwd 9x7t 提取码 9x7t 使用 Proteus 仿真32单片机 实现了可以测量正弦波
  • 不想dto套dto可以这样写

    之前都是要新建个dto文件的 偶然看到别人这样写 简单记录一下 Data public class GdtDailyBalanceContent List
  • 编程教育是孩子计算机启蒙的好伙伴

    网络上关于 少儿编程 的利好资讯铺天盖地 印证着这一行业的欣欣向荣 国际上 很多发达国家早已把编程教育纳入小学课程表 重视儿童学习编程成为教育的主流 格物斯坦小坦克认为 由此看来从小就培养孩子学习编程 真的有必要 其实 大多数家长对编程可能
  • 没有公网IP,怎么实现外网访问内网视频监控

    以海康威视监控为例 先在内网部署好监控系统 通过本地浏览器输入监控设备管理地址 登录管理后台 在管理后台可成功查看摄像头视频画面即内网监控系统搭建成功 找到配置界面查看设备端口信息 记下HTTP访问端口80 默认网址访问端口 及服务数据传输
  • devops

    1 环境准备 使用的虚拟机环境centos7 8 Jenkins 10 21 90 111 k8sMaster 10 21 90 113 k8sNode 10 21 90 114 同步主机时区为亚洲 并同步时间 root linux nod
  • React Hooks的history带参数跳转,并获取参数

    跳转页面带参数 history push pathname admin test query id user id name user name 跳转后获取参数 const query props console log query nam
  • esp8266学习笔记(5)——连接wifi、AP、UDP通信

    终于开始接触网络了 基础不行 这个摸索了有点久 还好网上资料多 有些细节还是没有怎么吃透 哈哈 开始联网了 ESP8266有三种模式 station模式 0x01 soft AP模式 0x02 soft AP station模式 0x03