STM32F407_串口通信的实现

上篇文章(串口通信简介-CSDN博客)重点叙述了串口通信的通信协议,本文将重点叙述利用STM32F407单片机实现串口通信。(#注意:本文是基于HAL库的实现方式)

一、STM32F407串口简介

STM32F4 的串口分为两种:

①USART(即通用同步异步收发器);

②UART(即通用异步收发 器);

UART 是在 USART 基础上裁剪掉了同步通信功能,只剩下异步通信功能。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用串口通信基本都是异步通信。

STM32F4 有 4 个 USART 和 2 个 UART,其中 USART1 和 USART6 的时钟源来于 APB2 时钟,其最大频率为84MHz,其他4个串口的时钟源可以来于APB1时钟,其最大频率为42MHz。

二、USART结构图

① USART 信号引脚

TX:发送数据输出引脚;

RX:接收数据输入引脚;

SCLK:发送器时钟输出,适用于同步传输;

SW_RX:数据接收引脚,属于内部引脚,用于智能卡模式;

IrDA_RDI:IrDA 模式下的数据输入;

IrDA_TDO:IrDA 模式下的数据输出;

nRTS:发送请求,若是低电平,表示 USART 准备好接收数据;

nCTS:清除发送,若是高电平,在当前数据传输结束时阻断下一次的数据发送;

② 数据寄存器

USART_DR 包含了已发送或已接收的数据。由于它本身就是两个寄存器组成的,一个专门给发送用的(TDR),一个专门给接收用的(RDR),因此该寄存器具备读和写的功能。TDR 寄存器提供了内部总线和输出移位寄存器之间的并行接口。RDR 寄存器提供了内部总线和输入移位寄存器之间的并行接口。

当进行数据发送时,向 USART_DR 中写入的数据会自动存储在 TDR 内;当进行数据读取时,从 USART_DR 读数据会自动提取 RDR 的数据。

USART 数据寄存器(USART_DR)低 9 位数据有效,其他数据位保留。USART_DR 的第 9 位数据是否有效跟 USART_CR1 的 M 位设置有关,当 M 位为 0 时,表示 8 位数据字长;当 M 位 为 1 时,表示 9 位数据字长,一般使用 8 位数据字长。

当使能校验位(USART_CR1 中 PCE 位被置位)进行发送时,写到 MSB 的值(根据数据的长度不同,MSB 是第 7 位或者第 8 位)会被后来的校验位取代。

③ 控制器

USART 有专门控制发送的发送器,控制接收的接收器,还有唤醒单元、中断控制等等

④ 时钟与波特率

这部分的主要功能就是为 USART 提供时钟以及配置波特率。

波特率,即每秒钟传输的码元个数,在二进制系统中(串口的数据帧就是二进制的形式), 波特率与波特率的数值相等,所以我们今后在把串口波特率理解为每秒钟传输的二进制位数。

波特率通过以下公式得出:

“fck ”是串口的时钟,(USART2\3 和 UART4\5 的时钟源为 PCLK1,USART1\6 的时钟源为 PCLK2);

“USARTDIV”是一个无符号的定点数,存放在波特率寄存器(USART_BRR)的低 16 位,DIV_Mantissa[11:0]存放的是 USARTDIV 的整数部分,DIV_Fractionp[3:0]存放的是 USARTDIV 的小数部分;

例如:当串口 1 需要设置 115200 的波特率,且此时fck = 84MHz时,那么根据上式可得:

解得:USARTDIV ≈ 45.5729,

因此,USARTDIV 的整数部分为45,即0x2D,则DIV_Mantissa[11:0]=0x2D;小数部分为 0.5729,转换为十六进制,0.5729*16=9.1664,USARTDIV 允许有余数,对结果四舍五入取整,因此,DIV_Fractionp = 0x9。

三、USART 的配置步骤

1、把 USART_CR1 寄存器的 UE位 置位,以此激活 USART;

2、编程 USART_CR1 的 M 位,以此定义字长;

3、在 USART_CR2 中编程停止位的位数;

4、如果采用多缓冲器通信,配置 USART_CR3 中的 DMA 使能位(DMAT)。按多缓冲器通信中的描述配置 DMA 寄存器;

5、利用 USART_BRR 寄存器选择要求的波特率;

6、设置 USART_CR1 中的 TE 位,发送一个空闲帧作为第一次数据发送;

7、把要发送的数据写进 USART_DR 寄存器(此动作清除 TXE 位)。

#注意:在只有一个缓冲器的情况下,对每个待发送的数据重复步骤 7。

8、在 USART_DR 寄存器中写入最后一个数据字后,要等待 TC=1,它表示最后一个数据帧的传输结束。当需要关闭 USART 或需要进入停机模式之前,需要确认传输结束,避免破坏最后一次传输。

四、相关HAL库函数

1. HAL_UART_Init 函数

HAL_StatusTypeDef    HAL_UART_Init(UART_HandleTypeDef *huart);

函数描述

该函数用于初始化异步模式的收发器。

函数形参

形参 1(UART_HandleTypeDef *huart)是结构体指针类型的串口句柄,其定义如下:

typedef struct

{

USART_TypeDef                            *Instance;                    /* UART 寄存器基地址 */

UART_InitTypeDef                          Init;                             /* UART 通信参数 */

UART_AdvFeatureInitTypeDef       AdvancedInit;             /* UART 高级功能配置结构体 */

uint8_t                                            *pTxBuffPtr;                /* 指向 UART 发送缓冲区 */

uint16_t                                          TxXferSize;                 /* UART 发送数据的大小 */

__IO uint16_t                                 TxXferCount;              /* UART 发送数据的个数 */

uint8_t                                           *pRxBuffPtr;                /* 指向 UART 接收缓冲区 */

uint16_t                                         RxXferSize;                 /* UART 接收数据大小 */ __IO

uint16_t                                         RxXferCount;               /* UART 接收数据的个数 */

uint16_t                                         Mask;                           /* UART 数据接收寄存器掩码 */

DMA_HandleTypeDef                   *hdmatx;                       /* UART 发送参数设置(DMA) */

DMA_HandleTypeDef                   *hdmarx;                      /* UART 接收参数设置(DMA) */

HAL_LockTypeDef                         Lock;                         /* 锁定对象 */

_IO HAL_UART_StateTypeDef     gState;                       /* UART 发送状态结构体 */

_IO HAL_UART_StateTypeDef     RxState;                    /* UART 接收状态结构体 */

_IO uint32_t                                  ErrorCode;                 /* UART 操作错误信息 */

}UART_HandleTypeDef;

1)Instance:指向 UART 寄存器基地址。实际上这个基地址 HAL 库已经定义好了,可以选择USART1~ USART3、USART6、UART4、UART5。

2)Init:UART 初始化结构体,用于配置通讯参数,如波特率、数据位数、停止位等等。将在下文叙述。

3)AdvancedInit:用于配置高级功能,如自动波特率,MSB 先行等。

4)pTxBuffPtr,TxXferSize,TxXferCount:分别是指向发送数据缓冲区的指针,发送数据的大 小,发送数据的个数。

5)pRxBuffPtr,RxXferSize,RxXferCount:分别是指向接收数据缓冲区的指针,接受数据的大 小,接收数据的个数。

6)Mask:UART 数据接收寄存器的掩码,用于存放数据的校验位。

7)hdmatx,hdmarx:配置串口发送接收数据的 DMA 具体参数。

8)Lock:对资源操作增加操作锁保护,可选 HAL_UNLOCKED 或者 HAL_LOCKED 两个参数。 如果 gState 的值等于 HAL_UART_STATE_RESET,则认为串口未被初始化,此时,分配锁资 源,并且调用 HAL_UART_MspInit 函数来对串口的 GPIO 和时钟进行初始化。

9)gState,RxState:分别是 UART 的发送状态、工作状态的结构体和 UART 接受状态的结构 体。HAL_UART_StateTypeDef 是一个枚举类型,列出串口在工作过程中的状态值,有些值只适用于 gState,如 HAL_UART_STATE_BUSY。

10)ErrorCode:串口错误操作信息。主要用于存放串口操作的错误信息。

UART_InitTypeDef 结构体类型,用于配置 UART 的各个 通信参数,包括波特率,停止位等,具体说明如下:

typedef struct

{

uint32_t   BaudRate;                    /* 波特率 */

uint32_t   WordLength;                /* 字长 */

uint32_t   StopBits;                      /* 停止位 */

uint32_t   Parity;                          /* 校验位 */

uint32_t   Mode;                          /* UART 模式 */

uint32_t   HwFlowCtl;                 /* 硬件流设置 */

uint32_t   OverSampling;           /* 过采样设置 */

}UART_InitTypeDef

1)BaudRate:波特率设置。一般设置为 2400、9600、19200、115200。

2)WordLength:数据帧字长,可选 8 位或 9 位。这里我们设置为 8 位字长数据格式。

3)StopBits:停止位设置,可选 0.5 个、1 个、1.5 个和 2 个停止位,一般我们选择 1 个停止位。

4)Parity:奇偶校验控制选择,我们设定为无奇偶校验位。

5)Mode:UART 模式选择,可以设置为只收模式,只发模式,或者收发模式。

6)HwFlowCtl:硬件流控制选择,我们设置为无硬件流控制。

7)OverSampling:过采样选择,选择 8 倍过采样或者 16 倍过采样,一般选择 16 倍过采样。

函数返回值

HAL_StatusTypeDef 枚举类型的值,有 4 个,分别是 HAL_OK 表示成功,HAL_ERROR 表 示错误,HAL_BUSY 表示忙碌,HAL_TIMEOUT 超时。

2. HAL_UART_Receive_IT 函数

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart,

                                                                                                uint8_t  *pData, uint16_t Size);

函数描述

该函数用于开启以中断的方式接收指定字节。数据接收在中断处理函数里面实现。

函数形参

形参 1(UART_HandleTypeDef *huart)是结构体指针类型的串口的句柄,其定义如上文所述。

形参 2(uint8_t  *pData) 是要接收的数据地址。

形参 3(uint16_t  Size) 是要接收的数据大小,以字节为单位。

函数返回值

HAL_StatusTypeDef 枚举类型的值。

3. HAL_UART_IRQHandler 函数

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);

函数描述

该函数是 HAL 库中断处理公共函数,在串口中断服务函数中被调用,用于处理串口中断程序。

函数形参

形参 1(UART_HandleTypeDef *huart)是结构体指针类型的串口的句柄,其定义如上文所述。

函数返回值

无。

五、串口通信配置步骤

1)串口参数初始化(波特率、字长、奇偶校验等);

调用 HAL_UART_Init() 函数,进行串口参数初始化;

2)使能串口和GPIO时钟;

调用__HAL_RCC_USART1_CLK_ENABLE() 函数使能串口时钟;

调用__HAL_RCC_GPIOA_CLK_ENABLE() 函数使能GPIO时钟;

3)GPIO设置

调用 HAL_GPIO_Init() 函数,对GPIO模式设置;

4)开启串口相关中断,配置串口中断优先级

调用 HAL_UART_Receive_IT() 函数开启串口中断;

调用 HAL_NVIC_EnableIRQ() 函数使能串口中断;

调用 HAL_NVIC_SetPriority() 函数设置中断优先级;

5)编写中断服务函数

编写 HAL_UART_IRQHandler() 函数执行中断服务程序;

编写 HAL_UART_RxCpltCallback() 函数实现数据接收处理;

6)串口数据接收和发送

HAL_UART_Receive() 函数,用于接收数据;

HAL_UART_Transmit() 函数,用于发送数据;

六、串口通信程序流程图

main函数中的程序流程如下图所示,

usart.c文件中的程序流程图下图所示,

  • 15
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值