目录
- 前言
- 一、WiFI编程简介
-
- 主要API简介
- 二、开发过程
-
- 1.AP与STA模式区别
- 2.AP热点开发流程
- 3.STA网站开发流程
- 三、实现官方案例
-
- 1. AP
-
- 代码编写
- 编译调试
- 2. STA
-
- 代码编写
- 编译调试
前言
HarmonyOS新手入门设备开发的芯路历程 在官方文帐中,鸿蒙小熊派开发板从模块到芯片再次介绍。开发板使用的芯片是Hi3861V100芯片。 Hi3861V100是高度集成的2.4GHz SoC WiFi芯片,集成IEEE 802.11b/g/n基带和RF电路,RF电路包括功率放大器PA、低 噪声放大器LNA、RF balun、支持20MHz标准带宽和5MHz/10MHz窄带宽,提供最大72.2Mbit/s 物理层速率。Hi3861V100 WiFi支持正交频分复使用的基础支持(OFDM)该技术与直接序列扩频兼容(DSSS)和补码键控(CCK)技术,支 持IEEE 802.11 b/g/n协议的各种数据速率。 Hi3861V100芯片集成高性能32bit外设界面包括微处理器、硬件安全引擎和丰富的外设界面SPI、UART、I2C、PWM、 GPIO和多路ADC,支持高速SDIO2.0 Slave接口最高时钟可达50MHz;芯片内置SRAM和Flash,可独立运行,并支持 在Flash操作程序。 Hi3861V100支持HUAWEI LiteOS与第三方组件一起,提供开放、易用的开发和调试运行环境。 Hi3861V100支持HUAWEI LiteOS与第三方组件一起,提供开放、易用的开发和调试运行环境。 Hi3861V100芯片适用于物联网智能终端领域,如智能家电。
可以去官方社区账号专栏看更多。本文主要总结鸿蒙wifi接口
一、WiFI编程简介
Hi3861V100、Hi3861LV100 通过API(Application Programming Interface)为开发者提供Wi-Fi芯片初始化、资源配置、Station创建和配置、扫描、关联、去关联、状态查询等一系列功能, 框架结构如图所示。
-
APP应用开发层:用户基于用户API接口二次开发。
-
Example示例:SDK提供的功能开发示例。
-
API接口:提供基础SDK通用接口。
-
LWIP协议栈:网络协议栈。
-
WPA SUPPLICANT(含HOSTAPD):Wi-Fi管理模块。
-
Wi-Fi驱动:802.协议实现模块。
-
Platform平台:提供SoC系统板级支持包(包括芯片及外围设备驱动、操作系统及系统管理)
鸿蒙系统代码API文件如下: foundation\communication\interfaces\kits\wifi_lite\wifiservice\wifi_device.h foundation\communication\interfaces\kits\wifi_lite\wifiservice\wifi_hotspot.h
主要API简介
WifiErrorCode RegisterWifiEvent (WifiEvent * event)
描述: 为指定的Wi-Fi事件注册回调函数。WifiEvent中定义的Wi-Fi事件发生时,将调用注册回调函数 参数:
名字 | 描述 |
---|---|
event | 表示要注册回调的事件 |
WifiErrorCode EnableHotspot (void )
描述: 启用Wifi热点模式
WifiErrorCode SetHotspotConfig(const HotspotConfig* config)
描述: 设置指定的热点配置
int IsHotspotActive(void);
描述: 检查AP是否启用热点模式
WifiErrorCode GetStationList(StationInfo* result, unsigned int* size)
描述: 一系列连接到热点的获取系列STA 参数:
名字 | 描述 |
---|---|
result | 表示连接到热点STA列表 |
size | 表示连接到该热点的STA数量 |
WifiErrorCode EnableWifi (void )
描述: 启用STA模式
WifiErrorCode AddDeviceConfig (const WifiDeviceConfig * config, int * result )
描述: 添加用于配置连接的热点信息,生成此函数networkId 参数:
名字 | 描述 |
---|---|
config | 表示要连接的热点信息 |
result | 表示生成的networkId。每个networkId匹配热点配置 |
WifiErrorCode ConnectTo (int networkId)
描述: 连接到指定networkId的热点
struct netif *netifapi_netif_find(const char *name);
描述: 获取netif用于IP操作
err_t dhcp_start(n)
描述:启动DHCP, 获取IP
二、开发流程
1.AP与STA模式区别
:无线接入点,是一个无线网络的创建者,是网络的中心节点。一般家庭或办公室使用的无线路由器就是一个AP。
:就是每一个连接到无线网络中的终端(如笔记本电脑、PDA及其它可以联网的用户设备)都可称为一个站点。
: Access Point,提供无线接入服务,允许其它无线设备接入,提供数据访问,一般的无线路由/网桥工作在该模式下。AP和AP之间允许相互连接。 在此模式下,手机、PAD、电脑等设备可以直接连上模块,可以很方便对用户设备进行控制。
: Station, 类似于无线终端,sta本身并不接受无线的接入,它可以连接到AP,一般无线网卡即工作在该模式。 这是一种基本的组网方式,由一个AP和许多STA组成。其特点是AP处于中心地位,STA之间的相互通信都通过AP转发完成。该模式下,WIFI模块工作在STA(CLIENT)模式。通过适当的设置,COM的数据与WIFI的网路数据相互转换。
2.AP热点开发流程
鸿蒙设备完成Wifi热点的扫描需要以下几步
- 通过
RegisterWifiEvent
接口向系统注册热点状态改变事件、STA站点加入事件、STA站点退出事件
OnHotspotStateChangedHandler
用于绑定热点状态改变事件,该回调函数有一个参数 state ;其中state表示是否开启AP模式,取值为0和1,0表示已启用Wifi AP模式,1表示已禁用Wifi AP模式;
OnHotspotStaLeaveHandler
用于绑定STA站点退出事件,当有STA站点退出,该回调函数会打印出退出站点的MAC地址;
OnHotspotStaJoinHandler
用于绑定STA站点加入事件,当有新的STA站点加入时,该回调函数会创建 HotspotStaJoinTask,在该任务中会调用 GetStationList 函数获取当前接入到该AP的所有STA站点信息,并打印出每个STA站点的MAC地址;
调用
SetHotspotConfig
接口,设置指定的热点配置;调用
EnableHotspot
接口,使能 Wifi AP 模式;调用
IsHotspotActive
接口,检查AP热点模式是否启用;调用
netifapi_netif_set_addr
函数设置网卡信息;调用
netifapi_dhcps_start
函数启动dhcp服务;3.STA站点开发流程
鸿蒙设备完成Wifi热点的连接需要以下几步
- 通过
RegisterWifiEvent
接口向系统注册扫描状态监听函数,用于接收扫描状态通知,如扫描动作是否完成等
OnWifiConnectionChangedHandler
用于绑定连接状态监听函数,该回调函数有两个参数 state 和 info ;state表示扫描状态,取值为0和1,1表示热点连接成功;info表示Wi-Fi连接信息,包含以下参数:
名字 描述 ssid [WIFI_MAX_SSID_LEN] 连接的热点名称. bssid [WIFI_MAC_LEN] MAC地址. rssi 接收信号强度(RSSI). connState Wifi连接状态. disconnectedReason Wi-Fi断开的原因.
- 调用
EnableWifi
接口,使能 Wifi。- 调用
AddDeviceConfig
接口,配置连接的热点信息。- 调用
ConnectTo
接口,连接到指定networkId的热点。- 调用
WaitConnectResult
接口等待,该函数中会有15s的时间去轮询连接成功标志位g_ConnectSuccess
,当g_ConnectSuccess
为 1 时退出等待。- 调用
netifapi_netif_find
接口,获取 netif 用于 IP 操作- 调用
dhcp_start
接口,启动 DHCP, 获取 IP三、官方案例实现
1. AP
此模式下并不能联网,只是能够将终端连接到设备而已。如需联网应该采用AP+STA模式。
代码编写
#define AP_SSID "BearPi" #define AP_PSK "0987654321" #define ONE_SECOND 1 #define DEF_TIMEOUT 15 static void OnHotspotStaJoinHandler(StationInfo *info); static void OnHotspotStateChangedHandler(int state); static void OnHotspotStaLeaveHandler(StationInfo *info); static struct netif *g_lwip_netif = NULL; static int g_apEnableSuccess = 0; WifiEvent g_wifiEventHandler = { 0}; WifiErrorCode error; static BOOL WifiAPTask(void) { //延时2S便于查看日志 osDelay(200); //注册wifi事件的回调函数 g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler; g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler; g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler; error = RegisterWifiEvent(&g_wifiEventHandler); if (error != WIFI_SUCCESS) { printf("RegisterWifiEvent failed, error = %d.\r\n",error); return -1; } printf("RegisterWifiEvent succeed!\r\n"); //设置指定的热点配置 HotspotConfig config = { 0}; strcpy(config.ssid, AP_SSID); strcpy(config.preSharedKey, AP_PSK); config.securityType = WIFI_SEC_TYPE_PSK; config.band = HOTSPOT_BAND_TYPE_2G; config.channelNum = 7; error = SetHotspotConfig(&config); if (error != WIFI_SUCCESS) { printf("SetHotspotConfig failed, error = %d.\r\n", error); return -1; } printf("SetHotspotConfig succeed!\r\n"); //启动wifi热点模式 error = EnableHotspot(); if (error != WIFI_SUCCESS) { printf("EnableHotspot failed, error = %d.\r\n", error); return -1; } printf("EnableHotspot succeed!\r\n"); //检查热点模式是否使能 if (IsHotspotActive() == WIFI_HOTSPOT_NOT_ACTIVE) { printf("Wifi station is not actived.\r\n"); return -1; } printf("Wifi station is actived!\r\n"); //启动dhcp g_lwip_netif = netifapi_netif_find("ap0"); if (g_lwip_netif) { ip4_addr_t bp_gw; ip4_addr_t bp_ipaddr; ip4_addr_t bp_netmask; IP4_ADDR(&bp_gw, 192, 168, 1, 1); /* input your gateway for example: 192.168.1.1 */ IP4_ADDR(&bp_ipaddr, 192, 168, 1, 1); /* input your IP for example: 192.168.1.1 */ IP4_ADDR(&bp_netmask, 255, 255, 255, 0); /* input your netmask for example: 255.255.255.0 */ err_t ret = netifapi_netif_set_addr(g_lwip_netif, &bp_ipaddr, &bp_netmask, &bp_gw); if(ret != ERR_OK) { printf("netifapi_netif_set_addr failed, error = %d.\r\n", ret); return -1; } printf("netifapi_netif_set_addr succeed!\r\n"); ret = netifapi_dhcps_start(g_lwip_netif, 0, 0); if(ret != ERR_OK) { printf("netifapi_dhcp_start failed, error = %d.\r\n", ret); return -1; } printf("netifapi_dhcps_start succeed!\r\n"); } /****************以下为UDP服务器代码***************/ //在sock_fd 进行监听 int sock_fd; //服务端地址信息 struct sockaddr_in server_sock; //创建socket if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket is error.\r\n"); return -1; } bzero(&server_sock, sizeof(server_sock)); server_sock.sin_family = AF_INET; server_sock.sin_addr.s_addr = htonl(INADDR_ANY); server_sock.sin_port = htons(8888); //调用bind函数绑定socket和地址 if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1) { perror("bind is error.\r\n"); return -1; } int ret; char recvBuf[512] = { 0}; //客户端地址信息 struct sockaddr_in client_addr; int size_client_addr= sizeof(struct sockaddr_in); while (1) { printf("Waiting to receive data...\r\n"); memset(recvBuf, 0, sizeof(recvBuf)); ret = recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr*)&client_addr,(socklen_t*)&size_client_addr); if(ret < 0) { printf("UDP server receive failed!\r\n"); return -1; } printf("receive %d bytes of data from ipaddr = %s, port = %d.\r\n", ret, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); printf("data is %s\r\n",recvBuf); ret = sendto(sock_fd, recvBuf, strlen(recvBuf), 0, (struct sockaddr *)&client_addr, sizeof(client_addr)); if (ret < 0) { printf("UDP server send failed!\r\n"); return -1; } } /*********************END********************/ }
课程上说是获取站点列表函数在回调函数中调用得不到结果,所以写了个任务函数在回调函数中调用。
static void HotspotStaJoinTask(void) { static char macAddress[32] = { 0}; StationInfo stainfo[WIFI_MAX_STA_NUM] = { 0}; StationInfo *sta_list_node = NULL; unsigned int size = WIFI_MAX_STA_NUM; error = GetStationList(stainfo, &size); if (error != WIFI_SUCCESS) { printf("HotspotStaJoin:get list fail, error is %d.\r\n", error); return; } sta_list_node = stainfo; for (uint32_t i = 0; i < size; i++, sta_list_node++) { unsigned char* mac = sta_list_node->macAddress; snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); printf("HotspotSta[%d]: macAddress=%s.\r\n",i, macAddress); } g_apEnableSuccess++; } static void OnHotspotStaJoinHandler(StationInfo *info) { if (info == NULL) { printf("HotspotStaJoin:info is null.\r\n"); } else { printf("New Sta Join\n"); osThreadAttr_t attr; attr.name = "HotspotStaJoinTask"; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = 2048; attr.priority = 24; if (osThreadNew((osThreadFunc_t)HotspotStaJoinTask, NULL, &attr) == NULL) { printf("HotspotStaJoin:create task fail!\r\n"); } } return; } static void OnHotspotStaLeaveHandler(StationInfo *info) { if (info == NULL) { printf("HotspotStaLeave:info is null.\r\n"); } else { static char macAddress[32] = { 0}; unsigned char* mac = info->macAddress; snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); printf("HotspotStaLeave: macAddress=%s, reason=%d.\r\n", macAddress, info->disconnectedReason); g_apEnableSuccess--; } return; } static void OnHotspotStateChangedHandler(int state) { printf("HotspotStateChanged:state is %d.\r\n", state); if (state == WIFI_HOTSPOT_ACTIVE) { printf("wifi hotspot active.\r\n"); } else { printf("wifi hotspot noactive.\r\n"); } }
编译调试
修改
applications\BearPi\BearPi-HM_Nano\sample
路径下 BUILD.gn 文件,指定 wifi_ap 参与编译。 Linux终端或者MobaXterm的会话连接内,进入代码目录执行python build.py BearPi-HM_Nano
进行编译。 使用HiBurn工具,波特率设置为2000000. 选择对应的com口和要烧录的文件,勾选auto burn。点击connect,再点开发板复位按键。进行烧录。 通过MobaXterm的串口工具查看。用手机连一下试试。2. STA
此模式下设备能联网,但是不能够将终端连接到设备。如需联网应该采用AP+STA模式。
代码编写
相关声明
#define DEF_TIMEOUT 15 #define ONE_SECOND 1 static void WiFiInit(void); static void WaitSacnResult(void); static int WaitConnectResult(void); static void OnWifiScanStateChangedHandler(int state, int size); static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo *info); static void OnHotspotStaJoinHandler(StationInfo *info); static void OnHotspotStateChangedHandler(int state); static void OnHotspotStaLeaveHandler(StationInfo *info); static int g_staScanSuccess = 0; static int g_ConnectSuccess = 0; static int ssid_count = 0; WifiEvent g_wifiEventHandler = { 0}; WifiErrorCode error; #define SELECT_WLAN_PORT "wlan0" #define SELECT_WIFI_SSID "your wifi ssid"//这里改成要连接的热点账号和对应密码 #define SELECT_WIFI_PASSWORD "your wifi password" #define SELECT_WIFI_SECURITYTYPE WIFI_SEC_TYPE_PSK
static BOOL WifiSTATask(void) { WifiScanInfo *info = NULL; unsigned int size = WIFI_SCAN_HOTSPOT_LIMIT; static struct netif *g_lwip_netif = NULL; WifiDeviceConfig select_ap_config = { 0}; osDelay(200); printf("<--System Init-->\r\n"); //初始化WIFI,将回调函数绑定写到这里了 WiFiInit(); //使能WIFI if (EnableWifi() != WIFI_SUCCESS) { printf("EnableWifi failed, error = %d\n", error); return -1; } //判断WIFI是否激活 if (IsWifiActive() == 0) { printf("Wifi station is not actived.\n"); return -1; } //分配空间,保存WiFi信息 info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT); if (info == NULL) { return -1; } //轮询查找WiFi列表 do 标签:
hm2518集成电路集成电路hi12g03d1c集成电路