概述
Soft-AP 模式让 Ai-WB2 变成一个 Wi-Fi 热点(像手机开个人热点一样发出一个 Wi-Fi 信号),手机/电脑等设备可直接连接开发板,常用于设备配网、局域网直连控制。开发板默认 IP(网络里的「门牌号」)为 192.168.169.1,接入设备由板载 DHCP 服务器(自动分配 IP 的小管家)分配 IP。本教程演示开启热点并观察设备接入事件。
用大白话讲:Soft-AP 就是开发板自己「开热点」——它发出一个 Wi-Fi 信号(名字叫 SSID),手机像连家里 Wi-Fi 一样连上它,不用经过路由器就能和开发板通信。开发板给热点设了固定「门牌号」192.168.169.1,谁连进来,板子里的 DHCP 小管家就自动发给它一个 IP。常用于给设备配网、局域网直接控制设备。
本教程基于安信可官方 SDK(Ai-Thinker-Open/Ai-Thinker-WB2,版本
release_bl_iot_sdk_1.6.40)的官方示例applications/wifi/softAP编写,代码可在本地 SDK 中直接找到。
打开终端,进入官方 softAP 示例工程目录:
cd ~/Ai-Thinker-WB2/applications/wifi/softAP
说明:
cd是「进入目录」的命令,进入官方示例工程;后面所有make命令都要在这个目录下执行。
打开 softAP/main.c,修改开头的热点名称(SSID,Wi-Fi 的名字)与密码:
#define AP_SSID "ai-thinker"
#define AP_PWD "12345678"
例如:
#define AP_SSID "WB2-Hotspot"
#define AP_PWD "88888888"
💡 热点密码至少 8 位(WPA2 加密要求,不足 8 位开不了热点);可用手机搜索到热点并连接测试。
打开 softAP/main.c,本步完整代码已移至文末,见:
📜 完整代码 — 位于本页「完整代码」章节,默认折叠,点击展开,与官方示例(
applications/wifi/softAP/softAP/main.c)完全一致。
代码要点:
| 代码 | 作用 |
|---|---|
wifi_mgmr_ap_enable() |
先启用 AP 模式,不启用后面开热点的函数都用不了 |
wifi_mgmr_conf_max_sta(4) |
限制最多 4 台设备接入,防止热点被挤爆 |
wifi_mgmr_ap_start(if, ssid, 0, pwd, 6) |
真正开热点:名字、信道 0(自动)、密码、加密方式 6(WPA2) |
wifi_ap_ip_set(...) |
给热点定「门牌号」IP 192.168.169.1、掩码、网关 |
netif_find("ap1") |
找到热点网卡接口(ap1),改 IP 前必须先找到它 |
CODE_WIFI_ON_AP_STA_ADD |
有设备连上热点的通知,可在这里做业务 |
CODE_WIFI_ON_AP_STA_DEL |
有设备断开热点的通知,可在这里做业务 |
💡 默认网关 IP
192.168.169.1由components/network/lwip_dhcpd/dhcp_server_raw.c第 42 行DHCPD_SERVER_IP宏定义;想换网段(如192.168.4.1)需同步修改该宏与wifi_ap_ip_set参数。
在工程目录执行编译:
make -j8
说明:
make是「编译」命令,把代码变成开发板能运行的固件(烧进开发板的程序);-j8表示用 8 个 CPU 核并行编译,更快。
编译成功后生成固件 build_out/softAP.bin。
开发板保持 USB 连接,确认串口设备号后执行烧录:
make flash p=/dev/ttyUSB0 b=921600
说明:
make flash是「烧录」命令,把编译好的固件下载进开发板;p=后面是串口设备号(Linux 下常为/dev/ttyUSB0,Windows 下是COM3之类,以你电脑实际为准),b=921600是烧录波特率(串口传数据的速度),保持默认即可。
⏳ 烧录过程中按提示长按开发板 EN 键进入下载模式,等待进度条完成即烧录成功。
烧录完成后开发板自动重启运行,打开串口助手(波特率 921600,串口传数据的「语速」,两边必须一致)观察日志:
[OS] Starting TCP/IP Stack...
<<<<<<<<< init wifi done <<<<<<<<<<
<<<<<<<<< startting soft ap <<<<<<<<<<<
<<<<<<<<< startt soft ap OK<<<<<<<<<<<
[softAP]:SSID:ai-thinker,PASSWORD:12345678,IP addr:192.168.169.1
用手机搜索 Wi-Fi,找到热点 ai-thinker 输入密码连接,串口打印:
<<<<<<<<< station connent ap <<<<<<<<<<<
手机断开连接时打印 station disconnet ap。手机浏览器访问 http://192.168.169.1 可访问开发板 Web 服务(需配合 HTTP 服务器 类应用)。
手机连上热点且串口打印 station connent ap 即成功;如果手机搜不到热点,先看串口有没有打印 startt soft ap OK(没有就是热点没启动成功);如果搜得到却连不上,检查密码是否 8 位以上、是否修改后重新烧录了——都见文末 FAQ。
代码执行流程
例程从启动到运行的完整流程如下(图中的循环箭头表示反复执行):
本文 API 汇总
wifi_mgmr_ap_start(if, ssid, channel, pwd, enc)
启动热点(加密方式 6 = WPA2,0 = 开放)。
参数:
if:AP 接口句柄(wifi_mgmr_ap_enable()返回值)ssid:热点名称(官方默认"ai-thinker")channel:信道(1~13)pwd:热点密码(官方默认"12345678"),开放网络传NULLenc:加密方式(6= WPA2,0= 开放)
返回值:成功返回 0;失败返回负值错误码
wifi_mgmr_start_background(conf)
启动 Wi-Fi 管理器(连接/热点/扫描的调度核心)。
参数:
conf:wifi_conf_t结构体指针,可选字段:country_code(国家码,中国用"CN")
返回值:成功返回 0;失败返回负值错误码
netif_find(name)
按名称查找网络接口(热点口为 "ap1")。
参数:
name:网卡名称字符串,可选值:"st1"(station 口)/"ap1"(热点口)
返回值:成功返回 struct netif*;失败返回 NULL
netif_set_ipaddr / netif_set_netmask / netif_set_gw(netif, addr)
设置网卡 IP / 子网掩码 / 网关。
参数:
netif:目标网卡(netif_find返回值)addr:ip4_addr_t指针,用IP4_ADDR宏构造
返回值:无
IP4_ADDR(addr, a, b, c, d)
由 4 段整数构造 IP 地址(网络字节序)。
参数:
addr:输出的ip4_addr_t指针a, b, c, d:IP 四段数值,如192, 168, 169, 1
返回值:无
📌 热点事件码:
CODE_WIFI_ON_AP_STARTED(热点启动成功)/CODE_WIFI_ON_AP_STOPPED(停止)/CODE_WIFI_ON_AP_STA_ADD(设备接入)/CODE_WIFI_ON_AP_STA_DEL(设备离开),定义于hal_wifi.h。
完整代码
以下为 softAP/main.c 完整源码,与官方示例(applications/wifi/softAP/softAP/main.c)完全一致:
📜 点击展开 softAP/main.c 完整代码
/**
* @file main.c
* @author your name (you@domain.com)
* @brief
* @version 0.1
* @date 2022-10-09
*
* @copyright Copyright (c) 2022
*
*/
#include <FreeRTOS.h>
#include <task.h>
#include <stdio.h>
#include <string.h>
#include <aos/yloop.h>
#include <aos/kernel.h>
#include <lwip/tcpip.h>
#include <wifi_mgmr_ext.h>
#include <hal_wifi.h>
#include <lwip/netif.h>
#include <lwip/inet.h>
#include <blog.h>
#define AP_SSID "ai-thinker"
#define AP_PWD "12345678"
#define TAG "softAP"
static wifi_conf_t ap_conf = {
.country_code = "CN",
};
static wifi_interface_t ap_interface;
/**
* @brief wifi_ap_ip_set
* Set the IP address of soft AP
* @param ip_addr IPV4 addr
* @param netmask netmask
* @param gw DNS
*/
static void wifi_ap_ip_set(char* ip_addr, char* netmask, char* gw)
{
struct netif* ap_netif = netif_find("ap1");
int i = 0;
int ap_ipaddr[4] = { 0 };
int ap_netmask[4] = { 255,255,255,0 };
int ap_gw_arry[4] = { 0,0,0,0 };
ap_ipaddr[0] = atoi(strtok(ip_addr, "."));
for (i = 1;i<4;i++) {
ap_ipaddr[i] = atoi(strtok(NULL, "."));
}
if (netmask) {
ap_netmask[0] = atoi(strtok(netmask, "."));
for (i = 1;i<4;i++)
ap_netmask[i] = atoi(strtok(NULL, "."));
}
if (gw) {
ap_gw_arry[0] = atoi(strtok(gw, "."));
for (i = 1;i<4;i++)
ap_gw_arry[i] = atoi(strtok(NULL, "."));
}
if (ap_netif) {
ip_addr_t ap_ip;
ip_addr_t ap_mask;
ip_addr_t ap_gw;
IP4_ADDR(&ap_ip, ap_ipaddr[0], ap_ipaddr[1], ap_ipaddr[2], ap_ipaddr[3]);
IP4_ADDR(&ap_mask, ap_netmask[0], ap_netmask[1], ap_netmask[2], ap_netmask[3]);
IP4_ADDR(&ap_gw, ap_gw_arry[0], ap_gw_arry[1], ap_gw_arry[2], ap_gw_arry[3]);
netif_set_down(ap_netif);
netif_set_ipaddr(ap_netif, &ap_ip);
netif_set_netmask(ap_netif, &ap_mask);
netif_set_gw(ap_netif, &ap_gw);
netif_set_up(ap_netif);
blog_info("[softAP]:SSID:%s,PASSWORD:%s,IP addr:%s", AP_SSID, AP_PWD, ip4addr_ntoa(netif_ip4_addr(ap_netif)));
}
else
blog_info("no find netif ap1 ");
}
/**
* @brief wifi_ap_start
*
*/
static void wifi_ap_start()
{
ap_interface = wifi_mgmr_ap_enable();
wifi_mgmr_conf_max_sta(4);
wifi_mgmr_ap_start(ap_interface, AP_SSID, 0, AP_PWD, 6);
wifi_ap_ip_set("192.168.169.1", "255.255.255.0", "192.168.169.1"); //defaut gateway ip is "192.168.169.1",if you want usb other gateway ip ,please change components/network/lwip_dhcpd/dhcp_server_raw.c:42 DHCPD_SERVER_IP
//for example, gateway ip:"192.168.4.1" , change DHCPD_SERVER_IP to "192.168.4.1" :
//wifi_ap_ip_set("192.168.4.1", "255.255.255.0", "192.168.4.1");
//components/network/lwip_dhcpd/dhcp_server_raw.c:42 #define DHCPD_SERVER_IP "192.168.4.1"
}
static void event_cb_wifi_event(input_event_t* event, void* private_data)
{
switch (event->code) {
case CODE_WIFI_ON_INIT_DONE:
blog_info("<<<<<<<<< init wifi done <<<<<<<<<<");
wifi_mgmr_start_background(&ap_conf);
break;
case CODE_WIFI_ON_MGMR_DONE:
blog_info("<<<<<<<<< startting soft ap <<<<<<<<<<<");
wifi_ap_start();
break;
case CODE_WIFI_ON_AP_STARTED:
blog_info("<<<<<<<<< startt soft ap OK<<<<<<<<<<<");
break;
case CODE_WIFI_ON_AP_STOPPED:
break;
case CODE_WIFI_ON_AP_STA_ADD:
blog_info("<<<<<<<<< station connent ap <<<<<<<<<<<");
break;
case CODE_WIFI_ON_AP_STA_DEL:
blog_info("<<<<<<<<< station disconnet ap <<<<<<<<<<<");
break;
default:
break;
}
}
static void proc_main_entry(void* pvParameters)
{
aos_register_event_filter(EV_WIFI, event_cb_wifi_event, NULL);
hal_wifi_start_firmware_task();
aos_post_event(EV_WIFI, CODE_WIFI_ON_INIT_DONE, 0);
vTaskDelete(NULL);
}
static void system_thread_init()
{
/*nothing here*/
}
void main()
{
system_thread_init();
puts("[OS] Starting TCP/IP Stack...");
tcpip_init(NULL, NULL);
puts("[OS] proc_main_entry task...");
xTaskCreate(proc_main_entry, (char*)"main_entry", 1024, NULL, 15, NULL);
}常见问题与踩坑提示
⚠️ 手机搜索不到热点
原因:热点未启动成功、或手机 Wi-Fi 关闭/5GHz 优先
解决:确认串口打印 startt soft ap OK;手机开启 Wi-Fi 等待几秒重新搜索(热点为 2.4GHz)
⚠️ 连接热点提示密码错误
原因:热点密码不足 8 位(WPA2 要求)或修改代码后未重新烧录
解决:AP_PWD 至少 8 位;修改后重新编译烧录
⚠️ 设备接入但无法获取 IP
原因:DHCP 服务器未运行,或网段与 DHCPD_SERVER_IP 不一致
解决:确认未改动 dhcp_server_raw.c;换网段时同步修改宏与 wifi_ap_ip_set
⚠️ 想同时连接路由器又开热点
原因:官方示例只启用 AP 模式
解决:先 wifi_mgmr_sta_enable() + 连接路由器,再 wifi_mgmr_ap_enable() + wifi_mgmr_ap_start(),SDK 支持 STA+AP 共存
⚠️ 串口找不到设备 / 打不开
原因:USB 转串口驱动未装、权限不足,或数据线只能充电不能传数据
解决:Linux 用 lsusb/dmesg 查看设备,权限不足可 sudo chmod 666 /dev/ttyUSB0;Windows 装驱动后到设备管理器查 COM 口;换一根能传数据的线
⚠️ 烧录一直等待 / 失败
原因:未进入下载模式、波特率不对、或串口号填错
解决:烧录时按提示长按 EN 键进入下载模式;确认 p=/dev/ttyUSB0 换成你实际的串口;换 USB 口或数据线重试
运行自检
手机搜索到热点并连接成功(串口打印 station connent ap),即 Soft-AP 验证通过。
遇到问题?
如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

