终于开始接触网络了,基础不行,这个摸索了有点久,还好网上资料多,有些细节还是没有怎么吃透。哈哈,开始联网了。
ESP8266有三种模式:
- station模式:0x01
- soft-AP模式:0x02
- soft-AP&station模式:0x03
简单的介绍一下这三个模式:
- station模式
只能连接其他的路由器,不能被其他设备连接(自己可以连别人,别人不能连自己,简称‘攻’)
- soft-AP模式
这个模式可以看做是一个路由器,只能让其他设备连接本模块,自己不能去连其他路由器(别人可以连自己,自己不能连别人,简称‘受’)
- soft-AP&station模式
顾名思义,这个模式即可以连其他设备,也可以被其他设备连,一般用得最多的就是这个模式(自己连别人,别人连自己都ok,这个就不可描述了=_=凸)
连接wifi
根据手册(手册是个好东西呀)总体思路是这样的:
- 将8266设置为soft-AP&station模式,默认是soft-AP模式,有一点要注意一下,不过现在0.9.2以前版本基本没人用了吧。
wifi_set_opmode(0x03);//设置为soft-AP兼station模式
- 用wifi_station_scan获取AP信息,扫描wifi,我这里是扫描所有可用AP信息。
void to_scan(void) {
wifi_station_scan(NULL,scan_done);
}
- 用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配置
- 设置模式为station+soft-AP模式
- 使用wifi_softap_get_config获取当前ap配置
- 更改配置参数ssid和password,8266的wifi名和密码,看个人喜好设。
- 使用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通信
- 设置远程ip为“255.255.255.255”
- 设置远程端口:1234
- 设置本地端口:2333
- 注册接受回调函数
- 注册发送回调函数
- 建立udp通信
- 获取mac地址
- 发数据
配置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) {}
效果演示