[TOC]
环境搭建按照小熊派GITEE库中介绍十分钟快速上手搭建
ssh连接后,
打开bearpi文件夹
cd /home/bearpi
创建project文件夹
mkdir project && cd project
hpm init -t default
获取代码
hpm i @bearpi/bearpi_hm_nano
等待1-3分钟(根据不同网速)
当屏幕中出现Installed.
意味着代码获取完成
ssh bearpi@192.168.3.21
其中的IP地址输入虚拟机的IP,输入密码后,SSH连接到虚拟机;
python build.py BearPi-HM_Nano
build successs
,打开桌面的HiBurn,将固件下载到Hi3861开发板中进行验证。打开桌面的HiBurn,选择开发板的com口;
select file 选择编译好的固件,Z:\home\bearpi\project\out\BearPi-HM_Nano
中的Hi3861_wifiiot_app_allinone.bin
勾选上Auto burn
;
点击connect
,然后开发板点击reset
按键重新上电,此时开始下载程序;
在Z:\home\bearpi\project\applications\BearPi\BearPi-HM_Nano\sample
在sample文件夹中新建程序,例如,新家my_app文件夹
在该文件夹中新建程序,进行编译
BUILD.gn 中修改程序
static_library("wificonnect") {
sources = [
"demo1_1.c",
"bsp_usart.c",
]
include_dirs = [
"//utils/native/liteos/include",
"//kernel/liteos_m/components/cmsis/2.0",
"//base/iot_hardware/interfaces/kits/wifiiot_lite",
"//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
"//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
]
}
static_library中 填写该程序的名称
sources中填写 .c文件
include中填写 .h文件的路径
然后在外部文件夹中的BUILD.gn,修改程序,添加文件夹:程序名称
,将不需要编译的程序使用# 注释掉
#"D10_iot_cloud_oc_manhole_cover:cloud_oc_manhole_cover",
#"D11_iot_cloud_oc_infrared:cloud_oc_infrared",
#"D12_iot_cloud_oc_agriculture:cloud_oc_agriculture",
#"D13_iot_cloud_oc_gps:cloud_oc_gps",
# "my_app:myapp",
"demo1_1:wificonnect",
上图表示,只编译demo1_1文件夹中的wificonnect程序。
使用海思的SDK进行编写
#include "hi_gpio.h"
小熊派使用的库底层也是海思的库,只是在上面封装了两层。
参考API手册进行查询和编写,小熊派的程序中查看底层进行重新编写。
Hi3861V100/Hi3861LV100 SDK 开发指南
Hi3861V100/Hi3861LV100 Wi-Fi 软件开发指南
查询这几个文档进行编写
在使用hi3861进行串口通信时,使用串口1,串口0用于打印log,发送数据时会自动原样发送回来,没有该功能软件的开关,因此使用串口1
在使用串口1进行数据收发时,开发板连接TTL转串口模块时,无法下载程序,也无法正常重启
这是由于
其中IO6为UART1_TXD ,连接TTL转USB时,会置高,因此在后续使用时,先给hi3861上电,再UART1初始化。使模组可以进入正常工作状态。
代码存放位置为demo1、 demo2、demo3
创建LED闪烁任务,50ms闪烁一次
static void LedTask(void)
{
while (1)
{
WhiteLedOn();
osDelay(50);
WhiteLedOff();
osDelay(50);
}
}
/*entry 加入,登记 */
static void LedEntry(void)
{
osThreadAttr_t attr;
attr.name = "LedTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 4096;
attr.priority = osPriorityNormal;
if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL)
{
printf("[LedEntry] Falied to create LedTask!\n");
}
}
控制LED灯的GPIO口初始化设置
/* LED灯 GPIO初始化 */
void LED_INIT(void)
{
//设置GPIO_2引脚为输出模式
hi_gpio_init();
/* 设置IO复用功能 */
hi_io_set_func(HI_IO_NAME_GPIO_12 , HI_IO_FUNC_GPIO_12_GPIO);
hi_io_set_func(HI_IO_NAME_GPIO_2 , HI_IO_FUNC_GPIO_2_GPIO);
/* 设置IO为输出模式 */
hi_gpio_set_dir(HI_GPIO_IDX_12, HI_GPIO_DIR_OUT);
hi_gpio_set_dir(HI_GPIO_IDX_2, HI_GPIO_DIR_OUT);
}
查询SDK手册进行编写,先进行GPIO初始化,然后选择GPIO口的功能,然后设置IO的输出/输出模式。
控制LED灯亮灭,使用hi_gpio_set_ouput_val(HI_GPIO_IDX_12, HI_GPIO_VALUE1) ;
/* 绿灯亮 */
void GreenLedOn(void)
{
hi_gpio_set_ouput_val(HI_GPIO_IDX_12, HI_GPIO_VALUE1) ;
printf("GreenLedOn ! \r\n");
}
/* 绿灯灭 */
void GreenLedOff(void)
{
hi_gpio_set_ouput_val(HI_GPIO_IDX_12, HI_GPIO_VALUE0) ;
printf("GreenLedOff ! \r\n");
}
任务创建后,上电后,LED灯开始闪烁。
定义串口收发BUF,由于存放数据。
/* 串口1收发buf */
uint8_t sendBuf[UART_BUFF_SIZE]={0};
uint8_t *sendBuf_ptr = sendBuf;
uint8_t recvBuf[UART_BUFF_SIZE]={0};
uint8_t *recvBuf_ptr = recvBuf;
初始化串口,使用串口1进行数据收发,
初始化完成后,在while循环中处理收到的数据,
使用switch case 处理command
指令
收到指令后,并且回复串口指令, Usart_SendArray(sendBuf,10);
。
/* 串口1 任务 */
static void UART_Task(void)
{
uint32_t ret;
uint32_t command;
/* 串口设置 */
WifiIotUartAttribute uart_attr =
{
.baudRate = 115200,
.dataBits = 8,
.stopBits = 1,
.parity = 0,
};
/* 初始化串口 */
ret = UartInit(WIFI_IOT_UART_IDX_1, &uart_attr, NULL);
if (ret != WIFI_IOT_SUCCESS)
{
printf("Failed to init uart! Err code = %d\n", ret);
return;
}
printf("UART Test Start\n");
while (1)
{
/* 通过串口1接收数据 */
UartRead(WIFI_IOT_UART_IDX_1, recvBuf_ptr, UART_BUFF_SIZE);
//usleep(5000);
/* 串口指令控制LED灯亮灭 */
command = recvBuf[1];
command = (command <<8) + recvBuf[2];
switch(command)
{
case LEDON:
GreenLedOn();
sendBuf[0] = 0x11;
Usart_SendArray(sendBuf,10);
break;
case LEDOFF:
GreenLedOff();
break;
default:
break;
}
}
}
GPIO外部中断控制,按照下面流程初始化设置
设置完成后,在主函数中调用KEY_INIT
void KEY_INIT(void)
{
/* 初始化F1按键,设置为下降沿触发中断 */
/* 设置按键的GPIO复用功能为GPIO */
hi_io_set_func(HI_GPIO_IDX_7,HI_IO_FUNC_GPIO_7_GPIO);
/* 设置按键GPIO为输入模式 */
hi_gpio_set_dir(HI_GPIO_IDX_7, HI_GPIO_DIR_IN);
/* 设置上拉输入 */
hi_io_set_pull(HI_GPIO_IDX_7,HI_IO_PULL_UP);
/* 设置终端回调函数 */
//hi_gpio_register_isr_function
/* 中断回调函数前加(gpio_isr_callback)类型转换 */
hi_gpio_register_isr_function(HI_GPIO_IDX_7,HI_INT_TYPE_EDGE,HI_GPIO_EDGE_FALL_LEVEL_LOW, (gpio_isr_callback)KEY_Pressed, NULL ) ;
//GpioRegisterIsrFunc(HI_GPIO_IDX_7,HI_INT_TYPE_EDGE,HI_GPIO_EDGE_FALL_LEVEL_LOW, KEY_Pressed, NULL) ;
}
注意,在使用hi库的hi_gpio_register_isr_function
中的中断回调函数前,应加(gpio_isr_callback)
进函数类型转换,否则会出错。
中断回调函数
static volatile hi_gpio_value led_value = HI_GPIO_VALUE0 ;
/* GPIO 中断回调函数 */
void KEY_Pressed(char *arg)
{
(void) arg;
led_value = !led_value;
hi_gpio_set_ouput_val(HI_GPIO_IDX_12, led_value);
}
按下按键时,led灯的电平引脚进行翻转。
当使用串口调试助手时,RTS勾选上时,开发板按reset按键无法进行重启
原因是:
安信可的开发板上RTS连接着PWRON引脚,导致无法被拉低,无法重启。
将串口调试助手中的RTS取消勾选,即可按键重启了。
SSID 服务集标识符(Service Set IDendifier),用于标识不同的网络,即网络的名称
AP 接入点(Access Point),是允许其他无线设备连接的设备。
STA 工作站(Station) ,WIFI设备。
WPA WIFI访问包含,是一种保护无线网络访问安全的技术,目前有WPA,WPA2,WPA3三种标准
Frequency 频段,无线网络是使用无线电波进行通信的。IEEE 802.11协议中定义了不同的频段,如2.4GHz,3.6GHz,4.9GHz,5.8GHz。
Channel 信道。每个频段又被分为若干信道
Band 频带,目前HarmonyOS定义的频带有2G和5G两种
wifi_connect.c
中的函数进行连接static void UDPClientTask(void)
{
WifiConnect("653","123456789");
}
static void UDPClientDemo(void)
{
osThreadAttr_t attr;
attr.name = "UDPClientTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 10240;
attr.priority = osPriorityNormal;
if (osThreadNew((osThreadFunc_t)UDPClientTask, NULL, &attr) == NULL)
{
printf("[UDPClientDemo] Falied to create UDPClientTask!\n");
}
}
也需要创建任务中执行WifiConnect("653","123456789");
WiFiInit();
EnableWifi();
WiFiInit();
函数中进行wifi事件event的注册
EnableWifi();
函数进行wifi的使能,其中
会进行以下操作
/* 设置wifi模块为STA模式 */
hiRet = hi_wifi_sta_start(ifName, &len);
/* 设置wifi模块断线自动重新连接 */
hiRet = hi_wifi_sta_set_reconnect_policy(WIFI_RECONN_POLICY_ENABLE, WIFI_RECONN_POLICY_TIMEOUT,
WIFI_RECONN_POLICY_PERIOD, WIFI_RECONN_POLICY_MAX_TRY_COUNT);
因此不需要在外部重复设置自动重连。
==注意:==
如果需要自动重连能够正常执行,应该保证WIFI连接步骤中,DHCP功能的执行,
因此
先启动DHCP
设置模块IP地址
等待DHCP设置完成,输出连接信息
/* 启动DHCP */
if (g_lwip_netif)
{
dhcp_start(g_lwip_netif);
printf("begain to dhcp");
}
/* 设置静态IP地址 */
hi_sta_set_addr(g_lwip_netif);
/* 等待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;
}
printf("<-- DHCP state:Inprogress -->\r\n");
osDelay(100);
}
串口输出模块连接状态log
[11:50:30.081]收←◆<-- DHCP state:Inprogress -->
[11:50:31.078]收←◆<-- DHCP state:OK -->
server :
server_id : 192.168.1.1
mask : 255.255.255.0, 1
gw : 192.168.1.1
T0 : 86400
T1 : 43200
T2 : 75600
clients <1> :
mac_idx mac addr state lease tries rto
0 94c9601e1a28 192.168.1.110 10 0 1 3
设置连接WIFI后的IP地址的函数hi_sta_set_addr(struct netif *pst_lwip_netif)
,
static void hi_sta_set_addr(struct netif *pst_lwip_netif)
{
//struct netif *pst_lwip_netif;
ip4_addr_t st_gw;
ip4_addr_t st_ipaddr;
ip4_addr_t st_netmask;
printf("%s %d \r\n", __FILE__, __LINE__);
if (pst_lwip_netif == NULL) {
printf("hisi_reset_addr::Null param of netdev\r\n");
return;
}
IP4_ADDR(&st_gw, 192, 168, 1, 1);
IP4_ADDR(&st_ipaddr, 192, 168, 1, 6);
IP4_ADDR(&st_netmask, 255, 255, 255, 0);
netifapi_netif_set_addr(pst_lwip_netif, &st_ipaddr, &st_netmask, &st_gw);
}
设置完成后,上电后连接WIFI后,将自动连接WIFI,连接成功后,设置模块自身的IP地址。
C:\Users\10512>ping 192.168.1.6
正在 Ping 192.168.1.6 具有 32 字节的数据:
来自 192.168.1.6 的回复: 字节=32 时间=16ms TTL=255
来自 192.168.1.6 的回复: 字节=32 时间=1ms TTL=255
来自 192.168.1.6 的回复: 字节=32 时间=2ms TTL=255
来自 192.168.1.6 的回复: 字节=32 时间=2ms TTL=255
192.168.1.6 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 1ms,最长 = 16ms,平均 = 5ms
timer 文件夹中为定时器文件,创建一个定时器,定时检测WIFI的连接状态,通过指示灯进行显示,wifi连接后,指示灯亮,wifi断开连接后,指示灯灭;
usart 文件夹中为串口文件,创建一个串口,接收和发送串口指令
还包括GPIO控制指示灯的相关函数;
按键中断设置
wifi 文件夹中为WIFI连接程序,调用其中的函数进行wifi连接
mymain.c 文件为主程序,其中mymain()为主函数,程序从此开始运行
BUILD.gn 编译文件,在其中将上述头文件所在文件夹和.c源文件添加到其中
static_library("demo4") {
sources = [
"mymain.c",
"usart/bsp_usart.c",
"wifi/wifi_connect.c",
"timer/bsp_timer.c",
]
include_dirs = [
"usart",
"wifi",
"timer",
"//utils/native/liteos/include",
"//kernel/liteos_m/components/cmsis/2.0",
"//base/iot_hardware/interfaces/kits/wifiiot_lite",
"//foundation/communication/interfaces/kits/wifi_lite/wifiservice",
"//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/",
]
}
在timer文件中创建一个timer定时器,每3s检测一次wifi的连接状态
==注意==
不要在定时器的回调函数中检测状态,否则会报警告
可以在回调函数中设置标志位,在外部函数中进行检测
/* 定时器定时时间到标志 */
uint8_t timerOverFlag = 0;
/***** 定时器1 回调函数 *****/
void Timer1_Callback(void *arg)
{
(void)arg;
timerOverFlag = 1;
}
在外部函数中检测,当wifi连接正常时,红灯亮,当wifi断开连接时,红灯灭。
/* WIFI连接 任务*/
static void UDPClientTask(void)
{
hi_wifi_status mywifi_status;
WifiConnect("653","123456789");
while (1)
{
if(hi_wifi_sta_get_connect_info(&mywifi_status)== HISI_OK &&timerOverFlag == 1 )
{
timerOverFlag = 0;
if(mywifi_status.status == HI_WIFI_DISCONNECTED)
{
RedLedOff();
}
else
{
RedLedOn();
}
}
}
}
功能实现: demo5
/* 创建socket */
if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
perror("create socket failed!\r\n");
exit(1);
}
/* 初始化模块自身监听的IP地址和端口,用于接收数据 */
recv_addr.sin_family = AF_INET;
recv_addr.sin_port = htons(_PROT_);
recv_addr.sin_addr.s_addr = inet_addr("192.168.1.110");
addr_rexv_length = sizeof(recv_addr);
/* 监听模块自身的IP和PORT */
if (bind(sock_fd, (struct sockaddr *)&recv_addr, sizeof(recv_addr)) == -1)
{
perror("bind is error\r\n");
exit(1);
}
sendto(sock_fd, send_data, strlen(send_data), 0, (struct sockaddr *)&send_addr, addr_length);
recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&recv_addr, &addr_length_recv);
recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&recv_addr, &addr_length_recv);
网络调试助手按图中设置
当收到LEDON的数据时,绿灯亮,然后通过UDP发送ledon的字符数组
/* 接收服务端发送的字符串 */
recvfrom(sock_fd, recvBuf, sizeof(recvBuf), 0, (struct sockaddr *)&recv_addr, &addr_rexv_length);
/* 串口指令控制LED灯亮灭 */
wifi_command = recvBuf[1];
wifi_command = (wifi_command <<8) + recvBuf[2];
switch(wifi_command)
{
case LEDON:
GreenLedOn();
sendto(sock_fd, ledon, strlen(ledon), 0, (struct sockaddr *)&send_addr, addr_length);
break;
case LEDOFF:
GreenLedOff();
sendto(sock_fd, ledoff, strlen(ledoff), 0, (struct sockaddr *)&send_addr, addr_length);
break;
default:
break;
}
/* 关闭这个 socket */
/* 不关闭这个socket , 持续接收数据 */
//closesocket(sock_fd);
在没有开启UDP通信之前,可以实现定时检测WIFI连接状态,断线自动重连,
目前将UDP通信功能和上述功能放置在一个任务的while中时,功能异常,后续需要进行修改。
串口1收到的串口信息原样,通过UDP透传出去。优先完成。
为测试安信可Hi-12F模块功能,设计测试板进行测试
设计两路串口 一路用于串口通信,另一路用于下载程序
设计低功耗唤醒GPIO,WAKEUP引脚,使用此引脚唤醒模块进入工作模式。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。