Stm32 HAL库开发-UART串口通信轮询方式

电子说

1.2w人已加入

描述

1

HAL库中UART相关结构体的内容

本小节参考《description-of-stm32f0-hal-and-lowlayer-drivers-stmicroelectronics》、《STM32F051x 参考手册中文》。

奇偶校验

UART的结构体有两个,如图,UART_InitTypeDef是初始化结构体,包含UART开始运行时的配置;UART_HandleTypeDef是句柄结构体,包含UART所有运行时的信息。

奇偶校验

UART_InitTypeDef初始化结构体中包含,波特率、帧的字长、停止位长度、奇偶校验方式、工作模式、硬件流模式和过(超)采样率设置。

奇偶校验

其中过采样的目的类似于一种低通滤波,Stm32通过对一帧进行16次或者8次采样,并对采样结果进行“多数票决”来判断该帧为起始位或是数据位的0或1。详见《STM32F051x 参考手册中文》573页。

奇偶校验

硬件流控制是通过硬件对UART传输进行更精细的控制的手段。UART传输中,Stm32通过nCTS端口读取对方的nRTS端口电平,获知对方是否准备好接受新的数据,这种操作可以避免数据寄存器中未被读出的旧数据被新数据刷新掉的情况发生。详见《STM32F051x 参考手册中文》604页。

奇偶校验

UART_HandleTypeDef是UART句柄结构体,包含了UART运行过程中HAL层的所有信息。

2

UART初始化三步

在介绍Stm32的HAL初始化UART之前,我们先看一下Arduino怎么初始化UART的。

奇偶校验

Arduino使用非常简便的一句话,*Serial.begin(波特率); *来初始化UART,这一句话包含了三个内容:

  • UART对象——其代表我们要使用的UART外设;
  • UART启动——其代表根据UART参数启动串口;
  • UART参数——其代表UART以何种配置运行;

奇偶校验

Stm32的HAL初始化过程也可以进行类比:

奇偶校验

我们还可以用填表格来理解这三步操作:

奇偶校验

2.1

Step1-申明结构体变量-生成表格

奇偶校验

申明一个UART_HandleTypeDef的结构体变量,图中的结构体是在main函数中声明,推荐在main.c的头部申明结构体,使其成为全局变量。

奇偶校验

2.2

Step2-配置UART参数-填写表格

配置UART参数参数包括两步:

奇偶校验

第一步是要给UART_HandleTypeDef结构体变量赋值

  • 将我们要使用的外设赋值给其instance字段。
  • 将波特率、帧长度等配合赋值给其UART_InitTypeDef初始化结构体变量的相应字段。

奇偶校验

第二步是要配置与所使用的UART连接的GPIO口,因为任何外设想与外界交换数据都需要正确的和使用的GPIO进行绑定。

在还未介绍的Step3中,我们需要调用HAL_UART_Init()初始化UART,HAL_UART_Init()又会调用HAL_UART_MspInit()对于单片机的Msp( MCU Specific Package 单片机的具体方案 )进行配置,这里Msp就指具体配置哪个IO与UART进行连接。

在HAL_UART_MspInit()中配置GPIO又需要进行如下两步操作:

1. 定义GPIO_InitTypeDef初始化结构体变量作为所要初始化GPIO的配置的“暂存”。

奇偶校验

2. 然后判断此次调用HAL_UART_MspInit()函数的UART外设,根据不同的UART外设对于相应的GPIO和时钟进行如下操作:

  • 启动所用UART外设的时钟。
  • 启用所用GPIO的时钟。
  • 配置GPIO_InitTypeDef初始化结构体变量(变量值如上图)。
  • 使用初始化函数初始化GPIO。
    奇偶校验

2.3

Step3-使用函数初始化UART-提交表格

奇偶校验

完成了UART的参数配置和IO配置之后,我们需要使用HAL_UART_Init()函数提交之前配置好的UART_HandleTypeDef结构体变量这个“表格”,使得Stm32按照我们的参数配置、IO配置启动。

3

使用轮询模式

奇偶校验

3.1

UART通信的三种模式

UART通信有三种模式,分别为轮询模式、中断模式、DMA模式,本小节介绍轮询模式通信。

如果读者学过8位单片机的底层开发,应该能理解轮询模式和中断模式的区别以及中断模式比轮询模式在单片机任务较多时更为高效的原因。

《Mastering Stm32》一书的248页也对两者的区别进行了阐述:

奇偶校验

简单来说,轮询模式是内核在规定的阻塞时间内使用while循环读取传输的标志位,直到标志位被置位才将数据写入或读出DR寄存器。

而中断模式是传输完成的相关中断发生时,内核才放下手中的工作,将数据写入或读出DR寄存器。少了阻塞时间内的循环读取因此更高效。

而DMA模式则更为高效,DMA作为内核的二弟,当传输完成中断发生时,帮助大哥将数据写入或读出DR寄存器,不需要打断大哥-内核的工作。

3.2

轮询模式

奇偶校验

在轮询模式发送数据调用函数HAL_UART_Transmit() ,接收数据调用函数HAL_UART_Receive(),两者的传入参数列表,以及返回值意义相同,如下图,摘自《description-of-stm32f0-hal-and-lowlayer-drivers-stmicroelectronics》P572页。

奇偶校验

下面演示两个函数的几种调用案例:

/* 发送字符数组 */
  char buff[2] = {'a','b'};
  HAL_UART_Transmit(&huart3,(uint8_t *)buff,
                      sizeof(buff),HAL_MAX_DELAY);
/* 发送字符串 */
  HAL_UART_Transmit(&huart3, (uint8_t*)"Hello", 
                      strlen("Hello"),HAL_MAX_DELAY);
/* 接受字符数组 */
  char readBuf[1];
  HAL_UART_Receive(&huart2, (uint8_t*)readBuf, 1, HAL_MAX_DELAY);

至此本文已经完成了对于Stm32使用HAL初始化UART,以及在轮询模式通信方法的阐述。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分