hi3863 (ws63) 智能小车 (二)信息交互

首先实现与小车的信息交互功能。

把信息交互分为2个部分,小车端,主机控制端。

首先假设一下使用场景:

小车独立开始运行测试的时候,就没办法通过串口接收到小车的运行信息了。

在小车调试中,在小车旁边可以遥控器给小车发送简单指令,比如设置小车的速度,探测距离。小车将运行结果通过OLED模块显示出来。

在小车运行中,人就没办法在旁边干预了,就通过WiFi网络发送接收信息。

一般情况小车应用都是比较复杂的,数据上传PC才能处理。在有些实验场景下,是没有固定的WiFi网络提供的,没法给小车预设WiFi信息。比如参与一个竞赛,临时做一些适应场地的设置。

做了一堆尝试,最后确定下来这样一个结构。

我有一个模块作为控制端的接收和发送,开启WiFi 站点模式,通过串口与计算机连接。为下一步连接多台小车做准备。

PC机通过串口与控制端模块连接,发送指令控制这个模块的发送接收信息。

小车通过遥控器开启AP 热点模式,开启网络UDP服务端模式,接收到信息就对发送来信息的地址回传信息。

主要的代码

Hi3863 WiFi AP 热点开启

cpp 复制代码
/**
 * 
 * wifi ap
 * 
 * 2025 12 21
 * 
 **/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "cmsis_os2.h"

#include "wifi_event.h"
#include "wifi_device.h"
#include "wifi_device_config.h"
#include "wifi_hotspot.h"
#include "wifi_hotspot_config.h"

#include "err.h"
#include "lwip/netifapi.h"
#include "lwip/ip_addr.h"

#include "ap_start.h"

static struct netif *ap_netif = NULL;      // 网络接口

// static char ap_name[10] = "Didi";        // ssid
// static char ap_pass[10] = "123456789";   // key

// 1.1 Softap 状态
static void WiFi_Event_Softap_State(int32_t state)
{
    osal_printk(" [WiFi_Event_Softap_State] \r\n");
    osal_printk(" softap state : %d \r\n", state);
}

// 1.2 Softap 加入
static void WiFi_Event_Softap_Join(const wifi_sta_info_stru *info)
{
    unused(info);
    osal_printk(" [WiFi_Event_Softap_Join] \r\n");
}

// 1.3 Softap 离开
static void WiFi_Event_Softap_State_Leave(const wifi_sta_info_stru *info)
{
    unused(info);
    osal_printk(" [WiFi_Event_Softap_State_Leave] \r\n");
}

// 1. WiFi 事件回调
static wifi_event_stru WiFi_Event_Callback = {
    .wifi_event_softap_state_changed = WiFi_Event_Softap_State,
    .wifi_event_softap_sta_join = WiFi_Event_Softap_Join,
    .wifi_event_softap_sta_leave = WiFi_Event_Softap_State_Leave,   
};


// ap 启动
uint8_t AP_Start(char *ap_name, char *ap_pass, char *ap_addr)
{
    // 1. 注册 WiFi 事件回调
    if (wifi_register_event_cb(&WiFi_Event_Callback) != ERRCODE_SUCC) 
    {
        osal_printk(" [AP_Start] 1. wifi_register_event_cb FAILURE! \r\n");
        return 0;
    }

    // 等待WiFi初始完成
    while (wifi_is_wifi_inited() == 0)
    {
        (void)osDelay(10);
    }

    // ap 扩展配置
    softap_config_advance_stru ap_config_advance = {0};

    ap_config_advance.beacon_interval = 100;
    ap_config_advance.dtim_period = 2;
    ap_config_advance.gi = 0;
    ap_config_advance.group_rekey = 86400;
    ap_config_advance.protocol_mode = 4;
    ap_config_advance.hidden_ssid_flag = 1;

    // 2.1 配置SoftAP
    if (wifi_set_softap_config_advance(&ap_config_advance) != ERRCODE_SUCC) 
    {
        osal_printk(" [AP_Start] 2.1 wifi_set_softap_config_advance FAILURE! \r\n");
        return 0;
    }

    // ap 配置
    softap_config_stru ap_config = {0};

    (void)memcpy_s(ap_config.ssid, sizeof(ap_config.ssid), ap_name, strlen(ap_name));
    (void)memcpy_s(ap_config.pre_shared_key, WIFI_MAX_KEY_LEN, ap_pass, strlen(ap_pass));
    ap_config.security_type = 3;
    ap_config.channel_num = 13;
    ap_config.wifi_psk_type = 0;

    // 2.2 开启SoftAP
    if (wifi_softap_enable(&ap_config) != ERRCODE_SUCC) 
    {
        osal_printk(" [AP_Start] 2.2 wifi_softap_enable FAILURE! \r\n");
        return 0;
    }
    
    // 网口名 默认值
    char ifname[WIFI_IFNAME_MAX_SIZE + 1] = "ap0";

    // 3.1 获取网络接口
    ap_netif = netif_find(ifname);

    if (ap_netif == NULL)
    {
        osal_printk(" [AP_Start] 3.1 netif_find FAILURE! \r\n");
        return 0;
    }

    ip4_addr_t local_ipaddr;
    ip4_addr_t local_netmask;
    ip4_addr_t local_gw;

    IP4_ADDR(&local_ipaddr, 192, 168, 55, 1);
    IP4_ADDR(&local_netmask, 255, 255, 255, 0);
    IP4_ADDR(&local_gw, 192, 168, 55, 2);

    // 3.2 设置地址
    if (netifapi_netif_set_addr(ap_netif, &local_ipaddr, &local_netmask, &local_gw) != ERR_OK) 
    {
        osal_printk(" [AP_Start] 3.2 netifapi_netif_set_addr FAILURE! \r\n");
        return 0;
    }

    // 3.3 dhcp 启动
    if (netifapi_dhcps_start(ap_netif, NULL, 0) != ERR_OK) 
    {
        osal_printk(" [AP_Start] 3.3 netifapi_dhcps_start FAILURE! \r\n");
        return 0;
    }

    // 查看分配的IP地址

    ip4_addr_t ap_ipaddr;     // ip 地址
    ip4_addr_t ap_netmask;    // 掩码
    ip4_addr_t ap_gw;         // 网关

    IP4_ADDR(&ap_ipaddr, 0, 0, 0, 0);
    IP4_ADDR(&ap_netmask, 0, 0, 0, 0);
    IP4_ADDR(&ap_gw, 0, 0, 0, 0);

    (void)netifapi_netif_get_addr(ap_netif, &ap_ipaddr, &ap_netmask, &ap_gw);

    // 打印地址信息

    // osal_printk("\r\n ---- [ ap netif addr ] ---- \r\n");
    // osal_printk(" ap ip: %s \r\n", ip4addr_ntoa(&ap_ipaddr));
    // osal_printk(" ap gw: %s \r\n", ip4addr_ntoa(&ap_gw));
    // osal_printk(" ap netmask: %s \r\n", ip4addr_ntoa(&ap_netmask));
    // osal_printk(" ---- ---- ---- ---- \r\n");

    // 回传 地址
    strcpy(ap_addr, ip4addr_ntoa(&ap_ipaddr));

    osal_printk(" [AP_Start] SUCCESS. \r\n");

    return 1;
}

hi3863 WiFi STA 站点模式 开启

cpp 复制代码
/**
 * 
 *  wifi sta
 * 
 *  2025 12 21
 * 
 **/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "cmsis_os2.h"

#include "wifi_event.h"
#include "wifi_device.h"
#include "wifi_device_config.h"
#include "wifi_hotspot.h"
#include "wifi_hotspot_config.h"

#include "err.h"
#include "lwip/netifapi.h"
#include "lwip/ip_addr.h"

#include "sta_start.h"


static uint8_t conn_stat = 0;       // 连接状态
static uint8_t scan_stat = 0;       // 扫描状态

struct netif *sta_netif = 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;

    osal_printk(" [ WiFi_Conn_State_Changed_Callback ] state = %d \r\n", state);

    if(state != 0)
    {
        conn_stat = 1;
    }

    return;
}

// 扫描状态改变 回调
static void WiFi_Scan_State_Changed_Callback(int32_t state, int32_t size)
{
    (void)state;
    (void)size;

    osal_printk(" [ WiFi_Scan_State_Changed_Callback ] state = %d \r\n", state);

    scan_stat = 1;

    return;
}


// WiFi 事件 回调
static 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,              // 扫描状态改变

};

// sta 启动
uint8_t STA_Start(char *ap_name, char *ap_pass, char *sta_addr)
{
    // 1. 注册事件回调
    if(wifi_register_event_cb(&WiFi_Event_Callback) != ERRCODE_SUCC)
    {
        osal_printk(" [STA_Start] 1. wifi_register_event_cb FAILURE! \n");
        return 0;
    }

    // 获取 WiFi 设备初始化状态
    while(wifi_is_wifi_inited() != 1)
    {
        (void)osDelay(20);
    }

    // 2.1 开启 STA
    if(wifi_sta_enable() != ERRCODE_SUCC)
    {
        osal_printk(" [STA_Start] 2.1 wifi_sta_enable FAILURE! \n");  
        return 0;
    }

    // 2.2 进行全信道基础扫描
    if(wifi_sta_scan() != ERRCODE_SUCC)
    {
        osal_printk(" [STA_Start] 2.2 wifi_sta_scan FAILURE! \n");   
        return 0;
    }

    // 等待 扫描状态改变
    while(scan_stat != 1)
    {
        (void)osDelay(20);
    }

    // 最大扫描数
    uint32_t ap_num = 16;

    // 扫描信息大小
    uint32_t scan_info_size = sizeof(wifi_scan_info_stru) * ap_num;

    // 2.3 分配存储空间
    wifi_scan_info_stru *result = osal_kmalloc(scan_info_size, OSAL_GFP_ATOMIC);

    // 分配 失败
    if(result == NULL)
    {
        osal_printk(" [STA_Start] 2.3 osal_kmalloc FAILURE! \n");   
        return 0;
    }

    // 空间清零
    memset_s(result, scan_info_size, 0, scan_info_size);

    // 2.4 获取sta扫描结果
    if(wifi_sta_get_scan_info(result, &ap_num) != ERRCODE_SUCC)
    {
        osal_kfree(result);
        osal_printk(" [STA_Start] 2.4 wifi_sta_get_scan_info FAILURE! \n");  
        return 0;
    }

    uint8_t ap_find = 0;    // ap 查找 结果 
    uint8_t idx;            // 序号

    // 检索 热点名
    for(idx = 0; idx < ap_num; idx++)
    {
        osal_printk(" result[idx].ssid = %s \r\n", result[idx].ssid);

        if(strlen(ap_name) == strlen(result[idx].ssid))
        {
            if(memcmp(ap_name, result[idx].ssid, strlen(ap_name)) == 0)
            {
                ap_find = 1;
                break;
            }
        }
    }

    // 2.5 未检索到 热点
    if(ap_find == 0)
    {
        osal_kfree(result);
        osal_printk(" [STA_Start] 2.5 ap_find == 0 FAILURE! \n"); 
        return 0;
    }

    // 连接 AP 的 STA 配置信息
    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;  // IP的分配类型

    osal_kfree(result);

    // 连接到 WiFi AP 热点
    if(wifi_sta_connect(&sta_config) != ERRCODE_SUCC)
    {
        osal_printk(" [STA_Start] 2.6 wifi_sta_connect FAILURE! \n");
        return 0;
    }

    // 等待 连接状态改变
    while(conn_stat != 1)
    {
        (void)osDelay(20);
    }

    // 网络 接口 名
    char if_name[WIFI_IFNAME_MAX_SIZE + 1] = "wlan0";

    // 3.1 获取 网络接口信息
    sta_netif = netifapi_netif_find(if_name);

    // 网络接口信息 为空
    if(sta_netif == NULL)
    {
        osal_printk(" [STA_Start] 3.1 netifapi_netif_find FAILURE! \n"); 
        return 0;
    }

    // 3.2 开启 DHCP
    if(netifapi_dhcp_start(sta_netif) != ERR_OK)
    {
        osal_printk(" [STA_Start] 3.2 netifapi_dhcp_start FAILURE! \n"); 
        return 0;
    }

    // 等待协商完成
    while(netifapi_dhcp_is_bound(sta_netif) != ERR_OK)
    {
        (void)osDelay(20);
    }
    
    // 查看分配的IP地址

    ip4_addr_t sta_ipaddr;     // ip 地址
    ip4_addr_t sta_netmask;    // 掩码
    ip4_addr_t sta_gw;         // 网关

    IP4_ADDR(&sta_ipaddr, 0, 0, 0, 0);
    IP4_ADDR(&sta_netmask, 0, 0, 0, 0);
    IP4_ADDR(&sta_gw, 0, 0, 0, 0);

    (void)netifapi_netif_get_addr(sta_netif, &sta_ipaddr, &sta_netmask, &sta_gw);

    // 打印地址信息

    // ip_addr_t addr;

    osal_printk("\r\n ---- [ sta netif addr ] ---- \r\n");
    osal_printk(" sta ip: %s \r\n", ip4addr_ntoa(&sta_ipaddr));
    osal_printk(" sta netmask: %s \r\n", ip4addr_ntoa(&sta_netmask));
    osal_printk(" sta gw: %s \r\n", ip4addr_ntoa(&sta_gw));
    osal_printk(" ---- ---- ---- ---- \r\n");

    // 回传 地址
    strcpy(sta_addr, ip4addr_ntoa(&sta_ipaddr));

    osal_printk(" [STA_Start] 0. SUCCESS. \n");  

    return 1;
}

网络 UDP Server 端

cpp 复制代码
/**
 * 
 *  hi3863
 * 
 *  UDP网络通讯 服务端
 * 
 *  2025 12 21
 *  
 **/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "cmsis_os2.h"

#include "lwip/ip_addr.h"
#include "lwip/netifapi.h"
#include "lwip/sockets.h"
#include "lwip/err.h"

#include "udp_server.h"

static int server_socket = -1;

static struct sockaddr_in client_addr;
static socklen_t client_addr_size = sizeof(client_addr);


// udp server 创建
uint8_t UDP_Server_Create(char *server_ip, int server_port)
{
    // 1. 创建 socket
    server_socket = lwip_socket(AF_INET, SOCK_DGRAM, 0);

    if(server_socket == -1)
    {
        osal_printk(" [UDP_Server_Create] 1. lwip_socket FAILURE! \r\n");
        return 0;
    }

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(server_port);
    server_addr.sin_addr.s_addr = inet_addr(server_ip);

    // 2. 绑定 网络 信息
    if(lwip_bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
    {
        osal_printk(" [UDP_Server_Create] 2. lwip_bind FAILURE! \r\n");
        return 0;
    }

    osal_printk(" [UDP_Server_Create] SUCCESS. \r\n");

    return 1;
}


// udp 接收 数据
uint8_t UDP_Server_Recv_Data(uint8_t *recv_buff, uint8_t buff_len)
{
    ssize_t len = lwip_recvfrom(server_socket, recv_buff, (size_t)buff_len, MSG_DONTWAIT, (struct sockaddr *)&client_addr, &client_addr_size);
    
    if(len == -1)
    {
        return 0;
    }

    osal_printk(" UDP Recv Data : %d \r\n", len);

    return (uint8_t)len;
}


// udp 发送 数据
uint8_t UDP_Server_Send_Data(uint8_t *send_buff, uint8_t buff_len)
{
    ssize_t len = lwip_sendto(server_socket, send_buff, (size_t)buff_len, MSG_DONTWAIT, (struct sockaddr *)&client_addr, client_addr_size);
    
    if(len == -1)
    {
        return 0;
    }

    osal_printk(" UDP Send Data : %d \r\n", len);

    return (uint8_t)len;     
}


// udp server 关闭 
void UDP_Server_Close(void)
{
    if(server_socket != -1)
    {
        lwip_close(server_socket);
        osDelay(20);
        server_socket = -1;

        osal_printk(" [UDP_Server_Close ] \r\n");
    }
}

网络 UDP Client 端

cpp 复制代码
/**
 * 
 *  hi3863
 * 
 *  UDP网络通讯 客户端
 * 
 *  2025 12 20 
 *  
 **/ 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "cmsis_os2.h"

#include "lwip/ip_addr.h"
#include "lwip/netifapi.h"
#include "lwip/sockets.h"
#include "lwip/err.h"

#include "udp_client.h"


static int client_socket = -1;

static struct sockaddr_in server_addr;
static socklen_t server_addr_size = sizeof(server_addr);


// udp client 创建
uint8_t UDP_Client_Create(char *server_ip, int server_port)
{
    // 1. 创建 socket
    client_socket = lwip_socket(AF_INET, SOCK_DGRAM, 0);

    if(client_socket == -1)
    {
        osal_printk(" [UDP_Client_Create] 1. lwip_socket FAILURE! \r\n");
        return 0;
    }

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(server_port);
    server_addr.sin_addr.s_addr = inet_addr(server_ip);
    server_addr_size = sizeof(server_addr);

    osal_printk(" [UDP_Client_Create] 0. SUCCESS. \r\n");

    return 1;
}


// udp 接收 数据
uint8_t UDP_Client_Recv_Data(uint8_t *recv_buff, uint8_t buff_len)
{
    ssize_t len = lwip_recvfrom(client_socket, recv_buff, (size_t)buff_len, MSG_DONTWAIT, NULL, 0);
    
    if(len == -1)
    {
        return 0;
    }

    osal_printk(" UDP Recv Data : %d \r\n", len);

    return (uint8_t)len;
}


// udp 发送 数据
uint8_t UDP_Client_Send_Data(uint8_t *send_buff, uint8_t buff_len)
{
    ssize_t len = lwip_sendto(client_socket, send_buff, (size_t)buff_len, MSG_DONTWAIT, (struct sockaddr *)&server_addr, server_addr_size);
    
    if(len == -1)
    {
        return 0;
    }

    osal_printk(" UDP Send Data : %d \r\n", len);

    return (uint8_t)len;     
}

// udp 关闭 socket
void UDP_Client_Close(void)
{
    if(client_socket != -1)
    {
        lwip_close(client_socket);
        osDelay(20);
        client_socket = -1;
    }

    osal_printk(" [UDP_Client_Close] \r\n");
}

hi3863 串口通信

cpp 复制代码
/**
 * 
 *  hi3863
 * 
 *  串口通讯
 * 
 *  2025 12 21
 * 
 **/ 

#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"

#include "watchdog.h"
#include "pinctrl.h"
#include "gpio.h"
#include "uart.h"

#include "uart_comm.h"


#define BAUD_RATE           115200                  // 波特率
#define DATA_BITS           UART_DATA_BIT_8         // uart_data_bit_t UART数据位为8-bit
#define STOP_BITS           UART_STOP_BIT_1         // uart_stop_bit_t UART停止位为1-bit
#define PARITY              UART_PARITY_NONE        // uart_parity_t   UART无奇偶校验


// 串口 接收 缓存
static uint8_t uart_buffer[UART_BUFF_SIZE] = {0};

// 串口 接收 标志 接收数据的长度
static uint16_t uart_rx_len = 0;


// 串口 接收 回调
static void UART_RX_Callback(const void *buffer, uint16_t length, bool error)
{
    unused(error);

    if (buffer == NULL || length == 0)
    {
        return;
    }

    // 接收到 length 个数据
    uart_rx_len = length;
}


// 串口 初始化 成功 返回 0 失败 返回 错误代码
uint8_t UART_Pin_Init(void)
{    
    // 设置引脚复用模式
    uapi_pin_set_mode(UART_TX_PIN, PIN_MODE_1);
    uapi_pin_set_mode(UART_RX_PIN, PIN_MODE_1);

    // UART PIN 配置
    uart_pin_config_t pin_config = {
        .tx_pin = UART_TX_PIN,          // 发送引脚
        .rx_pin = UART_RX_PIN,          // 接收引脚
        .cts_pin = PIN_NONE,            // 发送就绪引脚
        .rts_pin = PIN_NONE             // 接收就绪引脚
    };

    // UART 基本属性定义
    uart_attr_t attr = {
        .baud_rate = BAUD_RATE,         // UART 波特率
        .data_bits = DATA_BITS,         // UART 数据位
        .stop_bits = STOP_BITS,         // UART 停止位
        .parity = PARITY                // UART 奇偶校验位
    };

    // UART 缓存数据结构定义
    uart_buffer_config_t buffer_config = {
        .rx_buffer = uart_buffer,           // 接收数据的 buffer 指针
        .rx_buffer_size = UART_BUFF_SIZE    // 接收 Buffer 的长度
    };

    // 1. 去初始化指定的串口 在初始化前先去初始化
    if(uapi_uart_deinit(UART_BUS_ID) != ERRCODE_SUCC)
    {
        osal_printk(" [UART_Pin_Init] 1. uapi_uart_deinit FAILURE! \r\n");
        return 0;
    }

    // 2. 初始化指定的串口
    if(uapi_uart_init(UART_BUS_ID, &pin_config, &attr, NULL, &buffer_config) != ERRCODE_SUCC)
    {
        osal_printk(" [UART_Pin_Init] 2. uapi_uart_init FAILURE! \n");
        return 0;
    }

    // 3. 注册接收回调函数 
    if(uapi_uart_register_rx_callback(UART_BUS_ID, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE, 1, UART_RX_Callback) != ERRCODE_SUCC)
    {
        osal_printk(" [UART_Pin_Init] 3. uapi_uart_register_rx_callback FAILURE! \n");
        return 0;
    }

    osal_printk(" [UART_Pin_Init] 0. SUCCESS. \r\n");

    return 1;
}


// 串口 去初始化
void UART_Pin_Deinit(void)
{
    (void)uapi_uart_deinit(UART_BUS_ID);

    uapi_pin_set_mode(UART_TX_PIN, HAL_PIO_FUNC_GPIO);
    uapi_pin_set_mode(UART_RX_PIN, HAL_PIO_FUNC_GPIO);
}


// 串口 读取收到数据 有数据 返回 数据长度 没有数据 返回 0
uint8_t UART_Read_Data(uint8_t *buff, uint8_t size)
{
    uint8_t len = (uint8_t)uart_rx_len;

    if(len > 0)
    {
        (void)memcpy_s(buff, (size_t)size, uart_buffer, (size_t)len);

        uart_rx_len = 0;
        memset(uart_buffer, 0, UART_BUFF_SIZE);

        return len;
    }

    return 0;
}


// 串口 发送数据 成功 返回 发送数据长度 失败 返回 0
uint8_t UART_Send_Data(uint8_t *buff, uint8_t size, uint8_t boot)
{
    uint8_t data[UART_BUFF_SIZE + 2] = {0};
    memcpy_s(data, (UART_BUFF_SIZE + 2), buff, (size_t)size);

    uint32_t len = (uint32_t)size;

    if(boot == 1)
    {
        data[size] = '\r';
        data[size + 1] = '\n';

        len += 2;
    }

    int32_t ret = uapi_uart_write(UART_BUS_ID, data, len, 0);

    if(ret > 0)
    {
        return (uint8_t)ret;
    }

    return 0;
}

其他模块代码我前面都有写,这里不复述了。

注意说明一点,WiFi AP 模式,设置密码长度 最少要 8 位。

运行起来到是很流畅,但是肯定还有没发现的错误。

代码太多了,我浏览一遍都要花好长时间,代码写的也乱,也没法做详细的说明。

到最后做一个最小集成版,发出来。

然后下篇更新,小车动力部分。

Hi3863 Lite os 的 PWM非常有意思,感觉挺高级的,我这没见过什么世面,感觉非常好的功能。

下篇讲。

相关推荐
个案命题2 小时前
鸿蒙生态的“完美无瑕”与“吹毛求疵”
华为·harmonyos
前端世界2 小时前
鸿蒙语音控制实战:从语音识别到业务执行的完整链路
华为·语音识别·harmonyos
三佛科技-187366133972 小时前
LP2177B(输出电压可调3.3V/5V 400mA)兼容BP2525电源芯片方案
单片机·嵌入式硬件
llilian_1613 小时前
总线授时卡 CPCI总线授时卡的工作原理及应用场景介绍 CPCI总线校时卡
运维·单片机·其他·自动化
90后的晨仔13 小时前
鸿蒙ArkUI如何使用RGB、十六进制等设置颜色值?
harmonyos
禾仔仔14 小时前
USB MSC从理论到实践(模拟U盘为例)——从零开始学习USB2.0协议(六)
嵌入式硬件·mcu·计算机外设
音浪豆豆_Rachel15 小时前
Flutter鸿蒙化之深入解析Pigeon多参数接口设计:multiple_arity.dart全解
flutter·harmonyos
音浪豆豆_Rachel15 小时前
Flutter鸿蒙文件选择器深度解析:文本文件处理与跨平台挑战
flutter·harmonyos
The Electronic Cat16 小时前
树莓派使用串口启动死机
单片机·嵌入式硬件·树莓派