记一个惨痛教训,务必记得即时保存文件。(这次不是丢了,而是无法build)。切记,切记,eclipse修改后务必ctrl+s然后clean 然后再build!
1、实验目的
了解SDK开发的STA模式操作方法,熟悉相关API函数。
2、函数解读
1、wifi_get_opmode
可以说讲的十分清楚了, 那我们就来看一下我们模块现在的模式吧。
/*
* user_main.c
*
* Created on: 2018年1月3日
* Author: CLAY
*/
#include "user_main.h"
#include "driver/uart.h" //串口0需要的头文件
void user_init()
{
uint8 wifimode;
uart_init(115200,115200);
wifimode = wifi_get_opmode();
os_printf("\r\n当前模式是 : %d\r\n", wifimode);
}
void user_rf_pre_init(){}
关于”user_main.h”,这个是我自定义的文件在 app/include 中,这样以后需要哪个头文件直接往这里面一扔,然后只需要引用”user_main.h”就行了。。。
编译,有一个错误。关于os_printf
的头文件是在 os_api.h
中。
uart0 和 uart1 学习
曾在番外篇的最后也提到过一点相关的东西。
8266有两个串口,UART0和UART1,UART1在GPIO2相当于TXD1!主要和os_printf从哪里输出有关,但无论哪个,下载程序还是用UART0。
app/driver/uart.c
332行当我加了注释并下载完成程序后,串口显示为:
换成TX1后,
哈哈,,get到一个新技能吧。
相关手册上看到,分享:https://pan.baidu.com/s/1hs7xZTi 密码:yc6y
还有这个,
[Question]: RTS 和 CTS 以前也见过相关的知识点,以后补充上吧。
有一个感觉也会用到的,先记录下先。。
2、wifi_set_mode & wifi_set_mode_current
1->station 模式
2->AP模式
3->STA+AP模式
然后两者比较
测试代码
/*
* user_main.c
*
* Created on: 2018年1月3日
* Author: CLAY
*/
#include "user_main.h"
#include "driver/uart.h" //串口0需要的头文件
void user_init()
{
uint8 opmode;
uart_init(115200,115200);
opmode = wifi_get_opmode();
os_printf("\r\n当前模式是 : %d\r\n", opmode);
wifi_set_opmode_current(0x01);
opmode = wifi_get_opmode();
os_printf("\r\n当前模式为 :%d\r\n", opmode);
}
void user_rf_pre_init(){}
也可以知道,current不保存到flah中。
再来看看另一个
验证是如我所料。
3、wifi_station_scan
获取当前环境中的ap
要特别注意,
不能在user_int中调用,必须在系统初始化完成后,并且station使能的情况下(也就是说处于AP+STA或者STA模式下才能使用)
那么,问题就来了。啥时候初始化完成呢?如何知道初始化是否完成呢?
这就引入了 回调函数 —-
system_init_done_cb
看这个函数。
4、wifi_station_get_connect_status
3、代码展示
上个整套的代码吧,边理解注释边学习上面提到的函数用法!
/*
* user_main.c
*
* Created on: 2018年1月3日
* Author: CLAY
*/
#include "user_main.h"
#include "driver/uart.h" //串口0需要的头文件
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\r\n");
return;
}
else
{
if(count >= 7)
{
os_printf("WIFI Connect Fail\r\n");
return;//if忘了包含return,然后导致不会打印上面这两个。。
}
}
os_timer_arm(&connect_timer,2000,NULL);//重新打开定时器
}
void ICACHE_FLASH_ATTR
scan_done(void *arg, STATUS status)//扫描完成的回调函数 scan_done(这个有意思了,arg是以链表的形式存在的。)
{
uint8 ssid[33];
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); //memset 初始化数组
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("+CWLAP:(%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;
}
os_memcpy(&stationConf.ssid, "6103", 32); //0s_memcpy 内存拷贝函数 32表示拷贝前32个字符
os_memcpy(&stationConf.password, "12346103", 64);
wifi_station_set_config_current(&stationConf);
wifi_station_connect(); //这个函数当上一个函数不是在user_int中调用,在其他地方都需要加上这句connect
os_timer_setfn(&connect_timer,Wifi_conned,NULL); //定时器回调函数(当定时器时间到了该怎么办?进行回调)
os_timer_arm(&connect_timer,2000,NULL); //每隔2s 去检测是否真的连接上。
}
else
{
// os_sprintf(temp,"err, scan status %d\r\n", status);
// uart0_sendStr(temp);
}
}
void to_scan(void)
{
wifi_station_scan(NULL,scan_done);
}
void user_init()
{
uint8 opmode;
uart_init(115200,115200);
wifi_set_opmode(0x03);
opmode = wifi_get_opmode();
os_printf("\r\n当前模式是 : %d\r\n", opmode);
wifi_set_opmode_current(0x01);
opmode = wifi_get_opmode();
os_printf("\r\n当前模式为 :%d\r\n", opmode);
//wifi_set_opmode(STATION_MODE);
system_init_done_cb(to_scan);//初始化完成后的回调函数
}
void user_rf_pre_init(){}
还有我的user_main.h
/*
* user_main.h
*
* Created on: 2018年1月3日
* Author: CLAY
*/
#ifndef APP_INCLUDE_USER_MAIN_H_
#define APP_INCLUDE_USER_MAIN_H_
#include "osapi.h" //os_printf所需要的头文件
#include "user_interface.h"
ETSTimer connect_timer;
#endif /* APP_INCLUDE_USER_MAIN_H_ */
关于上面的程序,其实大部分参考了人家AT的程序。不过不丢人,刚开始学嘛,能变成自己的东西就好!搬运工也只是暂时的!
寻找相关程序路径:
at_init()
-> system_os_task(at_procTask......)
->
zt_cmdprocess
->at_fun
(这个数组,at指定都在这, 找到我们想要参考的,Cwlap) ->at_exeCmcCwlap
->这样就能参考人家的代码了。。。 ->wifi_station_scan
-> scan_done
->
特别是用到链表那一点,又复习了一波链表的知识,嘻嘻。。。
(当时大一学的C的链表记录,哈哈哈)
不行了,2018年1月3日18:36:24。。午饭也没吃。。饿死了。先去吃个饭,回来接着写。嘿嘿嘿。。。
实验总结
1、关于wifi几个常用的数组名
1、auth_mode 加密模式(枚举类型)
2、SSID - WIFI名字
3、rssi - 信号强度单位db
4、bssid MAC地址
5、channel 信道
2、宏 ICACHE_FLASH_ATTR的妙用
其实我们可以在很多函数顶头看到这个宏的,比如,
那么,这个宏到底是啥意思呢?
添加这个宏后,讲存放在 irom中,(其实就是ROM嘛)。CPU仅在调用它们的时候,将它们读到cache中运行。没有添加这个宏的函数,一上电便被加载到iram中(其实就是RAM嘛)。
由于空间受限,定无法将所有函数都放到iram中,因此大部分函数钱都要加上“ICACHE_FLASH_ATTR”这个宏,否则ram挤爆了,就会错误了。
需要注意的
不要在GPIO或者UART中断中调用带有这种宏的函数,否则将引起异常。