经过上次的HelloWorld,我们知道了其实ESP8266其实是里面有个单片机的模块,我的操作其实就是操作里面的单片机,因为是单片机所以里面会有各种内置的外设,而我们的重点是使用WiFi,所以就直接操作WIFI了。
特别需要注意的一个宏:
添加了这个宏的函数就会存放到ROM里面去,CPU仅在调用的时候才将它们读到cache(缓存)中运行,没有添加这个宏的函数将一开始上电就运行在RAM中;由于模块的空间有限,我们无法将所有的代码都一次性加载到RAM中去运行,因此在大部分函数前添加这个特殊的宏。
需要注意的是不要在GPIO或UART中断处理函数中调用带有“ICACHE_FLASH_ATTR”宏的函数,否则将引起异常。
还是在app文件夹下面新建一个user_main.c文件,并写好
然后在入口函数里面写业务逻辑代码。
一、方法一
怎么写呢?没思路的话就看at-firmware固件源码吧,因为at-firmware固件就是接受外面传进来的AT指令来执行的,那么,我们就可以看着它的代码来完成我们的扫描WiFi的功能,AT指令为AT+CWLAP
可以看到“ICACHE_FLASH_ATTR”修饰的功能函数包含了两种任务,接受任务(at_recvTask)和处理任务(at_procTask)
进入处理任务中去。。。。
二、方法二
还可以根据,工作流程来:
//步骤一
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);//等到系统完成初始化就扫描
}
//步骤二
void to_scan(void) {
wifi_station_scan(NULL,scan_done);
}
//步骤三
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;
}
//扫描完成以后就开始连接WiFi了
}
else
{
// os_sprintf(temp,"err, scan status %d\r\n", status);
// uart0_sendStr(temp);
os_printf("%s","Error");
}
}
等到扫描完成以后,就可以设定连接WiFi了,在scan_done()扫描函数中添加如下代码,
//扫描完成以后就开始连接WiFi了
os_memcpy(&stationConf.ssid, "MERCURY_6398", 32);//WiFi名字加入到配置中去
os_memcpy(&stationConf.password, "123456789", 64);//WiFi密码加入到配置中去
wifi_station_set_config_current(&stationConf);//将设置好的配置加入到配置函数中去
wifi_station_connect();//在非user_init()入口函数中连接WiFi,需要调用这个函数
os_timer_setfn(&connect_timer,Wifi_conned,NULL);//调用自己写的WiFi连接函数
os_timer_arm(&connect_timer,2000,NULL);//设置连接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!");
return;
}else{
if(count>=7){
os_printf("Wifi connect fail!");
return;
}
}
os_timer_arm(&connect_timer,2000,NULL);
}
于是就完成了扫描连接的所有功能。
user_main.c的所有代码
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,NULL);
}
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;
}
//扫描完成以后就开始连接WiFi了
os_memcpy(&stationConf.ssid, "MERCURY_6398", 32);
os_memcpy(&stationConf.password, "123456789", 64);
wifi_station_set_config_current(&stationConf);
wifi_station_connect();
os_timer_setfn(&connect_timer,Wifi_conned,NULL);//调用WiFi连接函数
os_timer_arm(&connect_timer,2000,NULL);
}
else
{
// os_sprintf(temp,"err, scan status %d\r\n", status);
// uart0_sendStr(temp);
os_printf("%s","Error");
}
}
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);
}
void user_rf_pre_init(){}
后记:
从其他地方也看到了,扫描ESP8266扫描WiFi的代码,放到这里参考一下:
扫描的套路都是一样的
void ICACHE_FLASH_ATTR
scan_done(void *arg, STATUS status)
{
uint8 ssid[33];
char temp[128];
if (status == OK)
{
struct bss_info *bss_link = (struct bss_info *)arg;
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_printf("(%d,\"%s\",%d,\""MACSTR"\",%d)\r\n",
bss_link->authmode, ssid, bss_link->rssi,
MAC2STR(bss_link->bssid),bss_link->channel);
bss_link = bss_link->next.stqe_next;
}
}
else
{
os_printf("scan fail !!!\r\n");
}
}
void ICACHE_FLASH_ATTR
user_scan(void)
{
if(wifi_get_opmode() == SOFTAP_MODE)
{
os_printf("ap mode can't scan !!!\r\n");
return;
}
wifi_station_scan(NULL,scan_done);
}
void user_init(void)
{
os_printf("SDK version:%s\n", system_get_sdk_version());
//Set softAP + station mode
wifi_set_opmode(STATIONAP_MODE);
// wifi scan has to after system init done.
system_init_done_cb(user_scan);
}
这里就是扫描特定的WiFi名字,然后代码要这样设定:比如要扫描一个为ESP8266的WiFi名字
void ICACHE_FLASH_ATTR
user_scan(void)
{
if(wifi_get_opmode() == SOFTAP_MODE)
{
os_printf("ap mode can't scan !!!\r\n");
return;
}
struct scan_config config;
os_memset(&config, 0, sizeof(config));
config.ssid = "ESP8266";
wifi_station_scan(&config,scan_done);
}