1、实验简介

参考网址:https://gitee.com/Lockzhiner-Electronics/lz3863/tree/master/apps/c1_wifi_connect

1.1、实验目的

本实验旨在帮助学习者掌握 OpenHarmony 轻量系统中 WiFi 无线网络 的基本使用方法。通过本实验,你将学会:

  1. 理解 WiFi AP(Access Point,接入点)STA(Station,站点) 两种工作模式;
  2. 在开发板上创建 SoftAP 热点,配置 SSID、密码、加密方式与信道;
  3. 在开发板上以 STA 模式扫描并连接指定热点,通过 DHCP 获取 IP 地址;
  4. 掌握 WiFi 事件回调、扫描、关联与 DHCP 的完整连接流程;
  5. 完成案例代码的编译、烧录与双板联调现象观察。

1.2、实验内容

本案例包含两个独立功能模块,分别编译烧录到两块开发板上联调:

模块 源文件 功能说明
WiFi 热点模块(AP) wifi_connect_example_AP.c 创建名为 HiSpark_AP 的 WiFi 热点,启动 DHCP 服务器
WiFi 连接模块(STA) wifi_connect_example_STA.c 扫描并连接 HiSpark_AP,保持连接 60 秒后自动断开

两个模块共用 wifi_connecter.c 中的底层封装接口,各自通过独立 RTOS 线程运行,互不耦合。

热点(AP)默认配置:

项目 说明
SSID HiSpark_AP
密码 123456789
加密类型 WIFI_SEC_TYPE_PSK(值为 2,WPA/WPA2-PSK)
工作信道 7
AP IP 地址 192.168.43.1
网关地址 192.168.43.2
网络接口 ap0

连接(STA)默认配置:

项目 说明
目标 SSID HiSpark_AP
目标密码 123456789
连接保持时间 60 秒(每秒打印剩余倒计时)
IP 获取方式 DHCP 动态获取
网络接口 wlan0

1.3、实验环境

项目 说明
硬件 两块 LZ3863-星闪开发板、USB 数据线
软件 OpenHarmony v5.1.0 源码、hb 编译工具
调试工具 串口助手(波特率 115200,用于查看日志)
案例路径 applications/sample/wifi-iot/app/c1_wifi_connect/

注意:本实验需要 两块开发板 分别烧录 AP 固件和 STA 固件,才能完成完整的 WiFi 连接联调。


2、基础知识

2.1、WiFi 工作模式

WiFi 设备通常支持以下两种基本工作模式:

模式 英文全称 角色 典型场景
AP 模式 Access Point 接入点(热点) 开发板创建热点,供手机或其他设备连接
STA 模式 Station 无线站点(客户端) 开发板连接路由器或另一块开发板的热点

本实验中:

  • 开发板 A 运行 AP 模块,相当于一个微型路由器;
  • 开发板 B 运行 STA 模块,相当于连接路由器的终端设备。

2.2、SoftAP 与 DHCP 服务

SoftAP(软件接入点) 指通过软件在 WiFi 芯片上模拟 AP 功能,无需额外硬件路由器。本案例 AP 模块调用 wifi_softap_enable() 启动热点,并通过 lwIP 协议栈在 ap0 接口上配置 DHCP 服务器(netifapi_dhcps_start),为连接的 STA 设备自动分配 IP 地址。

AP 侧网络参数:

IP 地址:  192.168.43.1
子网掩码:255.255.255.0
网关:    192.168.43.2

2.3、STA 连接流程

STA 模块的连接过程可分为以下阶段:

启用 STA 模式 → 扫描周围热点 → 匹配目标 SSID → 发起关联连接
    → 等待关联成功 → 启动 DHCP 客户端 → 获取 IP 地址 → 连接完成

各阶段通过 g_wifi_state 状态变量和 WiFi 事件回调函数协同推进。

2.4、WiFi 事件回调机制

STA 连接过程中,驱动通过事件回调通知应用层状态变化。本案例注册了两个回调:

回调函数 触发时机 处理逻辑
wifi_scan_state_changed 扫描完成 打印日志,状态置为 SCAN_DONE
wifi_connection_changed 关联状态变化 连接成功置为 CONNECT_DONE,失败重新初始化
wifi_event_stru wifi_event_cb = {
    .wifi_event_connection_changed = wifi_connection_changed,
    .wifi_event_scan_state_changed = wifi_scan_state_changed,
};

2.5、软件调用层次

本案例的软件调用层次如下:

应用层(wifi_connect_example_AP.c / wifi_connect_example_STA.c)
    ├── StartHotspot()              ← AP 模块:启动热点
    ├── ConnectToHotspot()          ← STA 模块:连接热点
    └── DisconnectWithHotspot()     ← STA 模块:断开连接
            │
封装层(wifi_connecter.c)
    ├── wifi_softap_enable()        ← 启动 SoftAP
    ├── wifi_sta_enable/scan/connect() ← STA 扫描与连接
    ├── wifi_register_event_cb()    ← 注册事件回调
    └── netifapi_dhcp_start/stop()  ← DHCP 客户端/服务器
            │
协议栈 / 驱动层
    ├── lwIP 网络协议栈
    └── WiFi 驱动(HMAC/DMAC)

2.6、核心 API 介绍

2.6.1、头文件
#include <stdio.h>
#include <string.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_device.h"
#include "wifi_connecter.h"
2.6.2、应用层封装 API
API 名称 功能说明
StartHotspot(ssid, key, secType, channel) 启动 WiFi 热点,返回 ERRCODE_SUCC 表示成功
ConnectToHotspot(ssid, password) 扫描并连接指定热点,完成 DHCP 获取 IP
DisconnectWithHotspot() 停止 DHCP 并断开当前 WiFi 连接
2.6.3、WiFi 驱动 API
API 名称 功能说明
wifi_softap_enable(&hapd_conf) 启用 SoftAP,传入热点配置结构体
wifi_softap_disable() 关闭 SoftAP
wifi_sta_enable() 启用 STA 模式
wifi_sta_scan() 发起周围热点扫描
wifi_sta_get_scan_info() 获取扫描结果列表
wifi_sta_connect(&config) 连接指定热点
wifi_sta_disconnect() 断开当前连接
wifi_sta_get_ap_info() 获取当前连接状态信息
wifi_register_event_cb(&event_cb) 注册 WiFi 事件回调
2.6.4、网络协议栈 API
API 名称 功能说明
netif_find(ifname) 按接口名查找网络接口(如 ap0wlan0
netifapi_netif_set_addr() 设置接口 IP、掩码、网关
netifapi_dhcps_start() 启动 DHCP 服务器(AP 侧)
netifapi_dhcp_start() 启动 DHCP 客户端(STA 侧)
netifapi_dhcp_is_bound() 查询 DHCP 是否已绑定
netifapi_dhcp_stop() 停止 DHCP 客户端
2.6.5、线程与系统入口 API
API 名称 功能说明
osThreadNew(func, arg, &attr) 创建 RTOS 线程
osDelay(ticks) 线程延时,100 ticks ≈ 1 秒(tick = 10 ms)
SYS_RUN(func) 注册系统启动入口函数,上电后自动执行

3、程序设计

3.1、程序架构

本案例目录结构

c1_wifi_connect/
├── wifi_connect_example_AP.c   # AP 热点示例(烧录到开发板 A)
├── wifi_connect_example_STA.c  # STA 连接示例(烧录到开发板 B)
├── wifi_connecter.c            # WiFi 连接/热点封装实现
├── wifi_connecter.h            # 封装接口头文件
├── BUILD.gn                    # GN 编译配置
├── README_zh.md                # 案例简要说明
└── 实验手册.md                  # 本实验手册

AP 模块执行流程:

系统启动
    │
    ▼
WifiHotspotDemo()               ← SYS_RUN 注册,系统启动时自动执行
    │
    ▼
osThreadNew(WifiHotspotTask)    ← 创建热点任务线程
    │
    ▼
WifiHotspotTask()
    └── StartHotspot()          ← 配置并启动 SoftAP + DHCP 服务器
            ├── wifi_softap_enable()
            ├── netifapi_netif_set_addr()
            └── netifapi_dhcps_start()

STA 模块执行流程:

系统启动
    │
    ▼
WifiConnectDemo()               ← SYS_RUN 注册,系统启动时自动执行
    │
    ▼
osThreadNew(WifiConnectTask)    ← 创建连接任务线程
    │
    ▼
WifiConnectTask()
    ├── ConnectToHotspot()      ← 扫描、连接、DHCP 获取 IP
    ├── 60 秒倒计时(osDelay)   ← 每秒打印剩余时间
    └── DisconnectWithHotspot() ← 断开连接

3.2、源文件说明

文件 说明
wifi_connect_example_AP.c AP 热点示例,创建 WifiHotspotTask 线程启动热点
wifi_connect_example_STA.c STA 连接示例,创建 WifiConnectTask 线程连接热点并倒计时断开
wifi_connecter.c 核心封装,实现 StartHotspotConnectToHotspotDisconnectWithHotspot
wifi_connecter.h 封装接口声明
BUILD.gn 编译配置,通过注释切换 AP/STA 源文件

3.3、关键代码分析

(1)AP 模块 — 热点配置参数
#define SSID "HiSpark_AP"
#define KEY "123456789"
#define WIFI_SEC_TYPE_PSK 2
#define CHANNEL 7
(2)AP 模块 — WifiHotspotTask 线程

热点线程直接调用 StartHotspot() 启动热点,并通过串口打印结果:

static void WifiHotspotTask(void)
{
    if (StartHotspot(SSID, KEY, WIFI_SEC_TYPE_PSK, CHANNEL) != 0)
    {
        printf("StartHotspot failed!\n");
    }
    else
    {
        printf("StartHotspot success!\n");
    }
}
(3)AP 模块 — 系统入口
static void WifiHotspotDemo(void)
{
    osThreadAttr_t attr;
    attr.name = "WifiHotspotTask";
    attr.stack_size = 0x1000;
    attr.priority = osPriorityNormal;

    if (osThreadNew(WifiHotspotTask, NULL, &attr) == NULL)
    {
        printf("[WifiHotspotDemo] Falied to create WifiHotspotTask!\n");
    }
}

SYS_RUN(WifiHotspotDemo);
(4)STA 模块 — WifiConnectTask 线程

连接线程完成"连接 → 倒计时保持 → 断开"的完整流程:

static void WifiConnectTask(void)
{
    int timeout = 60;
    if (ConnectToHotspot(SSID, KEY) != 0)
    {
        printf("Connect to AP failed!\n");
    }
    else
    {
        printf("Connect to AP success!\n");
    }

    while (timeout--)
    {
        printf("After %d seconds I will disconnect with AP!\r\n", timeout);
        osDelay(100);   // 100 ticks × 10 ms = 1 秒
    }

    DisconnectWithHotspot();
}
(5)封装层 — StartHotspot 核心逻辑

StartHotspot() 完成 SoftAP 启用与 DHCP 服务器配置:

errcode_t StartHotspot(char *ssid, char *key, wifi_security_enum security_type, uint8_t channel_num)
{
    char ifname[] = "ap0";
    ip4_addr_t st_ipaddr, st_netmask, st_gw;
    softap_config_stru hapd_conf = {0};

    IP4_ADDR(&st_ipaddr, 192, 168, 43, 1);   // AP IP
    IP4_ADDR(&st_netmask, 255, 255, 255, 0);
    IP4_ADDR(&st_gw, 192, 168, 43, 2);       // 网关

    // 配置热点参数
    memcpy_s(hapd_conf.ssid, sizeof(hapd_conf.ssid), ssid, strlen(ssid));
    memcpy_s(hapd_conf.pre_shared_key, WIFI_MAX_KEY_LEN, key, WIFI_MAX_KEY_LEN);
    hapd_conf.security_type = security_type;
    hapd_conf.channel_num = channel_num;

    // 启用 SoftAP(失败则重试)
    while (wifi_softap_enable(&hapd_conf) != ERRCODE_SUCC) {
        printf("Hotspot enable fail\r\n");
        osal_msleep(100);
    }

    // 配置网络地址并启动 DHCP 服务器
    netif_p = netif_find(ifname);
    netifapi_netif_set_addr(netif_p, &st_ipaddr, &st_netmask, &st_gw);
    netifapi_dhcps_start(netif_p, NULL, 0);

    printf("wifi init succ.\r\n");
    return ERRCODE_SUCC;
}
(6)封装层 — ConnectToHotspot 核心逻辑

ConnectToHotspot() 实现完整的 STA 连接流程:

errcode_t ConnectToHotspot(char *ssid, char *key)
{
    // 1. 启用 STA 模式
    while (wifi_sta_enable() != ERRCODE_SUCC) { ... }

    // 2. 循环扫描 → 匹配 SSID → 连接
    while (a) {
        wifi_sta_scan();
        wifi_register_event_cb(&wifi_event_cb);
        get_match_network(ssid, key, &expected_bss);  // 从扫描结果中匹配目标 AP
        wifi_sta_connect(&expected_bss);
        // 轮询等待连接成功 ...
    }

    // 3. DHCP 获取 IP
    g_iface = netifapi_netif_find("wlan0");
    netifapi_dhcp_start(g_iface);
    // 等待 DHCP 绑定并获取 IP 地址 ...

    printf("Connect success.\r\n");
    return ERRCODE_SUCC;
}
(7)封装层 — get_match_network 扫描匹配

从扫描结果中按 SSID 字符串精确匹配目标热点,并复制 BSSID、加密类型和密码:

errcode_t get_match_network(char *expected_ssid, char *key, wifi_sta_config_stru *expected_bss)
{
    wifi_sta_get_scan_info(result, &num);   // 获取扫描结果

    for (bss_index = 0; bss_index < num; bss_index++) {
        if (strlen(expected_ssid) == strlen(result[bss_index].ssid)) {
            if (memcmp(expected_ssid, result[bss_index].ssid, strlen(expected_ssid)) == 0) {
                break;   // 找到目标 AP
            }
        }
    }
    // 复制 SSID、BSSID、加密类型、密码到连接配置结构体
    expected_bss->ip_type = DHCP;
    return ERRCODE_SUCC;
}
(8)BUILD.gn — AP/STA 切换

编译时通过注释切换 AP 或 STA 源文件,同一时刻只能编译其中一个

static_library("wifi_connect_example") {
  sources = [
    "wifi_connecter.c",
    #"wifi_connect_example_STA.c",    // STA 模式(注释掉)
    "wifi_connect_example_AP.c"      // AP 模式(当前启用)
  ]
  // ...
}

3.4、程序执行流程

DHCP服务器 开发板B (STA) 开发板A (AP) DHCP服务器 开发板B (STA) 开发板A (AP) 热点已启动,等待连接 保持连接 60 秒倒计时 连接断开 SYS_RUN → WifiHotspotDemo StartHotspot("HiSpark_AP") wifi_softap_enable + dhcps_start SYS_RUN → WifiConnectDemo ConnectToHotspot("HiSpark_AP") wifi_sta_scan() 扫描发现 HiSpark_AP wifi_sta_connect() 关联成功 netifapi_dhcp_start() 分配 IP 地址 打印 "Connect to AP success!" DisconnectWithHotspot() wifi_sta_disconnect()

4、编译步骤

本实验需要分别编译 AP 固件和 STA 固件,烧录到两块开发板。以下步骤只需在首次编译时完成 4.1~4.3 的配置注册。

4.1、确认案例目录

确认案例已位于 OpenHarmony 源码目录下:

applications/sample/wifi-iot/app/c1_wifi_connect/
├── wifi_connect_example_AP.c
├── wifi_connect_example_STA.c
├── wifi_connecter.c
├── wifi_connecter.h
├── BUILD.gn
└── 实验手册.md

若从外部复制,请将 c1_wifi_connect 目录放到上述 app/ 路径下。

4.2、修改 BUILD.gn(注册编译组件)

编辑 applications/sample/wifi-iot/app/BUILD.gn,在 features 列表中添加本案例:

lite_component("app") {
  features = [
    "startup",
    "c1_wifi_connect:wifi_connect_example",   // 添加此行
  ]
}

4.3、修改 SDK 配置文件

步骤 1:编辑 device/soc/hisilicon/ws63v100/sdk/build/config/target_config/ws63/config.py

找到 'ws63-liteos-app' 配置段,在其 'ram_component' 列表中添加:

"wifi_connect_example"

步骤 2:编辑 device/soc/hisilicon/ws63v100/sdk/libs_url/ws63/cmake/ohos.cmake

找到 "ws63-liteos-app" 对应的 set(COMPONENT_LIST 部分,添加:

"wifi_connect_example"

4.4、编译 AP 固件(开发板 A)

编辑 applications/sample/wifi-iot/app/c1_wifi_connect/BUILD.gn,确保 sources 中启用 AP 源文件:

sources = [
  "wifi_connecter.c",
  #"wifi_connect_example_STA.c",
  "wifi_connect_example_AP.c"
]

在 OpenHarmony 源码根目录下执行编译:

rm -rf out
hb set -root .
# 通过上下方向键选择 ws63 对应的编译分支(如 nearlink_dk_3863 / ws63-liteos-app)
hb build -f

编译成功后,将固件烧录到 开发板 A(作为 AP 热点端)。

4.5、编译 STA 固件(开发板 B)

编辑 applications/sample/wifi-iot/app/c1_wifi_connect/BUILD.gn,切换为 STA 源文件:

sources = [
  "wifi_connecter.c",
  "wifi_connect_example_STA.c",
  #"wifi_connect_example_AP.c"
]

重新编译:

rm -rf out
hb set -root .
hb build -f

编译成功后,将固件烧录到 开发板 B(作为 STA 连接端)。

4.6、烧录固件

使用开发板配套的烧录工具,将编译生成的固件分别烧写到两块 LZ3863-星闪开发板。具体烧录步骤请参考开发板用户手册。


5、运行结果

5.1、硬件准备

  1. 开发板 A(AP 固件)上电或复位,等待热点启动;
  2. 开发板 B(STA 固件)上电或复位,开始扫描并连接热点;
  3. 两块开发板分别通过 USB 连接 PC,打开串口助手查看日志(波特率 115200,8N1)。

建议:先启动 AP 端开发板,确认热点创建成功后再启动 STA 端,以提高首次连接成功率。

5.2、串口配置

参数
波特率 115200
数据位 8
停止位 1
校验位
流控

5.3、AP 端预期输出(开发板 A)

烧录 AP 固件并复位后,串口助手可观察到:

StartHotspot success!
wifi init succ.

表示热点 HiSpark_AP 已成功创建,DHCP 服务器已启动,等待 STA 设备连接。

5.4、STA 端预期输出(开发板 B)

烧录 STA 固件并复位后,串口助手可观察到完整的连接过程:

Start Scan !
[WIFI_STA_SAMPLE] Scan done!.
STA try connect.
[WIFI_STA_SAMPLE] Connect succ!.
STA DHCP start.
STA DHCP bound success.
STA IP 192.168.43.x
Connect success.
Connect to AP success!
After 59 seconds I will disconnect with AP!
After 58 seconds I will disconnect with AP!
...
After 1 seconds I will disconnect with AP!
After 0 seconds I will disconnect with AP!
netifapi_dhcp_stop: 0
Disconnect: 0

其中:

  • Start Scan ! / Scan done! 表示热点扫描完成;
  • STA try connect. / Connect succ! 表示与 AP 关联成功;
  • STA IP 192.168.43.x 表示通过 DHCP 获取到 IP 地址;
  • Connect to AP success! 表示应用层确认连接成功;
  • After N seconds... 为 60 秒倒计时日志;
  • Disconnect: 0 表示断开连接成功。

5.5、结果分析

现象 说明
AP 端输出 StartHotspot success! SoftAP 热点创建成功
AP 端输出 wifi init succ. DHCP 服务器启动成功
STA 端输出 Scan done! 周围热点扫描完成
STA 端输出 Connect succ! 与目标 AP 无线关联成功
STA 端输出 STA IP 192.168.43.x DHCP 分配 IP 成功,网络层连通
STA 端倒计时 60 秒后断开 DisconnectWithHotspot() 正常执行
STA 端反复 Can not find AP AP 端未启动或 SSID/密码不匹配
STA 端 Connect to AP failed! 连接流程异常,检查密码与加密类型

5.6、常见问题排查

问题 可能原因 解决方法
STA 扫描不到 AP AP 端未启动或距离过远 先启动 AP 端,两块板靠近放置
STA 反复 Can not find AP SSID 或密码不一致 确认两端 SSID/KEY 宏定义完全相同
关联成功但无 IP DHCP 服务器未启动 检查 AP 端是否输出 wifi init succ.
AP 端 StartHotspot failed! WiFi 驱动初始化异常 重新烧录固件,确认 config.py 已添加组件
编译报错找不到 wifi_connect_example BUILD.gn 或 config.py 未正确修改 逐步核对 4.2、4.3 节的配置项
两块板同时烧录了相同固件 BUILD.gn 未切换 AP/STA 源文件 按 4.4、4.5 节分别编译烧录
倒计时期间连接中断 信号干扰或距离过远 缩短两块板距离,避开强干扰源

6、实验扩展

完成基本实验后,可尝试以下扩展练习:

  1. 修改热点参数:更改 SSIDKEYCHANNEL 宏定义,观察 STA 端是否需要同步修改才能连接;
  2. 修改保持时间:将 STA 模块中 timeout = 60 改为其他值,调整连接保持时长;
  3. 手机验证热点:AP 固件烧录后,用手机搜索 HiSpark_AP 热点并连接,验证热点可用性;
  4. 连接外部路由器:修改 STA 模块的 SSID/KEY 为家中路由器参数,实现开发板上网;
  5. 静态 IP 配置:将 expected_bss->ip_typeDHCP 改为静态 IP,理解 DHCP 与静态配置的区别;
  6. 添加重连机制:在 DisconnectWithHotspot() 后增加自动重新连接逻辑,实现断线重连;
  7. 结合 TCP/UDP 实验:在 WiFi 连接成功后,配合后续网络通信案例实现数据收发。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐