hi3863 连接WiFi
在源码目录 \application\samples\wifi\sta_sample 下有官方的例子,根据对这个例子的学习理解,我根据自己的需要,整理简化了一下。首先在我的代码目录下 \application\samples\hi3863\ 下建一个 “mqtt_test”子文件夹,我将我要写的代码放在这个子文件夹下。在 \application\samples\hi3863\mqtt_test\
物联网应用是Hi3863及其系统中最主要的功能。
我分步来实现一个 MQTT 设备通信的应用。
首先在我的代码目录下 \application\samples\hi3863\ 下建一个 “mqtt_test”子文件夹,我将我要写的代码放在这个子文件夹下。
文件目录是这样的:

先写通单独功能,最后综合在一起,组成一个完整应用。
先设置编译配置
修改 \application\samples\hi3863\Kconfig
添加 编译菜单 MQTT_TEST 项
config MQTT_TEST
bool
prompt "Enable the mqtt test app."
default n
help
This option means enable the mqtt test app.
if MQTT_TEST
osource "application/samples/hi3863/mqtt_test/Kconfig"
endif
修改 \application\samples\hi3863\CMakeLists.txt
添加 编译 MQTT_TEST 目录
if(DEFINED CONFIG_MQTT_TEST)
add_subdirectory_if_exist(mqtt_test)
endif()
在 \application\samples\hi3863\mqtt_test\ 目录下 添加 CMakeLists.txt , Kconfig 文件
Kconfig 修改为
# wifi sta 站点模式 t1
config WIFI_STA_T1
bool
prompt "Enable the mqtt app wifi sta t1 "
default n
help
This option means enable the mqtt app wifi sta t1.
# mqtt client 客户端实现 t2
config MQTT_CLIENT_T2
bool
prompt "Enable the mqtt app mqtt client t2"
default n
help
This option means enable the mqtt t2.
# cjson data 格式数据 t3
config CJSON_DATA_T3
bool
prompt "Enable the mqtt app cjson data t3."
default n
help
This option means enable the mqtt app cjson data t3.
# crypt cjson 数据加密 t4
config CRYPT_CJSON_T4
bool
prompt "Enable the mqtt app crypt cjson t4."
default n
help
This option means enable the mqtt app crypt cjson t4.
# all in 全部 t5
config ALL_IN_T5
bool
prompt "Enable the mqtt app all in t5."
default n
help
This option means enable the mqtt app all in t5.
CMakeLists.txt 修改为
if(DEFINED CONFIG_WIFI_STA_T1)
add_subdirectory_if_exist(wifi_sta_t1)
endif()
if(DEFINED CONFIG_MQTT_CLIENT_T2)
add_subdirectory_if_exist(mqtt_client_t2)
endif()
if(DEFINED CONFIG_CJSON_DATA_T3)
add_subdirectory_if_exist(cjson_data_t3)
endif()
if(DEFINED CONFIG_CRYPT_CJSON_T4)
add_subdirectory_if_exist(crypt_cjson_t4)
endif()
if(DEFINED CONFIG_ALL_IN_T5)
add_subdirectory_if_exist(all_in_t5)
endif()
set(SOURCES "${SOURCES}" PARENT_SCOPE)
首先实现连WiFi的功能。
在源码目录 \application\samples\wifi\sta_sample 下有官方的例子,根据对这个例子的学习理解,我根据自己的需要,整理简化了一下。
在 \application\samples\hi3863\mqtt_test\wifi_sta_t1 目录下建这几个文件

然后 先修 CMakeLists.txt
set(SOURCES_LIST
${CMAKE_CURRENT_SOURCE_DIR}/entry.c
${CMAKE_CURRENT_SOURCE_DIR}/wifi_sta.c
)
set(PUBLIC_HEADER_LIST
${CMAKE_CURRENT_SOURCE_DIR}
)
set(SOURCES "${SOURCES_LIST}" PARENT_SCOPE)
set(PUBLIC_HEADER "${PUBLIC_HEADER_LIST}" PARENT_SCOPE)
添加2个要编译的文件
wifi_sta.c 代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "osal_addr.h"
#include "cmsis_os2.h"
#include "lwip/netifapi.h"
#include "wifi_hotspot.h"
#include "wifi_hotspot_config.h"
#include "wifi_sta.h"
static uint8_t conn_stat = 0; // 连接 状态
static uint8_t scan_stat = 0; // 扫描 状态
struct netif *net_if = NULL; // 网络接口信息
// 连接状态改变 回调
static void WiFi_Conn_State_Changed_Callback(int32_t state, const wifi_linked_info_stru *info, int32_t reason_code)
{
(void)info;
(void)reason_code;
if(state != 0)
{
conn_stat = 1;
}
return;
}
// 扫描状态改变 回调
static void WiFi_Scan_State_Changed_Callback(int32_t state, int32_t size)
{
(void)state;
(void)size;
scan_stat = 1;
return;
}
// WiFi 事件 回调
wifi_event_stru WiFi_Event_Callback = {
.wifi_event_connection_changed = WiFi_Conn_State_Changed_Callback, // 连接状态改变
.wifi_event_scan_state_changed = WiFi_Scan_State_Changed_Callback, // 扫描状态改变
};
// WiFi STA 模式 连接 AP :输入 AP 名 , AP 密码 , 空 IP 地址
uint8_t WiFi_STA_Conn_AP(char *ap_name, char *ap_pass, char *ip_str)
{
// 注册事件回调
if(wifi_register_event_cb(&WiFi_Event_Callback) != ERRCODE_SUCC)
{
return 1;
}
// 获取 WiFi 设备初始化状态
while(wifi_is_wifi_inited() != 1)
{
(void)osDelay(20);
}
// 开启 STA
if(wifi_sta_enable() != ERRCODE_SUCC)
{
return 2;
}
// 进行全信道基础扫描
if(wifi_sta_scan() != ERRCODE_SUCC)
{
return 3;
}
// 等待 扫描状态改变
while(scan_stat != 1)
{
(void)osDelay(20);
}
// 最大扫描数
uint32_t ap_num = 16;
// 扫描信息大小
uint32_t scan_info_size = sizeof(wifi_scan_info_stru) * ap_num;
// 分配存储空间
wifi_scan_info_stru *result = osal_kmalloc(scan_info_size, OSAL_GFP_ATOMIC);
// 分配 失败
if(result == NULL)
{
return 4;
}
// 空间清零
memset_s(result, scan_info_size, 0, scan_info_size);
// 获取sta扫描结果
if(wifi_sta_get_scan_info(result, &ap_num) != ERRCODE_SUCC)
{
osal_kfree(result);
return 5;
}
uint8_t ap_find = 0; // ap 查找 结果
uint8_t idx; // 序号
// 检索 热点名
for(idx = 0; idx < ap_num; idx++)
{
if(strlen(ap_name) == strlen(result[idx].ssid))
{
if(memcmp(ap_name, result[idx].ssid, strlen(ap_name)) == 0)
{
ap_find = 1;
break;
}
}
}
// 未检索到 热点
if(ap_find == 0)
{
osal_kfree(result);
return 6;
}
// 连接到 WiFi AP
// 连接 AP 的配置信息
wifi_sta_config_stru sta_config = {0};
memcpy_s(sta_config.ssid, WIFI_MAX_SSID_LEN, ap_name, strlen(ap_name));
memcpy_s(sta_config.bssid, WIFI_MAC_LEN, result[idx].bssid, WIFI_MAC_LEN);
memcpy_s(sta_config.pre_shared_key, WIFI_MAX_KEY_LEN, ap_pass, strlen(ap_pass));
sta_config.security_type = result[idx].security_type;
sta_config.ip_type = DHCP;
osal_kfree(result);
// 连接到 WiFi AP 热点
if(wifi_sta_connect(&sta_config) != ERRCODE_SUCC)
{
return 7;
}
// 等待 连接状态改变
while(conn_stat != 1)
{
(void)osDelay(20);
}
// dhcp 分配 IP
// 网络 接口 名
char if_name[WIFI_IFNAME_MAX_SIZE + 1] = "wlan0";
// 获取 网络接口信息
net_if = netifapi_netif_find(if_name);
// 网络接口信息 为空
if(net_if == NULL)
{
return 8;
}
// 开启 DHCP
if(netifapi_dhcp_start(net_if) != ERR_OK)
{
return 9;
}
// 等待协商完成
while(netifapi_dhcp_is_bound(net_if) != ERR_OK)
{
(void)osDelay(20);
}
// 保存 IP 地址
if(net_if->ip_addr.u_addr.ip4.addr != 0)
{
sprintf(ip_str, "%u.%u.%u.%u", (net_if->ip_addr.u_addr.ip4.addr & 0x000000ff),
(net_if->ip_addr.u_addr.ip4.addr & 0x0000ff00) >> 8,
(net_if->ip_addr.u_addr.ip4.addr & 0x00ff0000) >> 16,
(net_if->ip_addr.u_addr.ip4.addr & 0xff000000) >> 24);
}
return 0;
}
// wifi sta 关闭
void WiFi_STA_Close(void)
{
// 停止 DHCP
netifapi_dhcp_stop(net_if);
// 清空
net_if = NULL;
// 断开连接
wifi_sta_disconnect();
// 关闭 wifi sta
wifi_sta_disable();
}
// 打印 错误信息
void Print_Error(uint8_t error)
{
switch (error)
{
case 1:
// 注册 事件 回调 失败
osal_printk(" [wifi_register_event_cb] FAILURE! \n");
break;
case 2:
// 开启 STA 模式 失败
osal_printk(" [wifi_sta_enable] FAILURE! \n");
break;
case 3:
// 进行全信道基础扫描 失败
osal_printk(" [wifi_sta_scan] FAILURE! \n");
break;
case 4:
// 分配存储空间 失败
osal_printk(" [osal_kmalloc] FAILURE! \n");
break;
case 5:
// 获取 sta 扫描结果 失败
osal_printk(" [wifi_sta_get_scan_info] FAILURE! \n");
break;
case 6:
// 未检索到 WiFi ap 失败
osal_printk(" [ap_find == 0] FAILURE! \n");
break;
case 7:
// 连接 WiFi AP 失败
osal_printk(" [wifi_sta_connect] FAILURE! \n");
break;
case 8:
// 获取 网口 信息 失败
osal_printk(" [netifapi_netif_find] FAILURE! \n");
break;
case 9:
// 开启 DHCP 失败
osal_printk(" [netifapi_dhcp_start] FAILURE! \n");
break;
default:
break;
}
}
wifi_sta.h
#ifndef __WIFI_STA_H__
#define __WIFI_STA_H__
// WiFi STA 模式 连接 AP :输入 AP 名 , AP 密码 , 空 IP 地址
uint8_t WiFi_STA_Conn_AP(char *ap_name, char *ap_pass, char *ip_str);
// WiFi STA 关闭
void WiFi_STA_Close(void);
// 打印 错误信息
void Print_Error(uint8_t error);
#endif
entry.c
#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "wifi_sta.h"
#define TASK_PRIO 6 // 任务 优先级 OSAL_TASK_PRIORITY_MIDDLE
#define TASK_SIZE 0x2000 // 任务 大小
#define AP_NAME "WiFi名" // wifi ap 名
#define AP_PASS "WiFi密码" // wifi ap 连接密码
static char ip_str[16] = {0}; // IP 地址
// 任务
static void *wifi_sta_task(const char *arg)
{
unused(arg);
// 开始
osal_printk(" [wifi sta t1] start \n");
uint8_t ret;
// 连接 热点
ret = WiFi_STA_Conn_AP(AP_NAME, AP_PASS, ip_str);
if(ret == 0)
{
osal_printk(" [WiFi_STA_Conn_AP] SUCCESS. \n");
osal_printk(" ip addr : %s \n", ip_str);
}
else
{
Print_Error(ret);
}
uint8_t num = 0;
while (num < 5)
{
osal_msleep(500);
num++;
osal_printk(" connect... %d ms \n", num * 500);
}
osal_printk(" [WiFi_STA_Close] \n");
// 关闭 sta
WiFi_STA_Close();
// 结束 退出
osal_printk(" [wifi sta t1] end \n");
return NULL;
}
// 线程
static void wifi_sta_entry(void)
{
osal_task *task_handle = NULL;
// 锁定任务
osal_kthread_lock();
// 创建线程
task_handle = osal_kthread_create((osal_kthread_handler)wifi_sta_task, 0, "APPTask", TASK_SIZE);
// 创建成功
if (task_handle != NULL)
{
// 优先级
osal_kthread_set_priority(task_handle, TASK_PRIO);
// 释放
osal_kfree(task_handle);
}
// 解锁任务
osal_kthread_unlock();
}
// 加载
app_run(wifi_sta_entry);
然后 打开 系统配置

点 “save", 关闭
点编译。
编译成功后,烧录,运行。上一篇幅都有讲。

显示 连接成功,间隔一段时间,关闭连接,退出程序。
具体功能过程看源码库里的文档吧,我再重复也没有文档说的详细。代码都做了注释。
相关代码我写完在gitee.com上开个仓,有些都是新手入门,没有vip也没有百度网盘,我的代码都是基础的,我也是给自己做个记录,不值得你们消费,以后放gitee上下吧。
陆续再更。
更多推荐



所有评论(0)