查看: 157|回复: 1

小熊派BearPi-HM Nano鸿蒙开发板实战:从环境搭建到MQTT物联网通信

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式
对于希望快速入门HarmonyOS设备开发的开发者来说,小熊派BearPi-HM Nano是一款性价比极高的IoT开发板。它基于Hi3861 Wi-Fi SoC芯片,板载NFC、LED、按键、E53扩展接口等资源,配合华为DevEco Device Tool工具链,可以一站式完成代码编写、编译、烧录和调试。本文基于实际开发经验,整理从环境搭建到WiFi连接与MQTT通信的完整流程,并提炼常见问题的解决办法。

一、硬件认知与开发环境搭建
BearPi-HM Nano开发板采用三段式布局:左侧为E53扩展接口,引出GPIO、SPI、I2C、ADC、UART等引脚;中间是Hi3861主控、NFC线圈(用于“碰一碰”配网)和用户LED;右侧是USB Type-C接口(供电兼烧录)、CH340串口芯片、复位键和两个自定义按键。出厂固件上电后红色LED闪烁,若不亮需检查USB线是否为数据线。

开发环境的搭建在2024年以后有了重大简化:HUAWEI DevEco Device Tool 3.1+版本已支持纯Windows环境开发Hi3861,不再依赖Linux虚拟机。纯Windows方案的优势在于:首次编译仅需约2分30秒,一键烧录约30秒,环境配置仅三步——安装DevEco Device Tool、下载源码(推荐通过DevEco Marketplace导入hi3861_hdu_iot_application项目,SDK约413MB)、配置工具链。关键避坑点:Windows路径长度限制260字符,务必把项目放在磁盘根目录(如D:\bearpi_project),否则编译会莫名失败;首次编译会自动下载Python依赖,建议配置国内pip镜像加速。

硬件连接只需一根USB Type-C数据线即可同时实现供电、烧录和调试。烧录时需要将开发板置入烧录模式:按住复位键再上电,保持2秒,串口应打印“###HiBurn###”提示。

二、入门示例:LED闪烁与按键检测
LED控制是最基础的实验。板载红色LED连接GPIO 9,低电平点亮。以下代码使用HarmonyOS的IoTGpio接口实现500ms间隔闪烁:
  1. #include "ohos_init.h"
  2. #include "cmsis_os2.h"
  3. #include "iot_gpio.h"
  4. #include "hi_gpio.h"
  5. #include "hi_io.h"
  6. #define LED_GPIO_PIN 9
  7. static void GpioInit(void)
  8. {
  9.     IoTGpioInit(LED_GPIO_PIN);
  10.     IoTGpioSetDir(LED_GPIO_PIN, IOT_GPIO_DIR_OUT);
  11. }
  12. static void LED_Task(void *arg)
  13. {
  14.     (void)arg;
  15.     GpioInit();
  16.     while (1) {
  17.         IoTGpioSetOutputVal(LED_GPIO_PIN, IOT_GPIO_VALUE0);  // 点亮
  18.         osDelay(50);  // 500ms (10ms × 50)
  19.         IoTGpioSetOutputVal(LED_GPIO_PIN, IOT_GPIO_VALUE1);  // 熄灭
  20.         osDelay(50);
  21.     }
  22. }
  23. static void LED_Entry(void)
  24. {
  25.     osThreadAttr_t attr = {
  26.         .name = "LED_Task",
  27.         .stack_size = 4096,
  28.         .priority = osPriorityNormal,
  29.     };
  30.     osThreadNew(LED_Task, NULL, &attr);
  31. }
  32. SYS_RUN(LED_Entry);
复制代码

代码要点:SYS_RUN()宏使任务在系统启动时自动执行;osDelay()的参数单位是10ms;LED采用低电平驱动设计。

按键检测采用中断方式。KEY1连接GPIO 5,下降沿触发。示例代码在按键按下时翻转LED状态并打印计数值:
  1. #include "ohos_init.h"
  2. #include "cmsis_os2.h"
  3. #include "iot_gpio.h"
  4. #include "hi_gpio.h"
  5. #define KEY1_GPIO 5
  6. #define LED_GPIO 9
  7. static uint32_t key_press_count = 0;
  8. static void Key1_ISR(uint32_t gpioIrqNum)
  9. {
  10.     (void)gpioIrqNum;
  11.     key_press_count++;
  12.     printf("[KEY] Button pressed! Count: %u\r\n", key_press_count);
  13.     static uint8_t led_state = 0;
  14.     led_state = !led_state;
  15.     IoTGpioSetOutputVal(LED_GPIO, led_state ? IOT_GPIO_VALUE1 : IOT_GPIO_VALUE0);
  16. }
  17. static void GpioInterruptInit(void)
  18. {
  19.     IoTGpioInit(KEY1_GPIO);
  20.     IoTGpioInit(LED_GPIO);
  21.     IoTGpioSetDir(KEY1_GPIO, IOT_GPIO_DIR_IN);
  22.     IoTGpioSetDir(LED_GPIO, IOT_GPIO_DIR_OUT);
  23.     IoTGpioRegisterIsrFunc(KEY1_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW, Key1_ISR, NULL);
  24. }
  25. static void KeyDemo_Entry(void)
  26. {
  27.     GpioInterruptInit();
  28.     printf("[KEY Demo] Started. Press KEY1 to toggle LED.\r\n");
  29. }
  30. SYS_RUN(KeyDemo_Entry);
复制代码

调试时可用MobaXterm或PuTTY连接串口,波特率115200,观察按键计数信息。

三、进阶示例:WiFi STA连接与MQTT通信
物联网项目首先需要联网。Hi3861支持STA模式连接到无线路由器。以下代码演示完整流程:注册WiFi事件、使能WiFi、添加热点配置并连接、等待连接成功、获取网络接口并启动DHCP。等待连接超时设置为15秒,DHCP等待约3秒。
  1. #include "ohos_init.h"
  2. #include "cmsis_os2.h"
  3. #include "hi_wifi_api.h"
  4. #include "lwip/netifapi.h"
  5. #include "lwip/sockets.h"
  6. #include <string.h>
  7. #define WIFI_SSID "YourSSID"
  8. #define WIFI_PASSWORD "YourPassword"
  9. static volatile int g_connect_success = 0;
  10. static struct netif *g_lwip_netif = NULL;
  11. static void WifiConnectionHandler(uint8_t state, WifiLinkedInfo *info)
  12. {
  13.     (void)info;
  14.     if (state == WIFI_STATE_CONNECTED) {
  15.         printf("[WiFi] Connected to AP successfully!\r\n");
  16.         g_connect_success = 1;
  17.     } else {
  18.         printf("[WiFi] Disconnected, state: %d\r\n", state);
  19.     }
  20. }
  21. static void WifiScanDoneHandler(uint8_t state, uint8_t size)
  22. {
  23.     (void)state;
  24.     printf("[WiFi] Scan finished, found %d APs\r\n", size);
  25. }
  26. static int WiFiConnect(void)
  27. {
  28.     int ret;
  29.     WifiEvent event = {
  30.         .onWifiConnectionChanged = WifiConnectionHandler,
  31.         .onWifiScanStateChanged = WifiScanDoneHandler,
  32.     };
  33.     ret = RegisterWifiEvent(&event);
  34.     if (ret != WIFI_SUCCESS) return -1;
  35.     ret = EnableWifi();
  36.     if (ret != WIFI_SUCCESS) return -1;
  37.     WifiDeviceConfig config = {0};
  38.     strncpy(config.ssid, WIFI_SSID, sizeof(config.ssid) - 1);
  39.     strncpy(config.password, WIFI_PASSWORD, sizeof(config.password) - 1);
  40.     int networkId = -1;
  41.     ret = AddDeviceConfig(&config, &networkId);
  42.     if (ret != WIFI_SUCCESS || networkId < 0) return -1;
  43.     ret = ConnectTo(networkId);
  44.     if (ret != WIFI_SUCCESS) return -1;
  45.     int wait_count = 0;
  46.     while (!g_connect_success && wait_count < 150) {
  47.         usleep(100000);
  48.         wait_count++;
  49.     }
  50.     if (!g_connect_success) return -1;
  51.     g_lwip_netif = netifapi_netif_find("wlan0");
  52.     if (g_lwip_netif == NULL) return -1;
  53.     netifapi_netif_set_default(g_lwip_netif);
  54.     dhcp_start(g_lwip_netif);
  55.     for (int i = 0; i < 30; i++) {
  56.         osDelay(20);
  57.         if (dhcp_is_bound(g_lwip_netif) == ERR_OK) {
  58.             ip4_addr_t ip, gw, mask;
  59.             netifapi_netif_get_addr(g_lwip_netif, &ip, &netmask, &gw);
  60.             printf("[WiFi] IP: %s\r\n", ip4addr_ntoa(&ip));
  61.             return 0;
  62.         }
  63.     }
  64.     return -1;
  65. }
  66. // 在任务中调用WiFiConnect,成功后即可进行网络操作
复制代码

WiFi连接成功后,即可实现MQTT客户端。以下代码使用Eclipse Paho MQTT C客户端库,连接公共MQTT服务器broker.emqx.io:1883,订阅bearpi/control主题,并每隔2秒向bearpi/temperature发布模拟的传感器数据(JSON格式)。注意MQTT任务栈空间需设置为8192字节。
  1. // 包含MQTTClient.h等
  2. #define MQTT_SERVER_IP "broker.emqx.io"
  3. #define MQTT_SERVER_PORT 1883
  4. #define MQTT_CLIENT_ID "BearPi_Hi3861"
  5. #define MQTT_TOPIC_PUB "bearpi/temperature"
  6. #define MQTT_TOPIC_SUB "bearpi/control"
  7. static MQTTClient mqtt_client;
  8. static Network mqtt_network;
  9. static unsigned char mqtt_send_buf[1024];
  10. static unsigned char mqtt_recv_buf[1024];
  11. static void mqtt_message_arrived(MessageData *msg_data)
  12. {
  13.     if (msg_data == NULL) return;
  14.     printf("[MQTT] Received from topic '%.*s': %.*s\r\n",
  15.            msg_data->topicName->lenstring.len,
  16.            msg_data->topicName->lenstring.data,
  17.            msg_data->message->payloadlen,
  18.            (char *)msg_data->message->payload);
  19. }
  20. static void MqttTask(void)
  21. {
  22.     NetworkInit(&mqtt_network);
  23.     if (NetworkConnect(&mqtt_network, MQTT_SERVER_IP, MQTT_SERVER_PORT) != 0) {
  24.         printf("[MQTT] Network connect failed\r\n");
  25.         return;
  26.     }
  27.     MQTTClientInit(&mqtt_client, &mqtt_network, 3000, mqtt_send_buf, sizeof(mqtt_send_buf), mqtt_recv_buf, sizeof(mqtt_recv_buf));
  28.    
  29.     MQTTPacket_connectData connectData = MQTTPacket_connectData_initializer;
  30.     connectData.keepAliveInterval = 30;
  31.     connectData.cleansession = 1;
  32.     connectData.clientID.cstring = MQTT_CLIENT_ID;
  33.     connectData.username.cstring = "demo";
  34.     connectData.password.cstring = "demo";
  35.    
  36.     if (MQTTConnect(&mqtt_client, &connectData) != SUCCESS) {
  37.         NetworkDisconnect(&mqtt_network);
  38.         return;
  39.     }
  40.     MQTTSubscribe(&mqtt_client, MQTT_TOPIC_SUB, QOS1, mqtt_message_arrived);
  41.    
  42.     int msg_count = 0;
  43.     while (1) {
  44.         float temperature = 25.0f + (msg_count % 20) * 0.5f;
  45.         char payload[64];
  46.         snprintf(payload, sizeof(payload), "{"device":"%s","temp":%.1f,"humidity":%.1f}", MQTT_CLIENT_ID, temperature, 60.0f + msg_count % 30);
  47.         MQTTMessage message = { .qos = QOS1, .retained = 0, .payload = payload, .payloadlen = strlen(payload) };
  48.         MQTTPublish(&mqtt_client, MQTT_TOPIC_PUB, &message);
  49.         osDelay(200);  // 2秒
  50.         msg_count++;
  51.     }
  52. }
  53. // 使用SYS_RUN或创建任务启动MqttTask
复制代码

测试时可在PC端使用MQTTX客户端订阅相同主题,验证设备上报的数据。

四、I2C传感器读取(BH1750光照强度)
开发板的E53接口支持I2C通信。以BH1750为例,初始化I2C0(400KHz),发送连续高分辨率模式命令(0x10),等待150ms后读取2字节数据,换算公式为:光照强度(lux) = raw / 1.2。
  1. #include "hi_i2c.h"
  2. #define BH1750_ADDR 0x23
  3. #define BH1750_CON_H 0x10
  4. static void I2C_Init(void)
  5. {
  6.     hi_i2c_init(HI_I2C_IDX_0, 400000);
  7. }
  8. static int BH1750_ReadLux(float *lux)
  9. {
  10.     hi_u8 send_data[1] = {BH1750_CON_H};
  11.     hi_u8 recv_data[2] = {0};
  12.     if (hi_i2c_write(HI_I2C_IDX_0, BH1750_ADDR, send_data, 1) != HI_ERR_SUCCESS) return -1;
  13.     usleep(150000);
  14.     if (hi_i2c_read(HI_I2C_IDX_0, BH1750_ADDR, NULL, recv_data, 2) != HI_ERR_SUCCESS) return -1;
  15.     hi_u16 raw = (recv_data[0] << 8) | recv_data[1];
  16.     *lux = raw / 1.2f;
  17.     return 0;
  18. }
复制代码

五、常见问题速查
1. 编译报错“toolchain not found”:检查DevEco Device Tool中compiler_bin_path是否指向DevTools_Hi3861V100_v1.0文件夹。
2. 烧录失败“Failed to connect device”:确保开发板进入烧录模式——按住复位键上电后保持2秒,串口输出“###HiBurn###”。
3. WiFi连接成功但无法获取IP:确认路由器开启DHCP;或手动设置静态IP:netifapi_netif_set_addr(g_lwip_netif, &ipaddr, &netmask, &gw)。
4. MQTT连接失败:先确保WiFi已连通且获取到IP;检查服务器地址端口;部分企业网络需使用WebSocket或配置代理。

小熊派BearPi-HM Nano开发板虽然资源有限,但覆盖了Wi-Fi、NFC、GPIO、I2C、SPI、UART等物联网核心能力,配合丰富的E53扩展板和社区例程,是入门HarmonyOS设备开发的理想选择。以上示例代码均可在DevEco Device Tool中直接编译运行,帮助开发者快速实现从LED控制到云端对接的完整项目。
回复

使用道具 举报

发表于 3 小时前 | 显示全部楼层

Re: 小熊派BearPi-HM Nano鸿蒙开发板实战:从环境搭建到MQTT物联网通信

感谢楼主的详细分享!小熊派BearPi-HM Nano这个板子确实很适合入门鸿蒙设备开发,尤其你提到的纯Windows环境搭建方案,省去了装虚拟机的麻烦,对新手太友好了。LED和按键的示例代码也很清晰,我打算照着试一下。 不过帖子在WiFi STA和MQTT通信那里刚好截断了,有点意犹未尽。想请教一下,MQTT部分具体是用的哪个云平台?有没有遇到连接不稳定或者证书加载的问题?如果方便的话,希望能再补充一下MQTT通信的完整流程,比如如何配置WiFi、MQTT客户端的初始化代码,以及和板子上的传感器结合的例子。期待更新!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-5 15:32 , Processed in 0.031474 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部