概念先知道
- STA(Station)模式:开发板像手机一样去连路由器,是几乎所有网络实验的第一步。
- SSID / 密码:Wi-Fi 的名字和密码;只支持 2.4GHz 频段,5GHz 或中文 SSID 建议避免。
- 事件回调:Wi-Fi 固件状态变化时通知应用,例程通过
wifi_event_handler打印各阶段事件。 - GOT_IP:DHCP 分配 IP 成功的事件,只有出现它之后才能进行 TCP/UDP/HTTP/MQTT 通信。
例程功能简介
- 本页对应博流官方 SDK 的 wifi_tcp 例程(
examples/wifi/sta/wifi_tcp)的启动骨架,这是所有 Wi-Fi 例程共用的 STA 初始化流程: - 上电后初始化 shell 与射频参数,启动 lwIP 协议栈(
tcpip_init),再创建 Wi-Fi 固件任务:注册事件回调 → 启动固件(wifi_task_create/fhost_init)→ 收到INIT_DONE后启动 Wi-Fi 管理任务。 - 之后通过串口 shell 输入
wifi_sta_connect <SSID> <密码>连接路由器,串口实时打印CONNECTED→GOT_IP事件日志。
操作步骤
SDK 没有独立的“连接 Wi-Fi”例程,所有网络例程(wifi_tcp / wifi_udp / wifi_http / wifi_mqtt 等)共用同一套 STA 启动骨架。本页以 wifi_tcp 例程为例(前提:已按快速开始(Linux)或快速开始(Windows)搭建好环境):
cd examples/wifi/sta/wifi_tcpAi-M62(BL616)与 Ai-M61(BL618)同属一个系列,统一填写 bl616:
make CHIP=bl616 BOARD=bl616dk按住 BOOT(Ai-M61-32S-Kit 为 IO2)短按 EN/RST 进入下载模式,然后烧录(串口号换成实际值):
make flash CHIP=bl616 COMX=/dev/ttyUSB0串口助手波特率 2000000,等待出现 bouffalolab /> 提示符后输入连接命令(只支持 2.4GHz;密码为空时省略第二个参数):
wifi_sta_connect SSID <密码>连接过程中串口会依次打印 CODE_WIFI_ON_CONNECTED(已连上)和 CODE_WIFI_ON_GOT_IP(已拿到 IP,并打印剩余内存)。出现 GOT_IP 就说明连接成功,可以继续做 TCP/HTTP/MQTT 等实验。断开时打印 CODE_WIFI_ON_DISCONNECT。
代码执行流程
例程调用的 API 介绍
tcpip_init(init_done, arg)
初始化 lwIP 网络协议栈,必须在任何网络操作之前调用。
参数:
init_done:协议栈初始化完成回调,例程为 NULLarg:回调参数,例程为 NULL
返回值:无
async_register_event_filter(EV_WIFI, handler, NULL)
注册 Wi-Fi 事件过滤器,事件发生时回调 wifi_event_handler。
参数:
EV_WIFI:Wi-Fi 事件类别handler:事件回调函数NULL:用户参数
返回值:成功返回 0;失败返回负值错误码
wifi_sta_connect(ssid, password, ...)
shell 命令(由 Wi-Fi 管理组件提供):以 STA 模式连接路由器,与例程事件回调配合使用。
参数:
ssid:Wi-Fi 名称password:Wi-Fi 密码,开放网络可为空
返回值:无(结果通过事件打印)
完整代码
以下为 wifi_tcp/main.c 完整源码,与官方示例(examples/wifi/sta/wifi_tcp)一致,默认折叠,点击展开:
📜 点击展开 wifi_tcp/main.c 完整代码
/****************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include <lwip/tcpip.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include "wifi_mgmr_ext.h"
#ifndef BL602
#include "fhost_api.h"
#include "wifi_mgmr.h"
#endif
#include "bflb_irq.h"
#include "bflb_uart.h"
#include "rfparam_adapter.h"
#include "async_event.h"
#include "mm.h"
#include "board.h"
#include "shell.h"
#define DBG_TAG "MAIN"
#include "log.h"
struct bflb_device_s *gpio;
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
static struct bflb_device_s *uart0;
extern void shell_init_with_task(struct bflb_device_s *shell);
extern void wifi_event_handler(async_input_event_t ev, void *priv);
#ifdef BL602
extern void wifi_task_create(void);
extern int fhost_init(void);
extern int wifi_mgmr_task_start(void);
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Functions
****************************************************************************/
void wifi_start_firmware_task(void *param)
{
LOG_I("Starting wifi ...\r\n");
async_register_event_filter(EV_WIFI, wifi_event_handler, NULL);
wifi_task_create();
LOG_I("Starting fhost ...\r\n");
#ifndef BL602
fhost_init();
#endif
vTaskDelete(NULL);
}
void wifi_event_handler(async_input_event_t ev, void *priv)
{
uint32_t code = ev->code;
switch (code) {
case CODE_WIFI_ON_INIT_DONE: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_INIT_DONE\r\n", __func__);
wifi_mgmr_task_start();
} break;
case CODE_WIFI_ON_MGMR_DONE: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_MGMR_DONE\r\n", __func__);
} break;
case CODE_WIFI_ON_SCAN_DONE: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_SCAN_DONE\r\n", __func__);
wifi_mgmr_sta_scanlist();
} break;
case CODE_WIFI_ON_CONNECTED: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_CONNECTED\r\n", __func__);
void mm_sec_keydump();
mm_sec_keydump();
} break;
case CODE_WIFI_ON_GOT_IP: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_GOT_IP\r\n", __func__);
LOG_I("[SYS] Memory left is %d Bytes\r\n", kfree_size(0));
} break;
case CODE_WIFI_ON_DISCONNECT: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_DISCONNECT\r\n", __func__);
} break;
case CODE_WIFI_ON_AP_STARTED: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STARTED\r\n", __func__);
} break;
case CODE_WIFI_ON_AP_STOPPED: {
LOG_I("[APP] [EVT] %s, CODE_WIFI_ON_AP_STOPPED\r\n", __func__);
} break;
case CODE_WIFI_ON_AP_STA_ADD: {
LOG_I("[APP] [EVT] [AP] [ADD] %lld\r\n", xTaskGetTickCount());
} break;
case CODE_WIFI_ON_AP_STA_DEL: {
LOG_I("[APP] [EVT] [AP] [DEL] %lld\r\n", xTaskGetTickCount());
} break;
default: {
LOG_I("[APP] [EVT] Unknown code %u \r\n", code);
}
}
}
int main(void)
{
board_init();
uart0 = bflb_device_get_by_name("uart0");
shell_init_with_task(uart0);
if (0 != rfparam_init(0, NULL, 0)) {
LOG_I("PHY RF init failed!\r\n");
return 0;
}
LOG_I("PHY RF init success!\r\n");
tcpip_init(NULL, NULL);
xTaskCreate(wifi_start_firmware_task, "wifi init", 1024, NULL, 10, NULL);
vTaskStartScheduler();
while (1) {
}
}FAQ
连不上路由器,串口没有反应?
确认命令格式为 wifi_sta_connect SSID 密码(中间有空格);确认路由器是 2.4GHz、信号正常;确认没有开启 MAC 过滤;最后换一个信道或重启开发板再试。
提示 `PHY RF init failed!`?
射频参数读取失败。检查 Flash 是否为空或烧录不完整,重新烧录完整固件后再试。
只出现 CONNECTED 没有 GOT_IP?
路由器 DHCP 未开启或地址池耗尽。登录路由器开启 DHCP;也可以重启路由器再试。
`wifi_sta_connect` 命令不存在?
确认烧录的是本页指定的 wifi_tcp 例程固件(不是 AT 固件或其他例程),且等待 shell 提示符出现后再输入。
遇到问题?
如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

