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

终于开始接触网络了,基础不行,这个摸索了有点久,还好网上资料多,有些细节还是没有怎么吃透。哈哈,开始联网了。
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以前版本基本没人用了吧。esp8266学习笔记(5)——连接wifi、AP、UDP通信_第1张图片
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) {}

效果演示
esp8266学习笔记(5)——连接wifi、AP、UDP通信_第2张图片

你可能感兴趣的:(esp8266学习笔记)