HPM6750系列--第十一篇 Uart讲解(轮询模式)

2023-12-20 22:30

本文主要是介绍HPM6750系列--第十一篇 Uart讲解(轮询模式),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、目的

        在介绍完GPIO的相关内容下一个必须介绍的就是uart了,因为串口一个主要用途就是用于调试信息打印。

        HPM6750在uart的配置上也是相当炸裂,有17个串口;结合HPM6750的高主频高内存,完全可以作为一个串口服务器。

        ​​​​​​​

        

二、介绍

        1.框图 

        TX FIFO 包含待发送的数据,并将数据传送到 TX 移位寄存器。TX 移位寄存器为并行-串行转换器,把发送数据转换成串行的比特流。

        TXFIFO 的写入口是THR寄存器 (Transmitter Holding Register)。用户需要把FCR寄存器 (FIFO Control Reg- ister) 的 FIFOE 位置 1,来打开 TXFIFO。

        RX 控制器使用波特率控制模块生成的过采样时钟,对输入的每一位进行采样,并把收到的每一位移入 RX 移 位寄存器。RX 移位寄存器对数据进行串行-并行转换,并把数据存入 RX FIFO。RX FIFO 的读入口是RBR寄存器 (Receiver Buffer Register),用户需要把FCR寄存器 (FIFO Control Register)的 FIFOE 位置 1,来打开 RXFIFO。

         

        2.基本特征
  • 支持 5∼8 位数据长度
  • 可配置停止位:1 位,1.5 位或者 2 位
  • 可配置奇偶校验位:奇校验,偶校验,粘校验位
  • 支持 DMA 数据传输
  • 支持可配置波特率,支持独立的波特率生成时钟
  • 支持硬件流控
  • 支持奇偶校验错误,数据 FIFO 溢出等错误检测
  • 16 字节的 TXFIFO 和 RXFIFO
  • 支持各类中断
        3.功能时钟(输入时钟)、过采样率、波特率三者之间的关系

        在时钟章节我们讲到每个外设都可以八选一选择一个功能时钟,并且设置分频。 

         

         

        上图中我们通过clock_set_source_divider设置uart0选择clk_src_osc24m=24MHz时钟源,不分频,也就是说上图中的配置uart0输入时钟为24MHz。

        UART 时钟与波特率的比率就是过采样率OSC。    

        RX 控制器利用过采样时钟对输入数据进行采样。假设过采样率OSC为 16 当检测到输入信号第一个下降沿 时 (起始 START 位),计数器从 1 开始计数直到 16,在计数到 8 时,RX 控制器对输入数据采样。计数器在计数 到 16 后,会复位到 1,以此采样下一位数据,循环往复,直到停止 STOP 位。TX 控制器同样利用过采样时钟来 生成输出数据流。 

        uart外设内部还有一个时钟分频寄存器(16位)Divisor。分频值的 MSB 位于DLM寄存器 (Divisor Latch MSB),而 LSB 位于DLL寄存器 (Divisor Latch LSB)。

        三者之间的关系如下:

                  

        在SDK中有一个函数专门用于计算分频系数和过采样率,对于开发者来讲,只需要设置输入时钟和波特率即可。

         

       4.引脚配置(以uart0为例)

        由于uart0使用PY06/07作为TXD/RXD, 而PY06/07属于电源管理域的引脚,所以必须先通过HPM_PIOC先将引脚映射到HPM_IOC中,然后由HPM_IOC再将PY06/07复用为外设引脚。

        5.API接口说明 

        

typedef struct hpm_uart_config {uint32_t src_freq_in_hz;                    /**< Source clock frequency in Hz */uint32_t baudrate;                          /**< Baudrate */uint8_t num_of_stop_bits;                   /**< Number of stop bits */uint8_t word_length;                        /**< Word length */uint8_t parity;                             /**< Parity */uint8_t tx_fifo_level;                      /**< TX Fifo level */uint8_t rx_fifo_level;                      /**< RX Fifo level */bool dma_enable;                            /**< DMA Enable flag */bool fifo_enable;                           /**< Fifo Enable flag */uart_modem_config_t modem_config;           /**< Modem config */
#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1)uart_rxline_idle_config_t  rxidle_config;   /**< RX Idle configuration */
#endif
#if defined(UART_SOC_HAS_TXLINE_IDLE_DETECTION) && (UART_SOC_HAS_TXLINE_IDLE_DETECTION == 1)uart_rxline_idle_config_t  txidle_config;   /**< TX Idle configuration */
#endif
#if defined(UART_SOC_HAS_RXEN_CFG) && (UART_SOC_HAS_RXEN_CFG == 1)bool rx_enable;                             /**< RX Enable configuration */
#endif
} uart_config_t;

        各个字段含义:

src_freq_in_hz 输入时钟,八选一,并且可以分频(注意uart内部可以再次分频)
baudrate波特率
num_of_stop_bits

停止位

typedef enum num_of_stop_bits {
    stop_bits_1 = 0,
    stop_bits_1_5,
    stop_bits_2,
} num_of_stop_bits_t;

word_length

字长

typedef enum word_length {
    word_length_5_bits = 0,
    word_length_6_bits,
    word_length_7_bits,
    word_length_8_bits,
} word_length_t;

parity

奇偶校验位

typedef enum parity {
    parity_none = 0,
    parity_odd,
    parity_even,
    parity_always_1,
    parity_always_0,
} parity_setting_t;

tx_fifo_level发送触发阈值
rx_fifo_level接收触发阈值
dma_enable使能DMA
fifo_enable使能FIFO
modem_config

流控

typedef struct uart_modem_config {
    bool auto_flow_ctrl_en;     /**< Auto flow control enable flag */
    bool loop_back_en;          /**< Loop back enable flag */
    bool set_rts_high;          /**< Set signal RTS level high flag */
} uart_modem_config_t;

                uart_init函数用于设置波特率、字长、停止位、奇偶校验以及FIFO阈值。

hpm_stat_t uart_init(UART_Type *ptr, uart_config_t *config)
{uint32_t tmp;uint8_t osc;uint16_t div;/* disable all interrupts */ptr->IER = 0;/* Set DLAB to 1 */ptr->LCR |= UART_LCR_DLAB_MASK;if (!uart_calculate_baudrate(config->src_freq_in_hz, config->baudrate, &div, &osc)) {return status_uart_no_suitable_baudrate_parameter_found;}ptr->OSCR = (ptr->OSCR & ~UART_OSCR_OSC_MASK)| UART_OSCR_OSC_SET(osc);ptr->DLL = UART_DLL_DLL_SET(div >> 0);ptr->DLM = UART_DLM_DLM_SET(div >> 8);//设置奇偶校验/* DLAB bit needs to be cleared once baudrate is configured */tmp = ptr->LCR & (~UART_LCR_DLAB_MASK);tmp &= ~(UART_LCR_SPS_MASK | UART_LCR_EPS_MASK | UART_LCR_PEN_MASK);switch (config->parity) {case parity_none:break;case parity_odd:tmp |= UART_LCR_PEN_MASK;break;case parity_even:tmp |= UART_LCR_PEN_MASK | UART_LCR_EPS_MASK;break;case parity_always_1:tmp |= UART_LCR_PEN_MASK | UART_LCR_SPS_MASK;break;case parity_always_0:tmp |= UART_LCR_EPS_MASK | UART_LCR_PEN_MASK| UART_LCR_SPS_MASK;break;default:/* invalid configuration */return status_invalid_argument;}//设置停止位tmp &= ~(UART_LCR_STB_MASK | UART_LCR_WLS_MASK);switch (config->num_of_stop_bits) {case stop_bits_1:break;case stop_bits_1_5:tmp |= UART_LCR_STB_MASK;break;case stop_bits_2:if (config->word_length < word_length_6_bits) {/* invalid configuration */return status_invalid_argument;}tmp |= UART_LCR_STB_MASK;break;default:/* invalid configuration */return status_invalid_argument;}//设置字长ptr->LCR = tmp | UART_LCR_WLS_SET(config->word_length);//复位FIFO并设置FIFO阈值#if defined(UART_SOC_HAS_FINE_FIFO_THR) && (UART_SOC_HAS_FINE_FIFO_THR == 1)/* reset TX and RX fifo */ptr->FCRR = UART_FCRR_TFIFORST_MASK | UART_FCRR_RFIFORST_MASK;/* Enable FIFO */ptr->FCRR = UART_FCRR_FIFOT4EN_MASK| UART_FCRR_FIFOE_SET(config->fifo_enable)| UART_FCRR_TFIFOT4_SET(config->tx_fifo_level)| UART_FCRR_RFIFOT4_SET(config->rx_fifo_level)| UART_FCRR_DMAE_SET(config->dma_enable);#else/* reset TX and RX fifo */ptr->FCR = UART_FCR_TFIFORST_MASK | UART_FCR_RFIFORST_MASK;/* Enable FIFO */tmp = UART_FCR_FIFOE_SET(config->fifo_enable)| UART_FCR_TFIFOT_SET(config->tx_fifo_level)| UART_FCR_RFIFOT_SET(config->rx_fifo_level)| UART_FCR_DMAE_SET(config->dma_enable);ptr->FCR = tmp;/* store FCR register value */ptr->GPR = tmp;
#endifuart_modem_config(ptr, &config->modem_config);#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1)uart_init_rxline_idle_detection(ptr, config->rxidle_config);
#endif
#if defined(UART_SOC_HAS_RXEN_CFG) && (UART_SOC_HAS_RXEN_CFG == 1)if (config->rx_enable) {ptr->IDLE_CFG |= UART_IDLE_CFG_RXEN_MASK;}
#endifreturn status_success;
}

        读取字节


hpm_stat_t uart_receive_byte(UART_Type *ptr, uint8_t *byte)
{uint32_t retry = 0;while (!(ptr->LSR & UART_LSR_DR_MASK)) {if (retry > HPM_UART_DRV_RETRY_COUNT) {break;}retry++;}if (retry > HPM_UART_DRV_RETRY_COUNT) {return status_timeout;}*byte = ptr->RBR & UART_RBR_RBR_MASK;return status_success;
}

        不断查询LSR寄存器的UART_LSR_DR_MASK是否置位(存在有效的接收数据时该位置 1),如果置位说明可读,此时RBR寄存器存储的就是当前可读字节。

        写入字节

hpm_stat_t uart_send_byte(UART_Type *ptr, uint8_t c)
{uint32_t retry = 0;while (!(ptr->LSR & UART_LSR_THRE_MASK)) {if (retry > HPM_UART_DRV_RETRY_COUNT) {break;}retry++;}if (retry > HPM_UART_DRV_RETRY_COUNT) {return status_timeout;}ptr->THR = UART_THR_THR_SET(c);return status_success;
}

         不断查询LSR寄存器的UART_LSR_THRE_MASK是否置位(发送FIFO空),如果置位说明可写,此时写入THR寄存器就会传送给TX FIFO。

三、实战

        VScode打开工程并进入调试窗口,在

cd ~/workspace/work/hpm/hello_world
code .
uart0引脚配置

 

uart0串口寄存器配置

 

                以上就是uart的基本内容,包括功能说明、引脚配置、时钟配置、轮询读写。 

         

这篇关于HPM6750系列--第十一篇 Uart讲解(轮询模式)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/517738

相关文章

Python使用国内镜像加速pip安装的方法讲解

《Python使用国内镜像加速pip安装的方法讲解》在Python开发中,pip是一个非常重要的工具,用于安装和管理Python的第三方库,然而,在国内使用pip安装依赖时,往往会因为网络问题而导致速... 目录一、pip 工具简介1. 什么是 pip?2. 什么是 -i 参数?二、国内镜像源的选择三、如何

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

Redis的Zset类型及相关命令详细讲解

《Redis的Zset类型及相关命令详细讲解》:本文主要介绍Redis的Zset类型及相关命令的相关资料,有序集合Zset是一种Redis数据结构,它类似于集合Set,但每个元素都有一个关联的分数... 目录Zset简介ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZ

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能