1. 程序流程图:
  2. 调用AT源码扫描附近ap的函数:
static 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;
    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);
      uart0_sendStr(temp);
      bss_link = bss_link->next.stqe_next;
    }
    at_backOk;
  }
  else
  {
//  	os_sprintf(temp,"err, scan status %d\r\n", status);
//  	uart0_sendStr(temp);
    at_backError;
  }
  specialAtState = TRUE;
  at_state = at_statIdle;
}
  1. 修改代码:(如果扫描结果ok,使LED灯亮,串口输出ap信息,否则关闭LED,输出错误信息)
LOCAL os_timer_t scanAP_timer; //定义一个定时器变量用来储存定时器对象

static void ICACHE_FLASH_ATTR
scan_done(void *arg, STATUS status)
{
  uint8 ssid[33]; //定义了33个无符号字符型的数组,WiFi名字的一个数组 ,(typedef unsigned char  uint8;)
  char temp[128];
  unsigned int i=1;//用来显示扫描出AP的个数
  if (status == OK)
  {
	//定义一个struct bss_info类型数据的指针变量bss_link,并将指针变量arg强制转换为struct bss_info类型的指针

    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_strlen封装 C语言函数,计算字符串长度。返回 字符串长度
      {
        os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
      }
      else
      {
        os_memcpy(ssid, bss_link->ssid, 32);
      }
      os_sprintf(temp,"AP%d:(%d,\"%s\",%d,\""MACSTR"\",%d)\r\n",//字符串格式化命令,把格式化的数据写入某个字符串中(当前一个ap的信息)
    		  	 i, //ap个数
                 bss_link->authmode, ssid, bss_link->rssi,
                 MAC2STR(bss_link->bssid),bss_link->channel);
      uart0_sendStr(temp); //将字符串发送给UART0口
      bss_link = bss_link->next.stqe_next;//下一个ap的信息
      i++;
    }
    GPIO_OUTPUT_SET(GPIO_ID_PIN(2),	0);//打开LED
     os_printf("ok!\r\n");
  }
  else
  {
  	os_sprintf(temp,"err, scan status %d\r\n", status);//显示错误信息
  	uart0_sendStr(temp);
	os_printf("error!\r\n");
	GPIO_OUTPUT_SET(GPIO_ID_PIN(2),	1);//关闭LED
  }
}

4.user_main.c的全部程序

#include "c_types.h" //数据类型定义
#include "user_interface.h"
#include "osapi.h"
#include "gpio.h"
#include "eagle_soc.h"
/*GPIO 相关接口位于 /ESP8266_NONOS_SDK/include/eagle_soc.h & gpio.h。*/
//#include "eagle_soc.h"
//#include "gpio.h"
/*GPIO 相关接口位于 /ESP8266_NONOS_SDK/include/eagle_soc.h & gpio.h。*/
/**************************************************************************
 *        对于 ESP8266_NONOS_SDK_v1.5.2 至 ESP8266_NONOS_SDK_v2.2.1 之间的版
*         本,请在 user_main.c 增加函数 void user_rf_pre_init(void) 和 uint32
*         user_rf_cal_sector_set(void),可参考 IOT_Demo 的 user_main.c。用户可在
*         user_rf_pre_init中配置 RF初始化,RF设置接口为 system_phy_set_rfoption,
*         或者在 Deep-sleep(深度睡眠)前调用 system_deep_sleep_set_option。如果设置为 RF不打
*         开,则 ESP8266 Station 及 SoftAP均无法使用,请勿调用 Wi-Fi 相关接口及网络功
*         能。RF 关闭时,Wi-Fi 射频功能和网络堆栈管理API 均无法使用。
***************************************************************************/
uint32 priv_param_start_sec;
/******************************************************************************
 * FunctionName : user_rf_cal_sector_set <-- 将 RF参数设置存放在 Flash倒数第 5个扇区
 * 功能 :用户自定义 RF_CAL 参数存放在 Flash 的扇区号
 * 注意  : • 用户必须在程序中实现此函数,否则编译链接时会报错。但用户程序无需调用此函数,SDK
 *        底层会调用它,将 RF_CAL 参数保存在用户指定的 Flash 扇区里,这将占用用户参数区的⼀一个扇区。
 *      • SDK 预留的 4个扇区的系统参数区已经使用,因此 RF_CAL 参数需要占用到用户参数区的空
 *        间,由用户通过此函数设置⼀一个可用扇区供 SDK 底层使用。
 *      • 建议整个系统需要初始化时,或需要重新进行RF_CAL 时,烧录 blank.bin 初始化 RF_CAL 参
 *        数区,并烧录 esp_init_data.bin。注意,esp_init_data.bin 至少需要烧录⼀一次。
 * Parameters(参数)   : none
 * Returns(返回)      : rf cal sector(存储 RF_CAL 参数的 Flash 扇区号
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
/*	应用函数在定义时建议添加 ICACHE_FLASH_ATTR 宏,相应程序将存放在 flash 中,被
	调用时才加载到 cache运行。而如果添加了IRAM_ATTR 宏的函数,则会在上电启动
	时就加载到 iRAM(internal ram:内部RAM,指的是集成到SoC内部的RAM)中。*/
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;
            priv_param_start_sec = 0x3C;
            break;
        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            priv_param_start_sec = 0x7C;
            break;
        case FLASH_SIZE_16M_MAP_512_512:
            rf_cal_sec = 512 - 5;
            priv_param_start_sec = 0x7C;
            break;
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            priv_param_start_sec = 0xFC;
            break;
        case FLASH_SIZE_32M_MAP_512_512:
            rf_cal_sec = 1024 - 5;
            priv_param_start_sec = 0x7C;
            break;
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            priv_param_start_sec = 0xFC;
            break;
        case FLASH_SIZE_64M_MAP_1024_1024:
            rf_cal_sec = 2048 - 5;
            priv_param_start_sec = 0xFC;
            break;
        case FLASH_SIZE_128M_MAP_1024_1024:
            rf_cal_sec = 4096 - 5;
            priv_param_start_sec = 0xFC;
            break;
        default:
            rf_cal_sec = 0;
            priv_param_start_sec = 0;
            break;
    }
    return rf_cal_sec;
}
void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}
/******************************************************************************
 * FunctionName : user_init
 * 描述: 是上层程序的入口函数,给用户提供⼀一个初始化接口,用户可在
 * 该函数内增加硬件初始化、网络参数设置、定时器初始化等功能。
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
LOCAL os_timer_t scanAP_timer; //定义一个定时器变量用来储存定时器对象
static void ICACHE_FLASH_ATTR
scan_done(void *arg, STATUS status)
{
  uint8 ssid[33]; //定义了33个无符号字符型的数组,WiFi名字的一个数组 ,(typedef unsigned char  uint8;)
  char temp[128];
  unsigned int i=1;//用来显示扫描出AP的个数
  if (status == OK)
  {
	//定义一个struct bss_info类型数据的指针变量bss_link,并将指针变量arg强制转换为struct bss_info类型的指针

    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_strlen封装 C语言函数,计算字符串长度。返回 字符串长度
      {
        os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid));
      }
      else
      {
        os_memcpy(ssid, bss_link->ssid, 32);
      }
      os_sprintf(temp,"AP%d:(%d,\"%s\",%d,\""MACSTR"\",%d)\r\n",//字符串格式化命令,把格式化的数据写入某个字符串中(当前一个ap的信息)
    		  	 i, //ap个数
                 bss_link->authmode, ssid, bss_link->rssi,
                 MAC2STR(bss_link->bssid),bss_link->channel);
      uart0_sendStr(temp); //将字符串发送给UART0口
      bss_link = bss_link->next.stqe_next;//下一个ap的信息
      i++;
    }
    GPIO_OUTPUT_SET(GPIO_ID_PIN(2),	0);//打开LED
     os_printf("ok!\r\n");
  }
  else
  {
  	os_sprintf(temp,"err, scan status %d\r\n", status);//显示错误信息
  	uart0_sendStr(temp);
	os_printf("error!\r\n");
	GPIO_OUTPUT_SET(GPIO_ID_PIN(2),	1);//关闭LED
  }
}
void scanAP_cb(void){//设置定时器回调函数
	wifi_station_scan(NULL,scan_done);//扫描附近ap的信息//每5s重新扫描附近的ap信息
}
void ICACHE_FLASH_ATTR
init_cb(void){
	wifi_station_disconnect();//关闭ap
//	wifi_station_scan(NULL,scan_done);//扫描附近ap的信息
}
void ICACHE_FLASH_ATTR
user_init(void)
{
	wifi_set_opmode(0x01);//Station 模式
	os_timer_disarm	(&scanAP_timer);//先关闭定时器
	PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U,	FUNC_GPIO2);
	GPIO_OUTPUT_SET(GPIO_ID_PIN(2),	1);//先关闭LED
	os_timer_setfn(&scanAP_timer,(os_timer_func_t *)scanAP_cb,NULL);//设置定时器回调函数
	os_timer_arm(&scanAP_timer,5000,1);//使能毫秒定时器,每5s扫描一次ap
	system_init_done_cb(init_cb);//等到系统完成初始化就扫描,扫描获取所有可用AP的信息
}

esp8266支持spi吗 esp8266s1_esp8266支持spi吗