目录
  • 一、准备工作
  • 二、软件设计
  • 三、编译调试

Wifi连接热点

本示例将演示如何在BearPi-HM_Nano 2开发板上编写一个Wifi连接热点业务程序。

一、准备工作

参考BearPi-HM_Nano_2十分钟上手教程完成开发环境搭建、代码获取等工作,以及熟悉代码的编译和烧录流程。

二、软件设计

主要代码分析

打开device\bearpi\bearpi_hm_nano2\app\D2_iot_wifi_sta_connect\wifi_sta_connect.c

完成Wifi热点的连接需要以下几步

  1. 通过 RegisterWifiEvent 接口向系统注册扫描状态监听函数,用于接收扫描状态通知,如扫描动作是否完成等
  • OnWifiConnectionChangedHandler 用于绑定连接状态监听函数,该回调函数有两个参数 stateinfo

    • state表示扫描状态,取值为0和1,1表示热点连接成功;

    • info表示Wi-Fi连接信息,包含以下参数;

      名字描述
      ssid [WIFI_MAX_SSID_LEN]连接的热点名称.
      bssid [WIFI_MAC_LEN]MAC地址.
      rssi接收信号强度(RSSI).
      connStateWifi连接状态.
      disconnectedReasonWi-Fi断开的原因.
  1. 调用 EnableWifi 接口,使能 Wifi。
  2. 调用 AddDeviceConfig 接口,配置连接的热点信息。
  3. 调用 ConnectTo 接口,连接到指定networkId的热点。
  4. 调用 WaitConnectResult 接口等待,该函数中会有15s的时间去轮询连接成功标志位 g_ConnectSuccess,当g_ConnectSuccess 为 1 时退出等待。
  5. 调用 netifapi_netif_find 接口,获取 netif 用于 IP 操作
  6. 调用 dhcp_start 接口,启动 DHCP, 获取 IP
static int WifiConnectAp(const char *ssid, const char *psk, WifiScanInfo *info, int i)
{
    if (strcmp(ssid, info[i].ssid) == 0) {
        int result;
        printf("Select:%3d wireless, Waiting...\r\n", i + 1);

        // 拷贝要连接的热点信息
        WifiDeviceConfig select_ap_config = { 0 };
        strcpy_s(select_ap_config.ssid, sizeof(select_ap_config.ssid), info[i].ssid);
        strcpy_s(select_ap_config.preSharedKey, sizeof(select_ap_config.preSharedKey), psk);
        select_ap_config.securityType = WIFI_SEC_TYPE_PSK;

        if (AddDeviceConfig(&select_ap_config, &result) == WIFI_SUCCESS) {
            if (ConnectTo(result) == WIFI_SUCCESS && WaitConnectResult() == 1) {
                g_lwip_netif = netifapi_netif_find(SELECT_WLAN_PORT);
                return 0;
            }
        }
    }
    return -1;
}




static BOOL WifiStaTask(void)
{
    unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT;

    // 初始化WIFI
    if (WiFiInit() != WIFI_SUCCESS) {
        printf("WiFiInit failed, error = %d\r\n", error);
        return -1;
    }
    // 分配空间,保存WiFi信息
    WifiScanInfo *info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);
    if (info == NULL) {
        return -1;
    }
    // 轮询查找WiFi列表
    do {
        Scan();
        WaitScanResult();
        error = GetScanInfoList(info, &size);
    } while (g_staScanSuccess != 1);
    // 打印WiFi列表
    printf("********************\r\n");
    for (uint8_t i = 0; i < g_ssid_count; i++) {
        printf("no:%03d, ssid:%-30s, rssi:%5d\r\n", i + 1, info[i].ssid, info[i].rssi);
    }
    printf("********************\r\n");
    // 连接指定的WiFi热点
    for (uint8_t i = 0; i < g_ssid_count; i++) {
        if (WifiConnectAp(SELECT_WIFI_SSID, SELECT_WIFI_PASSWORD, info, i) == WIFI_SUCCESS) {
            printf("WiFi connect succeed!\r\n");
            break;
        }

        if (i == g_ssid_count - 1) {
            printf("ERROR: No wifi as expected\r\n");
            while (1)
                osDelay(DHCP_DELAY);
        }
    }

    // 启动DHCP
    if (g_lwip_netif) {
        dhcp_start(g_lwip_netif);
        printf("begin to dhcp\r\n");
    }
    // 等待DHCP
    for (;;) {
        if (dhcp_is_bound(g_lwip_netif) == ERR_OK) {
            printf("<-- DHCP state:OK -->\r\n");
            // 打印获取到的IP信息
            netifapi_netif_common(g_lwip_netif, dhcp_clients_info_show, NULL);
            break;
        }
        osDelay(DHCP_DELAY);
    }

    // 执行其他操作
    for (;;) {
        osDelay(DHCP_DELAY);
    }
}

Wifi API分析

本案例主要使用了以下几个API完成Wifi联网

RegisterWifiEvent()

WifiErrorCode RegisterWifiEvent (WifiEvent * event)

描述: 为指定的Wi-Fi事件注册回调函数。当WifiEvent中定义的Wi-Fi事件发生时,将调用已注册的回调函数

参数:

名字描述
event表示要注册回调的事件.

EnableWifi()

WifiErrorCode EnableWifi (void )

描述:

启用STA模式

AddDeviceConfig()

WifiErrorCode AddDeviceConfig (const WifiDeviceConfig * config, int * result )

描述:

添加用于配置连接到热点信息,此函数生成一个networkId

参数:

名字描述
config表示要连接的热点信息.
result表示生成的networkId。每个networkId匹配一个热点配置

ConnectTo()

WifiErrorCode ConnectTo (int networkId)

描述:

连接到指定networkId的热点

参数:

名字描述
networkId表示与目标热点匹配的网络id.

netifapi_netif_find()

struct netif *netifapi_netif_find(const char *name);

描述:

获取netif用于IP操作

dhcp_start()

err_t dhcp_start(n)

描述:

启动DHCP, 获取IP

三、编译调试

修改对接热点的账号密码

修改wifi_sta_connect.c第51行和52行的热点账号密码

#define SELECT_WIFI_SSID "BearPi"
#define SELECT_WIFI_PASSWORD "0987654321"

修改 BUILD.gn 文件

修改 device\bearpi\bearpi_hm_nano2\app 路径下 BUILD.gn 文件,指定 wifi_sta_connect 参与编译。

#"D1_iot_wifi_sta:wifi_sta",
"D2_iot_wifi_sta_connect:wifi_sta_connect",        
#"D3_iot_udp_client:udp_client",
#"D4_iot_tcp_server:tcp_server",
#"D5_iot_mqtt:iot_mqtt",        

运行结果

示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,会打印连接到的Wifi热点信息。

<--System Init-->

<--Wifi Init-->

register wifi event succeed!

+NOTICE:SCANFINISH
WaitSacnResult:wait success[1]s


Select:  2 wireless, Waiting...

+NOTICE:CONNECTED
callback function for wifi connect

WaitConnectResult:wait success[1]s
WiFi connect succeed!

begain to dhcp

<-- DHCP state:Inprogress -->

<-- DHCP state:OK -->

server :
	server_id : 192.168.0.1
	mask : 255.255.255.0, 1
	gw : 192.168.0.1
	T0 : 7200
	T1 : 3600
	T2 : 6300
clients <1> :
	mac_idx mac             addr            state   lease   tries   rto     
	0       801131801388    192.168.0.151   10      0       1       4