当前位置: 首页 > article >正文

【鸿蒙开发】Hi3861学习笔记- 串口

00. 目录

文章目录

    • 00. 目录
    • 01. 概述
    • 02. Hi3861串口
    • 03. 串口相关类型
      • 3.1 hi_uart_idx
      • 3.2 hi_uart_data_bit
      • 3.3 hi_uart_stop_bit
      • 3.4 hi_uart_parity
      • 3.5 hi_flow_ctrl
      • 3.6 hi_uart_attribute
      • 3.7 hi_uart_extra_attr
    • 04. 串口相关API
      • 4.1 hi_uart_init
      • 4.2 hi_uart_read
      • 4.3 hi_uart_write
      • 4.4 hi_uart_deinit
    • 05. 硬件设计
    • 06. 软件设计
    • 07. 实验现象
    • 08. 附录

01. 概述

UART(Universal Asynchronous Receiver/Transmitter)通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。是在应用程序开发过程中使用频率最高的数据总线。

UART 串口的特点是将数据一位一位地顺序传送,只要 2 根传输线就可以实现双向通信,一根线发送数据的同时用另一根线接收数据。UART 串口通信有几个重要的参数,分别是波特率、起始位、数据位、停止位和奇偶检验位,对于两个使用 UART 串口通信的端口,这些参数必须匹配,否则通信将无法正常完成。UART 串口传输的数据格式如下图所示:

在这里插入图片描述

  • 起始位:表示数据传输的开始,电平逻辑为 “0” 。
  • 数据位:可能值有 5、6、7、8、9,表示传输这几个 bit 位数据。一般取值为 8,因为一个 ASCII 字符值为 8 位。
  • 奇偶校验位:用于接收方对接收到的数据进行校验,校验 “1” 的位数为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性,使用时不需要此位也可以。
  • 停止位: 表示一帧数据的结束。电平逻辑为 “1”。
  • 波特率:串口通信时的速率,它用单位时间内传输的二进制代码的有效位(bit)数来表示,其单位为每秒比特数 bit/s(bps)。常见的波特率值有 4800、9600、14400、38400、115200等,数值越大数据传输的越快,波特率为 115200 表示每秒钟传输 115200 位数据。

02. Hi3861串口

Hi3861 有三个硬件 UART:UART0、UART1 和 UART2。这 3 个串口可映射到多个不同 IO,具体可查看 GPIO 管脚功能。

在这里插入图片描述

在这里插入图片描述

UART0 用于下载和 REPL 调试,因此可以使用 UART1 或 UART2 与外部串口设备通信,本实验为了方便操作,采用 UART0。

03. 串口相关类型

3.1 hi_uart_idx

/**
 * @ingroup iot_uart
 *
 * UART serial number. CNcomment:UART序号。CNend
 */
typedef enum {
    HI_UART_IDX_0,    /**< Physical port number 0.CNcomment:物理端口号0 CNend */
    HI_UART_IDX_1,    /**< Physical port number 1.CNcomment:物理端口号1 CNend */
    HI_UART_IDX_2,    /**< Physical port number 2.CNcomment:物理端口号2 CNend */
    HI_UART_IDX_MAX   /**< Maximum physical port number, which cannot be used. CNcomment:物理端口号最大值,
                         不可使用CNend */
} hi_uart_idx;

3.2 hi_uart_data_bit

/**
 * @ingroup iot_uart
 *
 * UART data bit. CNcomment:UART数据位。CNend
 */
typedef enum {
    HI_UART_DATA_BIT_5 = 5, /**< Data bit: support option 5bit.CNcomment:数据位:支持配置5bit.CNend */
    HI_UART_DATA_BIT_6,     /**< Data bit: support option 6bit.CNcomment:数据位:支持配置6bit.CNend */
    HI_UART_DATA_BIT_7,     /**< Data bit: support option 7bit.CNcomment:数据位:支持配置7bit.CNend */
    HI_UART_DATA_BIT_8,     /**< Data bit: support option 8bit.CNcomment:数据位:支持配置8bit.CNend */
} hi_uart_data_bit;

3.3 hi_uart_stop_bit

/**
 * @ingroup iot_uart
 *
 * UART stop bit. CNcomment:UART停止位。CNend
 */
typedef enum {
    HI_UART_STOP_BIT_1 = 1, /**< Stop bit, 1bit.CNcomment:停止位,1bit停止位.CNend */
    HI_UART_STOP_BIT_2 = 2, /**< Stop bit, 2bit.CNcomment:停止位,2bit停止位.CNend */
} hi_uart_stop_bit;

3.4 hi_uart_parity

/**
 * @ingroup iot_uart
 *
 * UART parity bit. CNcomment:UART校验位。CNend
 */
typedef enum {
    HI_UART_PARITY_NONE = 0, /**< Parity bit, None. CNcomment:校验位,无校验CNend */
    HI_UART_PARITY_ODD = 1,  /**< Parity bit, odd. CNcomment:校验位,奇校验CNend */
    HI_UART_PARITY_EVEN = 2, /**< Parity bit, even. CNcomment:校验位,偶校验CNend */
} hi_uart_parity;

3.5 hi_flow_ctrl

/**
 * @ingroup iot_uart
 *
 * UART hardware flow control mode. CNcomment:UART 硬件流控控制模式。CNend
 */
typedef enum {
    HI_FLOW_CTRL_NONE,     /**< hardware flow ctrl: disable flow ctrl.CNcomment:不使用。CNend */
    HI_FLOW_CTRL_RTS_CTS,  /**< hardware flow ctrl: enable rts and cts.CNcomment:使用RTS和CTS CNend */
    HI_FLOW_CTRL_RTS_ONLY, /**< hardware flow ctrl: enable rts only.CNcomment:只使用RTS CNend */
    HI_FLOW_CTRL_CTS_ONLY, /**< hardware flow ctrl: enable cts only.CNcomment:只使用CTS CNend */
} hi_flow_ctrl;

3.6 hi_uart_attribute

/**
 * @ingroup iot_uart
 *
 * UART basic settings. CNcomment:UART端口基本配置参数。CNend
 */
typedef struct {
    hi_u32 baud_rate; /**< Baud Rate.CNcomment:波特率。CNend */
    hi_u8 data_bits;  /**< Data bit. CNcomment:数据位。CNend */
    hi_u8 stop_bits;  /**< Stop bit. CNcomment:停止位。CNend */
    hi_u8 parity;     /**< Parity check flag. CNcomment:奇偶校验位。CNend */
    hi_u8 pad;        /**< reserved pad */
} hi_uart_attribute;

3.7 hi_uart_extra_attr

/**
 * @ingroup iot_uart
 *
 * UART extra attributes.CNcomment:UART端口额外参数配置。CNend
 */
typedef struct {
    hi_uart_fifo_line tx_fifo_line;
    hi_uart_fifo_line rx_fifo_line;
    hi_uart_fifo_line flow_fifo_line;
    hi_uart_block_state tx_block;
    hi_uart_block_state rx_block;
    hi_u16 tx_buf_size;
    hi_u16 rx_buf_size;
    hi_uart_dma_state tx_use_dma;
    hi_uart_dma_state rx_use_dma;
} hi_uart_extra_attr;

04. 串口相关API

4.1 hi_uart_init

/**
* @ingroup  iot_uart
* @brief  UART initialization. CNcomment:UART初始化。CNend
*
* @par 描述:
*           Set UART with configuration. CNcomment:根据参数配置指定UART。CNend
*
* @attention 1.If extra_attr is set to HI_NULL, all optimization parameters of the notification driver use the default
*            values.CNcomment:extra_attr为HI_NULL表示通知驱动所有优化参数使用默认值;CNend
*            2.If the value of the member parameter in extra_attr is 0, it indicates that the member parameter
*            is notified to the driver. The member parameter uses the default value.
*            CNcomment:extra_attr中成员参数值为0表示通知驱动该成员参数使用默认值;CNend
*            3.After the UART initialization is complete, if you want to change the UART optimization parameter
*            configuration, you need to call hi_uart_deinit to deinitialize the UART before calling hi_uart_init
*            to change the optimization parameter configuration. CNcomment:UART初始化完成后,若要变更UART
优化参数配置,需先调用hi_uart_deinit去初始化UART,再调用hi_uart_init变更优化参数配置。CNend
*
* @param  id            [IN] type #hi_uart_idx,UART port id. CNcomment:UART端口号。CNend
* @param  param         [IN] type #const hi_uart_attribute*,UART base settings.CNcomment:UART基本参数。CNend
* @param  extra_attr    [IN] type #const hi_uart_extra_attr*,UART extra settings. CNcomment:UART优化参数。CNend
*
* @retval #HI_ERR_SUCCESS  Success.
* @retval #HI_ERR_FAILURE  Failure.
* @par 依赖:
*            @li hi_uart.h:Describes UART APIs.CNcomment:UART相关接口。CNend
* @see  hi_uart_deinit。
*/
hi_u32 hi_uart_init(hi_uart_idx id, const hi_uart_attribute *param, const hi_uart_extra_attr *extra_attr);
功能:
	初始化指定的 UART 端口
参数:
	id:指定的 UART 端口
    param:指向 UART 属性的指针,可通过该参数配置波特率、数据位、停止位、奇偶校验等
	extra_attr:UART 额外参数配置,如 FIFO、DMA 等。该参数通常不使用,可设置为 NULL           
返回值:
	0 成功,1 失败

4.2 hi_uart_read

/**
* @ingroup  iot_uart
* @brief  Reads data.CNcomment:读数据。CNend
*
* @par 描述:
*           Reads the data received by the UART. CNcomment:将UART接收到的数据读取出来。CNend
*
* @attention This API must be used after the hi_uart_open function is called.
CNcomment:须在调用完hi_uart_init函数之后使用。CNend
* @param  id        [IN] type #hi_uart_idx,UART port id. CNcomment:UART端口号。CNend
* @param  data      [OUT] type #hi_u8*,Start address of the data to be read.CNcomment:读到数据的首地址。CNend
* @param  data_len  [IN] type #hi_u32,Number of bytes to be read.CNcomment:要读取数据的字节数。CNend
*
* @retval #>=0 Number of bytes that are actually read.CNcomment:实际读到数据的字节数。CNend
* @retval #HI_ERR_FAILURE  Data read error.CNcomment:读数据失败。CNend
* @par 依赖:
*            @li hi_uart.h:Describes UART APIs.CNcomment:UART相关接口。CNend
* @see  hi_uart_write。
*/
hi_s32 hi_uart_read(hi_uart_idx id, hi_u8 *data, hi_u32 data_len)
功能:
	从 UART 中读取指定长度数据
参数:
	id:指定的 UART 端口。
	data:表示指向要读取数据的起始地址的指针
	data_len:表示要读取的字节数
返回值:
	>0 为读取成功字节数,-1 失败

4.3 hi_uart_write

/**
* @ingroup  iot_uart
* @brief  Writes data.CNcomment:写数据。CNend
*
* @par 描述:
*           Writes the data to be sent to the UART. The block mode is used by default.
CNcomment:将待发送的数据写到UART。CNend
*
* @attention This API must be used after the hi_uart_init function is called.
CNcomment:须在调用完hi_uart_init函数之后使用。CNend
* @param  id        [IN] type #hi_uart_idx,UART port id. CNcomment:UART端口号。CNend
* @param  data   [IN] type #const hi_u8*,Start address of the data to be written.CNcomment:待写数据的首地址。CNend
* @param  data_len   [IN] type #hi_u32,Number of bytes to be written.CNcomment:待写数据的字节数。CNend
*
* @retval #>=0 Number of bytes to be sent.CNcomment:实际发送数据的字节数。CNend
* @retval #HI_ERR_FAILURE  Data send failure. CNcomment:发送数据失败。CNend
* @par 依赖:
*            @li hi_uart.h:Describes UART APIs.CNcomment:UART相关接口。CNend
* @see  hi_uart_read。
*/
hi_s32 hi_uart_write(hi_uart_idx id, const hi_u8 *data, hi_u32 data_len)
功能:
	将指定长度的数据写入到 UART
参数:
	id:指定的 UART 端口。
	data:表示指向要写入数据的起始地址的指针
	data_len:表示要写入的字节数。
返回值:
	>0 为成功写入的字节数,-1 失败

4.4 hi_uart_deinit

/**
* @ingroup  iot_uart
* @brief  Deinitializes UART.CNcomment:去初始化UART。CNend
*
* @par 描述:
*           Deinitializes UART.CNcomment:去初始化UART。CNend
*
* @attention This API is used together with hi_uart_init.CNcomment:与hi_uart_init成对使用。CNend
* @param  id        [IN] type #hi_uart_idx,UART port id. CNcomment:UART端口号。CNend
*
* @retval #HI_ERR_SUCCESS  Success.
* @retval #Other     Failure. For details, see hi_errno.h.
* @par 依赖:
*            @li hi_uart.h:Describes UART APIs.CNcomment:UART相关接口。CNend
* @see  hi_uart_init。
*/
hi_u32 hi_uart_deinit(hi_uart_idx id)
功能:
	去初始化指定的 UART
参数:
	id:指定的 UART 端口
返回值:
	0 成功,1 失败

05. 硬件设计

在这里插入图片描述

从图中可以看到,要使芯片串口与电脑进行通信,电脑一般是 USB 接口,这里通过 CH340C 芯片将 USB 与串口信号进行转换;Hi3861

是 3.3V 电平信号,而CH340C 是 5V 电平信号,所以 Q1 和 Q2 三极管电路主要用于 5V/3.3V 电平转换,USB1 为 USB 接口,可用于程序

下载、串口通信、5V 电源输入功能。

06. 软件设计

bsp_uart.h

#ifndef __BSP_UART_H__
#define __BSP_UART_H__

#include <unistd.h>
#include "cmsis_os2.h"
#include "hi_io.h"
#include "hi_gpio.h"

//管脚定义 TXD IO3  RXD IO4
#define UART0_TX_PIN HI_IO_NAME_GPIO_3
#define UART0_TX_GPIO_FUN HI_IO_FUNC_GPIO_3_UART0_TXD

#define UART0_RX_PIN HI_IO_NAME_GPIO_4
#define UART0_RX_GPIO_FUN HI_IO_FUNC_GPIO_4_UART0_RXD

//函数声明
void uart0_init(uint32_t baudrate);
void uart0_send_data(uint8_t *data, uint8_t len);
uint32_t uart0_read_data(uint8_t *data, uint8_t len);


#endif /*__BSP_UART_H__*/

bsp_uart.c


#include <unistd.h>
#include "bsp_uart.h"
#include "hi_uart.h"


//串口初始化
void uart0_init(uint32_t baudrate)
{
    hi_uart_attribute param;

    //TXD初始化
    hi_gpio_init();
    hi_io_set_pull(UART0_TX_PIN, HI_IO_PULL_UP);
    hi_io_set_func(UART0_TX_PIN, UART0_TX_GPIO_FUN);
    hi_gpio_set_dir(UART0_TX_PIN, HI_GPIO_DIR_OUT);

    //RXD初始化
    hi_io_set_pull(UART0_RX_PIN, HI_IO_PULL_NONE);
    hi_io_set_func(UART0_RX_PIN, UART0_RX_GPIO_FUN);
    hi_gpio_set_dir(UART0_RX_PIN, HI_GPIO_DIR_IN);   
    
    
    //串口初始化
    param.baud_rate = baudrate;
    param.data_bits = HI_UART_DATA_BIT_8;
    param.parity = HI_UART_PARITY_NONE;
    param.stop_bits = HI_UART_STOP_BIT_1;
    hi_uart_init(HI_UART_IDX_0, &param, NULL);

}

//串口发送数据
void uart0_send_data(uint8_t *data, uint8_t len)
{
    hi_uart_write(HI_UART_IDX_0, data, len);

}

//串口接收数据
uint32_t uart0_read_data(uint8_t *data, uint8_t len)
{

    return hi_uart_read(HI_UART_IDX_0, data, len);
}

template.c


#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

#include "hi_io.h"
#include "hi_gpio.h"

#include "bsp_led.h"
#include "bsp_uart.h"


#define TASK_STACK_SIZE 1024

//任务1ID
osThreadId_t task1_id;
osThreadId_t task2_id;



//线程回调入口函数
void task1 (void *arg)
{
    //LED初始化
    led_init();

    while(1)
    {
        //LED 高电平
        //hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_2, HI_GPIO_VALUE1);
        LED(HI_GPIO_VALUE1);
        sleep(1);

        //LED 低电平
        //hi_gpio_set_ouput_val(HI_IO_NAME_GPIO_2, HI_GPIO_VALUE0);
        LED(HI_GPIO_VALUE0);
        sleep(1);
    }

}

void task2(void *arg)
{

    uint8_t len = 0;
    uint8_t recv_buf[32];

    //串口初始化
    uart0_init(115200);

    while(1)
    {
        len = uart0_read_data(recv_buf, 32);

        if (len > 0)
        {
            uart0_send_data(recv_buf, len);
        }
    }

}


/**
 * @description: 初始化并创建任务
 * @param {*}
 * @return {*}
 */
static void template_demo(void)
{
    osThreadAttr_t attr;
    attr.name = "task1"; //任务名称
    attr.attr_bits = osThreadDetached; //分离状态
    attr.cb_mem = NULL;
    attr.cb_size = 0;
    attr.stack_mem = NULL;
    attr.stack_size = TASK_STACK_SIZE;
    attr.priority = osPriorityNormal;


    //创建任务1
    task1_id = osThreadNew(task1, NULL, &attr);
    if (NULL != task1_id)
    {
        printf("任务1创建OK task1_id = %d\n", task1_id);
    }

    attr.name = "task2"; //任务名称
    //创建任务2
    task2_id = osThreadNew(task2, NULL, &attr);
    if (NULL != task2_id)
    {
        printf("任务2创建OK task2_id = %d\n", task2_id);
    }

}
SYS_RUN(template_demo);

07. 实验现象

在这里插入图片描述

08. 附录


http://www.kler.cn/a/595597.html

相关文章:

  • Excel online开始支持Copilot高级数据分析:Python提供强大的数据见解
  • 【从零开始学习计算机科学与技术】系统工程概论(二)系统工程方法论
  • rust Send Sync 以及对象安全和对象不安全
  • 【Pandas】pandas Series plot.bar
  • 蓝桥每日打卡--打家劫舍4
  • 大数据学习(80)-数仓分层
  • [GHCTF 2025]Popppppp[pop链构造] [php原生类的利用] [双md5加密绕过]
  • 香港站群服务器租用应该怎么选?
  • [贪心算法]买卖股票的最佳时机 买卖股票的最佳时机Ⅱ K次取反后最大化的数组和 按身高排序 优势洗牌(田忌赛马)
  • SQL Server 数据库引擎服务实例功能出错的解析与解决方案
  • 使用 Tkinter 编写简单计算器应用
  • 【gradio】Gradio 高级功能:动态界面更新与多页面布局
  • 分享:图片识别改名,能识别图片中的文字并批量改名的工具,用WPF和阿里云来完成
  • VS Code PowerShell、Windows PowerShell、CMD 的区别与联系
  • vllm + litellm + langfuse 启动、代理、监控大模型(国内仓库)
  • C++的常用容器嵌套
  • 前端如何请求后端服务?---------nignx
  • Windows 图形显示驱动开发-WDDM 2.9功能- 支持跨适配器资源扫描 (CASO)(一)
  • 传感器研习社:Swift Navigation与意法半导体(STMicroelectronics)合作 共同推出端到端GNSS汽车自动驾驶解决方案
  • ES、Kibana一键式部署脚本执行文件,外加IK分词器和拼音分词器