STM32HAL开发中的UART和USART的联系与差异及使用(一)

前言:博主在实际的串口通信使用中发现,使用STM32CubeMX进行USART的配置时,发现软件生产代码所使用的相关配置句柄是UART开头(如下图所示),这不禁让我产生疑惑,USART和UART是否有严格的区别和界限呢,亦或是在相同的联系中带有差异呢,因此带着问题去学习了相关理论知识。


从功能特性上看区别:

通用异步收发器(Universal Asynchronous Receiver/Transmitter),通常称作UART,是一种串行、异步、全双工的通信协议

通用同步异步收发器(Universal Synchronous/Asynchronous),通常称作USART,是一种串行,可同步可异步,全双工的通信协议

UART(通用异步收发传输器):

  1. 异步通信: UART通常用于异步串口通信,其中数据通过固定的波特率进行传输,而无需外部时钟信号。

  2. 简单性: UART通常比USART更简单,因为它不支持同步模式和其他高级特性。

  3. 通信模式: UART通常只能工作在异步模式下,不支持同步模式。

USART(通用同步/异步收发传输器):

  1. 同步和异步通信: USART具有UART的所有功能,同时还支持同步通信模式,这意味着数据可以通过外部时钟信号进行同步传输。

  2. 高级特性: USART相对于UART来说更加灵活,支持更多的功能,例如硬件流控制、多主机通信等。

  3. 通信模式: USART可以工作在同步或异步模式下,提供了更多的通信选项。

联系:

  1. 共同点: USART和UART都是用于串口通信的模块,可以实现设备之间的数据传输。

  2. 使用方式: 在STM32中,USART和UART都可以通过配置寄存器来实现串口通信,而且通常会使用相似的接口和函数来进行初始化和数据传输。

  3. 硬件资源: 通常情况下,USART和UART会共享相同的硬件资源,例如引脚和时钟资源,因此在使用时需要注意资源的共享情况。

总的来说,UART是USART的一种简化版本,通常用于异步串口通信,而USART除了支持UART的所有功能外,还额外支持同步通信模式和其他高级特性,也就是说USART是UART的加强版。


从硬件方面初步认识UART和USART之后,再从HAL的角度去看这两者的区别:首先解答前言的问题,为什么USART的配置能使用UART的相关句柄呢?在STM32的HAL库中,通常使用UART_InitTypeDef结构体来配置USART模块的初始化参数。虽然结构体的名为UART_InitTypeDef,但实际上它用于配置USART模块,因为STM32的HAL库将UART和USART功能整合到了同一个模块中。UART_InitTypeDef结构体中包含了USART模块的各种配置参数,例如波特率、数据位、停止位、校验位等。通过填充这个结构体并传递给HAL库中的初始化函数,可以对USART模块进行配置。也就是当我们想要把USART当基础版UART使用时,就可以用UART的相关句柄和函数对USART进行"低级配置操作",那么为什么不直接使用USART自带的API进行操作呢,博主认为,因为此时USART的一些高级功能依赖的寄存器根本使用不到,可以节省程序设计的复杂性,也可以减少资源的不必要浪费和减小功耗。而要继续使用STM32USART的更复杂和高级的功能时,再用USART的自带的,相比于UART进一步扩展的内容。

那么从本质上来讲(寄存器角度),尽管HAL库是一些封装好的固件,底层仍然是操作寄存器达到配置的目的,在STM32微控制器中,USART和UART在异步串行通信模式下通常会共用相同的寄存器。这些寄存器包括数据寄存器、控制寄存器、状态寄存器、中断使能寄存器和中断标志寄存器等。这意味着在异步通信模式下,USART和UART使用相同的寄存器来执行串行通信操作。那么自然而然,两者就会共用相同的句柄结构和一些API函数。


UART 的HAL库使用

了解HAL库开发之前,先来看看异步串行通信的具体工作方式:

起始位为低电平(逻辑0),占用一位,用来通知接收设备,一个新的字符开始传输。(异步通信以字符为单位进行传输)通信道路在不传输数据时一直保持高电平(逻辑1),接收端不断检测通信道路的状态,如果在连续的1之后检测到一个0,就知道一个新的字符出现了,马上准备接收。起始位之后是数据位。由于计算机以字节为单位进行储存,一个字节有8位,因此数据位的位数一般为8位。在发送数据时,低位数据先发送,高位数据后发送,也就是说发送数据0xE9时,接收端接收的先后顺序是10010111。奇偶校验位占用一位,用于检测数据是否出错,停止位为高电平逻辑1,占用一位,用来指示一帧数据的结束。(事实上,接收端通过计时来确定停止位何时到达,否则无法区分数据位和停止位,因而通过一种协定,在一定时刻后判断停止位是否到来)

首先看看UART所需要用到的句柄结构

UART_InitTypeDef

UART_InitTypeDef 在stm32f1xx_hal_uart.h 中定义

 uint32_t BaudRate 

uint32_t WordLength

uint32_t StopBits

uint32_t Parity

uint32_t Mode

uint32_t HwFlowCtl

uint32_t OverSampling

uint32_t BaudRate:

(在UART_HandleTypeDef
中定义UART_InitTypeDef的配置实例图)

uint32_t BaudRate:配置 UART 通信的波特率

uint32_t WordLength:指定每个帧中传输或接收的数据位数。
可以是 UART_Word_Length 中定义的值。

uint32_t StopBits:指定发送的停止位数。
可以是 UART_Stop_Bits 中定义的值。

uint32_t Parity:指定奇偶校验模式
可以是 UART_Parity 中定义的值。

uint32_t Mode:指定是否启用或禁用接收或发送模式
可以是 UART_Mode 中定义的值。

uint32_t HwFlowCtl:指定是否启用或禁用硬件流控制模式
可以是 UART_Hardware_Flow_Control 中定义的值。

uint32_t OverSampling:

指定是否启用或禁用过采样 8 模式,以实现更高的速度(高达 fPCLK/8)。
在 STM32F1xx 系列中,这个特性不可用,因此 OverSampling 参数应始终设置为 16。
总之,UART_InitTypeDef 结构体用于配置 UART 初始化参数,包括波特率、数据位数、停止位数、奇偶校验模式、模式、硬件流控制和过采样模式。通过设置这些参数,可以灵活地配置 UART 模块以满足不同的通信需求。


UART_HandleTypeDef
UART_HandleTypeDef 在 stm32f1xx_hal_uart.h 中定义
USART_TypeDef * Instance        //指向 UART 实例的指针,用于标识特定的 UART和USART 外设。

UART_InitTypeDef Init      //UART 初始化配置结构体,包括 UART和USART 外设的各种配置参数,比如波特率、数据位、停止位等。

uint8_t * pTxBuffPtr          //指向发送缓冲区的指针,用于存储待发送数据。

uint16_t TxXferSize        //待发送数据的总大小。

uint16_t TxXferCount       //当前待发送数据的计数器,用于跟踪已经发送的数据量。

uint8_t * pRxBuffPtr        //指向接收缓冲区的指针,用于存储接收到的数据

uint16_t RxXferSize        //接收缓冲区的总大小

uint16_t RxXferCount        //当前接收到的数据计数器,用于跟踪已经接收的数据量。

 DMA_HandleTypeDef * hdmatx  //指向发送 DMA 外设的指针,用于 DMA 传输的控制。

DMA_HandleTypeDef * hdmarx  //指向接收 DMA 外设的指针,用于 DMA 传输的控制。

HAL_LockTypeDef Lock        //用于保护结构体的互斥锁,防止在多任务环境中同时访问该结构体。

__IO HAL_UART_StateTypeDef State        //表示 UART 外设的当前状态,比如就绪、发送中、接收中等。

__IO uint32_t ErrorCode                         //记录 UART 操作期间的错误码,用于错误处理和诊断。

绿字部分一般在结构体外自行定义使用,而蓝字部分一般不使用。


 其次从轮询方式,中断方式,和DMA方式学习UART相关接口函数

1.轮询方式的接口函数

HAL_UART_Init(UART_HandleTypeDef*huart)//按照句柄中设定的参数初始化串口

 返回值:HAL状态值,HAL_OK表示初始化成功,HAL_ERROP表示初始化失败

注意事项:①该函数调用MCU硬件初始化函数HAL_UART_MspInit()完成时钟,引脚和中断 等系统级初始化操作。②可有CubeMX软件自动生成。


HAL_UART_Transmit(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tTimeout)//在轮询方式下发送指定数量的数据

pData:通常是自定义的数组,指向数据缓冲区的指针,存放数据的地方

Size:发送的数据个数

Timeout:发送超时时间,以ms为单位,HAL_MAX_DELAY表示无限等待

返回值:HAL状态值,HAL_OK表示发送成功,HAL_ERROP表示发送失败,HAL_BUSY表示串口被占用,HAL_TIMEOUT表示发送超时

注意事项:①该函数连续发送数据,发送过程中通过判断TXE标志位来发送下一个数据,判断TC标志位来结束数据的发送②如果超时未发送,则不再发送,返回超时标志。③由用户调用


HAL_UART_Receive(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tTimeout)

入口参数,返回值和注意事项与上同,发送逻辑改为接收逻辑。


 2.中断方式的接口函数

轮询方式与中断方式的区别通俗的讲就是是否需要MCU时刻参与数据收发的过程,轮询下CPU无法执行其他任务,利用率较低。中断下CPU只有在中断发送时才会进行相关任务,提高了利用率。

HAL_UART_Transmit_IT(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tTimeout)//中断方式下发送指定量的数据

入口参数和返回值与上同

注意事项:①该函数使能串口发生中断。②完成指定量的数据发送后,将会关闭中断(一次性使用)需要重复调用,以便重新使能发送中断。③完成数据发送后,将会调用发送中断回调函数HAL_UART_TxCpltCallback()进行后续处理。④由用户调用。


HAL_UART_Receive_IT(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tTimeout)//中断方式下接收指定量的数据

入口参数,返回值,和注意事项与上同③中HAL_UART_TxCpltCallback()变为HAL_UART_RxCpltCallback


 void HAL_UART_IRQHandler(UART_HandleTypeDef*huart)//所有串口中断发生后的通用处理程序

事实上,该函数才负责完成具体的数据收发任务,并且最后会在函数中调用不同的回调函数来完成后续的中断任务。在调用 HAL_UART_Transmit_IT() 函数时,实际上只是将要发送的数据写入了发送缓冲区,并使能了 UART 的发送中断。数据的发送实际上是在使能中断后的中断处理函数中完成的。


HAL_UART_TxCpltCallback(UART_HandleTypeDef*huart)//发送中断回调函数

该函数由用户实际程序设计需要进行编写。


HAL_UART_RxCpltCallback(UART_HandleTypeDef*huart)//接收中断回调函数

该函数由用户实际程序设计需要进行编写。

HAL_UART_IRQHandler和HAL_UART_RxCpltCallback之间的调用关系:

HAL_UART_Receive_IT(先使能中断)-->HAL_UART_IRQHandler --> HAL_UART_RxCpltCallback 即当UART接收到数据后,该函数会调用HAL库提供的UART中断处理函数HAL_UART_IRQHandler,最后HAL_UART_IRQHandler函数会在数据接收完成时调用HAL_UART_RxCpltCallback回调函数。

3.DMA方式串口通信

名词释义:

(一)在UART通信中,停止位(Stop Bit)和校验位(Parity Bit)是用来提高通信可靠性的两种机制。

  1. 停止位(Stop Bit): 停止位是在每个数据字节的末尾添加的一个位,用于指示数据传输的结束。它告诉接收端已经接收完一个字节的数据,并且可以准备接收下一个字节。停止位的常见取值为1位或2位,其中1位是最常见的配置。(图中为一个停止位)

  2. 校验位(Parity Bit): 校验位是在数据字节的末尾添加的一个额外位,用于检测数据传输过程中的错误。校验位根据数据字节中的数据位计算出来,并与数据一起发送。接收端在接收数据时也会重新计算校验位,并与接收到的校验位进行比较,从而检测是否存在传输错误。常见的校验方式包括奇校验、偶校验和无校验。(图中为无校验)

作用:

  • 停止位: 主要用于同步接收端和发送端之间的数据传输节奏。接收端通过检测停止位来确定数据字节的结束,并在准备好接收下一个字节时等待停止位的到来。停止位的存在有助于确保数据的准确传输。

  • 校验位: 用于在数据传输过程中检测错误。发送端在发送数据时计算校验位,并将其附加到数据字节中。接收端在接收到数据后重新计算校验位,并将其与接收到的校验位进行比较。如果校验失败,则说明数据在传输过程中发生了错误,接收端可以请求重新发送或者进行其他错误处理。


(二)硬件流控【STM32学习笔记】USART 硬件流控 - 知乎 (zhihu.com)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/89440015


(三)并行通信:并行通信是指将数据字节的各位用多条数据线同时进行传输的通信方式。这种方式特点是控制简单,传输速度快,但传输线较多,长距离传输时硬件成本高。

           串行通信:是指将数据字节分成一位一位的形式在一条传输线上逐个传输。特点是传输线少,长距离传输时硬件成本低,但数据传输的控制方式比并行通信复杂。由于数据逐位传输,收发双方需要考虑数据的同步问题,即数据什么时候开始传输,什么时候结束传输,数据中的每一位持续的时间是多久。

按照实现数据同步的不同方式,串行通信又可分为同步串行和异步串行。

(1)同步串行:通信双方通过建立专门的时钟信号使双方达到完全同步。产生时钟的一方称为主机(master)和从机(slave)。此类通信的实例包括SPI和IIC。优点是可以实现高速度,大容量的数据传送,缺点是需要额外的时钟线,并且要求发送时钟和接收时钟保持严格的同步,通信协议和硬件电路较为复杂。

(2)异步通信:没有专门的时钟信号,而是依靠事先约定的字符格式和通信速率来完成通信。包括USB,以太网和UART。

同步串行的双方按照统一的节拍工作,配合很好,但是从机需要通过时钟信号来同步主机的数据传输节奏,从而进行正确的数据接收和发送。如果没有时钟信号,从机无法确定何时接收数据,因此通常会一直处于等待状态,因此如果双方没有一个固定的频率进行通信,这会让从机一直处于等待状态,浪费从机的CPU资源,所以同步通信适用于①双方有固定通信频率②发送端和接受端需要同步③数据传输速率高的场景。异步串行的接受方不必在意发送方,因此异步串行又叫异步通知,是发送方需要发送信息时会首先给接受方一个信息开始的信号,接收方接受到起始信号后认为后面为有效信息,完成接受,直到接收方收到了发送方发来的结束标志。平常如果没有起始信号,接收方该干嘛干嘛。

  • 30
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值