压缩包被破解了,摆烂了,链接没了,有需要的直接在文章里复制吧。
到发文时为止,已汉化内容:
- HAL库驱动头文件(hal.h文件,48个)
- HAL库驱动文件(hal.c 文件,42个)
- 外设访问层头文件(stm32f1xxx.h 寄存器宏定义文件,15个)
- 工具链向量表(.s文件,43个)
- LL库(正在进行)
- ...
本汉化只对库中注释进行汉化,所有原版校对完成的文件,实际代码均与官方原库一致 使用方法按官方库即可。(除部分原版代码报错的调整,修改条目见:使用说明)
源库文件来自ST官网:
版本:V1.8.0 + V1.8.5更新补丁(2023/10/7(官方更新记录2023/4/7))
/**
******************************************************************************
* @file stm32f1xx_hal_usart.c
* @author MCD Application Team
* @brief HAL库 USART 模块驱动
* 该文件提供固件函数,用于管理通用同步/异步接收器/发送器(USART)外设的以下功能:
* + 初始化和反初始化函数
* + IO 操作函数
* + 外设控制函数
*
******************************************************************************
* @attention
*
* 版权所有 (c) 2016 STMicroelectronics。
* 保留所有权利。
*
* 本软件根据可以在此软件组件的根目录中找到的 LICENSE 文件中的条款进行许可。
* 如果此软件没有附带 LICENSE 文件,则按原样提供。
*
******************************************************************************
@verbatim
==============================================================================
##### 如何使用驱动 #####
==============================================================================
[..]
USART HAL驱动程序可按以下方式使用:
(#) 声明一个 USART_HandleTypeDef 句柄结构(例如:USART_HandleTypeDef husart)。
(#) 通过实现 HAL_USART_MspInit() API来初始化USART底层资源:
(##) 启用 USARTx 接口时钟。
(##) USART 引脚配置:
(+++) 启用 USART GPIO 的时钟。
(+++) 将 USART 引脚配置为复用上拉功能(通常为复用开漏输出+外部上拉电阻)。
(##) 如果需要使用中断处理(HAL_USART_Transmit_IT()、HAL_USART_Receive_IT()和HAL_USART_TransmitReceive_IT() API)则需要进行NVIC配置:
(+++) 配置 USARTx 中断优先级。
(+++) 启用 NVIC USART IRQ 句柄。
(##) 如果需要使用DMA处理(HAL_USART_Transmit_DMA()、HAL_USART_Receive_DMA()和HAL_USART_TransmitReceive_DMA() API)则需要进行DMA配置:
(+++) 为 Tx/Rx 通道声明一个DMA句柄结构。
(+++) 启用DMAx接口时钟。
(+++) 使用所需的 Tx/Rx 参数配置声明的DMA句柄结构。
(+++) 配置DMA Tx/Rx 通道。
(+++) 将初始化的DMA句柄与 USART DMA Tx/Rx 句柄关联。
(+++) 配置传输完成中断的优先级并启用 DMA Tx/Rx 通道上的NVIC。
(+++) 配置USARTx中断优先级并启用 NVIC USART IRQ 句柄
(用于在DMA非循环模式下检测最后一个字节的发送完成)
(#) 在 husart Init 结构中设置波特率、数据位长度、停止位、奇偶校验、硬件流控制和模式(接收器/发送器)
(#) 通过调用 HAL_USART_Init() API来初始化USART寄存器:
(++) 这些API还通过调用定制的 HAL_USART_MspInit(&husart) API来配置低级硬件GPIO、时钟、CORTEX等。
-@@- 特定的USART中断(传输完成中断、RXNE(接收缓冲非空)中断和错误中断)将使用宏 __HAL_USART_ENABLE_IT() 和 __HAL_USART_DISABLE_IT() 在传输和接收过程中进行管理。
(#) 此驱动程序内可用三种操作模式:
*** 轮询模式 IO 操作 ***
=================================
[..]
(+) 阻塞模式下发送数据使用 HAL_USART_Transmit()。
(+) 阻塞模式下接收数据使用 HAL_USART_Receive()。
*** 中断模式 IO 操作 ***
===================================
[..]
(+) 非阻塞模式下发送数据使用 HAL_USART_Transmit_IT()。
(+) 在传输结束时执行 HAL_USART_TxHalfCpltCallback() 并且用户可以通过自定义函数指针 HAL_USART_TxCpltCallback 添加自己的代码。
(+) 非阻塞模式下接收数据使用 HAL_USART_Receive_IT()。
(+) 在接收结束时执行 HAL_USART_RxCpltCallback() 并且用户可以通过自定义函数指针 HAL_USART_RxCpltCallback 添加自己的代码。
(+) 在传输错误时执行 HAL_USART_ErrorCallback() 并且用户可以通过自定义函数指针 HAL_USART_ErrorCallback 添加自己的代码。
*** DMA 模式 IO 操作 ***
==============================
[..]
(+) 通过DMA以非阻塞模式发送数据使用 HAL_USART_Transmit_DMA()。
(+) 在发送过半时执行 HAL_USART_TxHalfCpltCallback() 并且用户可以通过自定义函数指针 HAL_USART_TxHalfCpltCallback 添加自己的代码。
(+) 在发送结束时执行 HAL_USART_TxCpltCallback() 并且用户可以通过自定义函数指针 HAL_USART_TxCpltCallback 添加自己的代码。
(+) 通过DMA以非阻塞模式接收数据使用 HAL_USART_Receive_DMA()。
(+) 在接收过半时执行 HAL_USART_RxHalfCpltCallback() 并且用户可以通过自定义函数指针 HAL_USART_RxHalfCpltCallback 添加自己的代码。
(+) 在接收结束时执行 HAL_USART_RxCpltCallback() 并且用户可以通过自定义函数指针 HAL_USART_RxCpltCallback 添加自己的代码。
(+) 在传输错误时执行 HAL_USART_ErrorCallback() 并且用户可以通过自定义函数指针 HAL_USART_ErrorCallback 添加自己的代码。
(+) 使用 HAL_USART_DMAPause() 暂停DMA传输。
(+) 使用 HAL_USART_DMAResume() 恢复DMA传输。
(+) 使用 HAL_USART_DMAStop() 停止DMA传输。
*** USART HAL 驱动宏列表 ***
=============================================
[..]
下面是USART HAL驱动程序中最常用的宏列表。
(+) __HAL_USART_ENABLE: 启用USART外设。
(+) __HAL_USART_DISABLE: 禁用USART外设。
(+) __HAL_USART_GET_FLAG : 检查指定的USART标志是否已设置。
(+) __HAL_USART_CLEAR_FLAG : 清除指定的USART挂起标志。
(+) __HAL_USART_ENABLE_IT: 启用指定的USART中断。
(+) __HAL_USART_DISABLE_IT: 禁用指定的USART中断。
[..]
(@) 您可以参考USART HAL驱动程序头文件以获取更多有用的宏。
##### 注册/注销回调 #####
==================================
[..]
当编译宏 USE_HAL_USART_REGISTER_CALLBACKS 被设置为 1 时,允许用户动态配置驱动程序回调函数。
[..]
使用函数 @ref HAL_USART_RegisterCallback() 来注册用户回调函数。
函数 @ref HAL_USART_RegisterCallback() 允许注册以下回调函数:
(+) TxHalfCpltCallback : 发送过半回调
(+) TxCpltCallback : 发送完成回调
(+) RxHalfCpltCallback : 接收过半回调
(+) RxCpltCallback : 接收完成回调
(+) TxRxCpltCallback : 发送接收完成回调
(+) ErrorCallback : 错误回调
(+) AbortCpltCallback : 中止完成回调
(+) MspInitCallback : USART MspInit 回调
(+) MspDeInitCallback : USART MspDeInit 回调
该函数的参数包括HAL外设句柄、回调ID和指向用户回调函数的指针。
[..]
使用函数 @ref HAL_USART_UnRegisterCallback() 来将回调函数重置为默认的预定义弱回调函数。
@ref HAL_USART_UnRegisterCallback() 函数的参数包括HAL外设句柄和回调ID。
该函数允许重置以下回调函数:
(+) TxHalfCpltCallback : 发送过半回调
(+) TxCpltCallback : 发送完成回调
(+) RxHalfCpltCallback : 接收过半回调
(+) RxCpltCallback : 接收完成回调
(+) TxRxCpltCallback : 发送接收完成回调
(+) ErrorCallback : 错误回调
(+) AbortCpltCallback : 中止完成回调
(+) MspInitCallback : USART MspInit 回调
(+) MspDeInitCallback : USART MspDeInit 回调
[..]
默认情况下,在 @ref HAL_USART_Init() 之后,当状态为 HAL_USART_STATE_RESET 时,所有回调函数都被设置为预定义弱回调函数:
例如 @ref HAL_USART_TxCpltCallback()、@ref HAL_USART_RxHalfCpltCallback()。
MspInit 和 MspDeInit 函数是例外,只有当这些回调函数为空(之前未注册)时,它们在 @ref HAL_USART_Init() 和 @ref HAL_USART_DeInit() 中被分别重置为预定义弱回调函数。
如果不是,MspInit 或 MspDeInit 不为空,那么 @ref HAL_USART_Init() 和 @ref HAL_USART_DeInit() 将保留并使用用户的 MspInit/MspDeInit 回调函数(之前已注册)。
[..]
回调函数只能在 HAL_USART_STATE_READY 状态下注册/注销。
MspInit/MspDeInit 是例外,它们可以在 HAL_USART_STATE_READY 或 HAL_USART_STATE_RESET 状态下注册/注销,因此注册(用户)的 MspInit/DeInit 回调函数可以在初始化/反初始化期间使用。
在这种情况下,首先使用 @ref HAL_USART_RegisterCallback() 注册 MspInit/MspDeInit 用户回调函数,然后再调用 @ref HAL_USART_DeInit() 或 @ref HAL_USART_Init() 函数。
[..]
当编译宏 USE_HAL_USART_REGISTER_CALLBACKS 被设置为 0 或未定义时,回调注册功能不可用,并且将使用预定义弱回调函数。
@endverbatim
[..]
(@) 附加说明:如果启用了奇偶校验,那么奇偶校验位将被写入数据寄存器中数据的最高位,随后被传输。
(也就是说数据的最高位将会被奇偶校验位替换,要注意校验位对数据的影响)
根据由 M 位(8位或9位)定义的帧长度,可能的USART帧格式如下表所示:
+-----------------------------------------------------------------------+
| M 位 | 校验使能 | USART 帧 |
|---------------------|-------------------------------------------------|
| 0 | 0 | | 起始位 | 8 数据位 | 停止位 | |
|---------|-----------|-------------------------------------------------|
| 0 | 1 | | 起始位 | 7 数据位 | 奇偶校验位 | 停止位 | |
|---------|-----------|-------------------------------------------------|
| 1 | 0 | | 起始位 | 9 数据位 | 停止位 | |
|---------|-----------|--------------------------------------------------|
| 1 | 1 | | 起始位 | 8 数据位 | 奇偶校验位 | 停止位 | |
+------------------------------------------------------------------------+
******************************************************************************
*/
/* 头文件 ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/** @addtogroup STM32F1xx_HAL_Driver
* @{
*/
/** @defgroup USART USART
* @brief HAL USART 同步模块驱动
* @{
*/
#ifdef HAL_USART_MODULE_ENABLED
/* 私有类型 -----------------------------------------------------------*/
/* 私有定义 ------------------------------------------------------------*/
/** @addtogroup USART_Private_Constants
* @{
*/
#define DUMMY_DATA 0xFFFFU
#define USART_TIMEOUT_VALUE 22000U
/**
* @}
*/
/* 私有宏 -------------------------------------------------------------*/
/* 私有变量 ---------------------------------------------------------*/
/* 私有函数原型 -----------------------------------------------*/
/* 私有函数 ---------------------------------------------------------*/
/** @addtogroup USART_Private_Functions
* @{
*/
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
static void USART_EndTxTransfer(USART_HandleTypeDef *husart);
static void USART_EndRxTransfer(USART_HandleTypeDef *husart);
static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart);
static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart);
static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart);
static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart);
static void USART_SetConfig(USART_HandleTypeDef *husart);
static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma);
static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
static void USART_DMAError(DMA_HandleTypeDef *hdma);
static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma);
static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status,
uint32_t Tickstart, uint32_t Timeout);
/**
* @}
*/
/* 导出函数 --------------------------------------------------------*/
/** @defgroup USART_Exported_Functions USART 导出函数
* @{
*/
/** @defgroup USART_Exported_Functions_Group1 USART 初始化和反初始化函数
* @brief 初始化和配置函数
*
@verbatim
==============================================================================
##### 初始化和配置函数 #####
==============================================================================
[..]
本节提供了一组函数,允许在异步和同步模式下初始化USART。
(+) 仅针对异步模式,可以配置以下参数:
(++) 波特率
(++) 数据位长度
(++) 停止位
(++) 奇偶校验:如果启用奇偶校验,那么写入数据寄存器的数据的最高位将被传输,但会被奇偶校验位改变。
根据由 M 位定义的帧长度(8位或9位),请参考参考手册了解可能的USART帧格式。
(++) USART极性
(++) USART相位
(++) USART最后一位
(++) 接收器/发送器模式
[..]
HAL_USART_Init() 函数遵循USART同步配置过程(有关过程的详细信息,请参阅参考手册(针对STM32F10Xxx微控制器的RM0008和针对STM32F100xx微控制器的RM0041))。
@endverbatim
* @{
*/
/**
* @brief 初始化USART模式,并初始化相关的句柄(根据 USART_InitTypeDef 中指定的参数)
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart)
{
/* 检查句柄 */
if (husart == NULL)
{
return HAL_ERROR;
}
/* 清除参数 */
assert_param(IS_USART_INSTANCE(husart->Instance));
if (husart->State == HAL_USART_STATE_RESET)
{
/* 分配锁资源并初始化 */
husart->Lock = HAL_UNLOCKED;
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
USART_InitCallbacksToDefault(husart);
if (husart->MspInitCallback == NULL)
{
husart->MspInitCallback = HAL_USART_MspInit;
}
/* 初始化底层硬件 */
husart->MspInitCallback(husart);
#else
/* 初始化底层硬件 : GPIO, CLOCK */
HAL_USART_MspInit(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
husart->State = HAL_USART_STATE_BUSY;
/* 设置 USART 通信参数 */
USART_SetConfig(husart);
/* 在USART模式下,必须保持以下位清零:
- USART_CR2(控制寄存器2)中的 LINEN(LIN模式使能)位
- USART_CR3(控制寄存器3)中的 HDSEL(半双工选择)、SCEN(智能卡模式使能)和 IREN(红外模式使能)位 */
CLEAR_BIT(husart->Instance->CR2, USART_CR2_LINEN);
CLEAR_BIT(husart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
/* 启用外设 */
__HAL_USART_ENABLE(husart);
/* 初始化 USART 状态 */
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_READY;
return HAL_OK;
}
/**
* @brief 反初始化 USART 外设
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart)
{
/* 检查句柄 */
if (husart == NULL)
{
return HAL_ERROR;
}
/* 清除参数 */
assert_param(IS_USART_INSTANCE(husart->Instance));
husart->State = HAL_USART_STATE_BUSY;
/* 禁用外设 */
__HAL_USART_DISABLE(husart);
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
if (husart->MspDeInitCallback == NULL)
{
husart->MspDeInitCallback = HAL_USART_MspDeInit;
}
/* 反初始化底层硬件 */
husart->MspDeInitCallback(husart);
#else
/* 反初始化底层硬件 */
HAL_USART_MspDeInit(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_RESET;
/* 释放锁 */
__HAL_UNLOCK(husart);
return HAL_OK;
}
/**
* @brief USART MSP 初始化
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
__weak void HAL_USART_MspInit(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE: 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
/**
* @brief USART MSP 反初始化
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
__weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE: 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/**
* @brief 注册用户的 USART 回调
* (替代预定义弱回调函数)
* @note 在 HAL_USART_STATE_RESET 状态下,可以在 HAL_USART_Init() 之前调用 HAL_USART_RegisterCallback(),
* 以注册 HAL_USART_MSPINIT_CB_ID 和 HAL_USART_MSPDEINIT_CB_ID 的回调。
* @param husart usart 句柄
* @param CallbackID 要注册的回调ID
* 该参数可以是以下数值之一:
* @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID 发送过半回调 ID
* @arg @ref HAL_USART_TX_COMPLETE_CB_ID 发送完成回调 ID
* @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID 接收过半回调 ID
* @arg @ref HAL_USART_RX_COMPLETE_CB_ID 接收完成回调 ID
* @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID 发送接收完成回调 ID
* @arg @ref HAL_USART_ERROR_CB_ID 错误回调 ID
* @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID 中止完成回调 ID
* @arg @ref HAL_USART_MSPINIT_CB_ID MspInit 回调 ID
* @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit 回调 ID
* @param pCallback 回调函数指针
* @retval HAL status
+ */
HAL_StatusTypeDef HAL_USART_RegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID,
pUSART_CallbackTypeDef pCallback)
{
HAL_StatusTypeDef status = HAL_OK;
if (pCallback == NULL)
{
/* 更新错误回调 */
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
return HAL_ERROR;
}
if (husart->State == HAL_USART_STATE_READY)
{
switch (CallbackID)
{
case HAL_USART_TX_HALFCOMPLETE_CB_ID :
husart->TxHalfCpltCallback = pCallback;
break;
case HAL_USART_TX_COMPLETE_CB_ID :
husart->TxCpltCallback = pCallback;
break;
case HAL_USART_RX_HALFCOMPLETE_CB_ID :
husart->RxHalfCpltCallback = pCallback;
break;
case HAL_USART_RX_COMPLETE_CB_ID :
husart->RxCpltCallback = pCallback;
break;
case HAL_USART_TX_RX_COMPLETE_CB_ID :
husart->TxRxCpltCallback = pCallback;
break;
case HAL_USART_ERROR_CB_ID :
husart->ErrorCallback = pCallback;
break;
case HAL_USART_ABORT_COMPLETE_CB_ID :
husart->AbortCpltCallback = pCallback;
break;
case HAL_USART_MSPINIT_CB_ID :
husart->MspInitCallback = pCallback;
break;
case HAL_USART_MSPDEINIT_CB_ID :
husart->MspDeInitCallback = pCallback;
break;
default :
/* 更新错误回调 */
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
/* 返回错误状态 */
status = HAL_ERROR;
break;
}
}
else if (husart->State == HAL_USART_STATE_RESET)
{
switch (CallbackID)
{
case HAL_USART_MSPINIT_CB_ID :
husart->MspInitCallback = pCallback;
break;
case HAL_USART_MSPDEINIT_CB_ID :
husart->MspDeInitCallback = pCallback;
break;
default :
/* 更新错误回调 */
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
/* 返回错误状态 */
status = HAL_ERROR;
break;
}
}
else
{
/* 更新错误回调 */
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
/* 返回错误状态 */
status = HAL_ERROR;
}
return status;
}
/**
* @brief 注销用户的 USART 回调
* (重置回调为默认的预定义弱回调函数)
* @note 在 HAL_USART_STATE_RESET 状态下,可以在 HAL_USART_Init() 之前调用 HAL_USART_UnRegisterCallback(),
* 以注销 HAL_USART_MSPINIT_CB_ID 和 HAL_USART_MSPDEINIT_CB_ID 的回调。
* @param husart usart 句柄
* @param CallbackID 要注销的回调ID
* 该参数可以是以下数值之一:
* @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID 发送过半回调 ID
* @arg @ref HAL_USART_TX_COMPLETE_CB_ID 发送完成回调 ID
* @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID 接收过半回调 ID
* @arg @ref HAL_USART_RX_COMPLETE_CB_ID 接收完成回调 ID
* @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID 发送接收完成回调 ID
* @arg @ref HAL_USART_ERROR_CB_ID 错误回调 ID
* @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID 中止完成回调 ID
* @arg @ref HAL_USART_MSPINIT_CB_ID MspInit 回调 ID
* @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit 回调 ID
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_UnRegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID)
{
HAL_StatusTypeDef status = HAL_OK;
if (husart->State == HAL_USART_STATE_READY)
{
switch (CallbackID)
{
case HAL_USART_TX_HALFCOMPLETE_CB_ID :
husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* 预定义弱回调函数 TxHalfCpltCallback */
break;
case HAL_USART_TX_COMPLETE_CB_ID :
husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* 预定义弱回调函数 TxCpltCallback */
break;
case HAL_USART_RX_HALFCOMPLETE_CB_ID :
husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* 预定义弱回调函数 RxHalfCpltCallback */
break;
case HAL_USART_RX_COMPLETE_CB_ID :
husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* 预定义弱回调函数 RxCpltCallback */
break;
case HAL_USART_TX_RX_COMPLETE_CB_ID :
husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* 预定义弱回调函数 TxRxCpltCallback */
break;
case HAL_USART_ERROR_CB_ID :
husart->ErrorCallback = HAL_USART_ErrorCallback; /* 预定义弱回调函数 ErrorCallback */
break;
case HAL_USART_ABORT_COMPLETE_CB_ID :
husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* 预定义弱回调函数 AbortCpltCallback */
break;
case HAL_USART_MSPINIT_CB_ID :
husart->MspInitCallback = HAL_USART_MspInit; /* 预定义弱回调函数 MspInitCallback */
break;
case HAL_USART_MSPDEINIT_CB_ID :
husart->MspDeInitCallback = HAL_USART_MspDeInit; /* 预定义弱回调函数 MspDeInitCallback */
break;
default :
/* 更新错误回调 */
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
/* 返回错误状态 */
status = HAL_ERROR;
break;
}
}
else if (husart->State == HAL_USART_STATE_RESET)
{
switch (CallbackID)
{
case HAL_USART_MSPINIT_CB_ID :
husart->MspInitCallback = HAL_USART_MspInit;
break;
case HAL_USART_MSPDEINIT_CB_ID :
husart->MspDeInitCallback = HAL_USART_MspDeInit;
break;
default :
/* 更新错误回调 */
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
/* 返回错误状态 */
status = HAL_ERROR;
break;
}
}
else
{
/* 更新错误回调 */
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
/* 返回错误状态 */
status = HAL_ERROR;
}
return status;
}
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
/**
* @}
*/
/** @defgroup USART_Exported_Functions_Group2 IO 操作函数
* @brief USART 发送和接收函数
*
@verbatim
==============================================================================
##### IO 操作函数 #####
==============================================================================
[..]
本节提供了一组函数,用于管理 USART 的同步数据传输。
[..]
USART 仅支持主模式:它不能 接收或发送 与 输入时钟相关的数据(SCLK 始终是输出)。
(#) 有两种传输模式:
(++) 阻塞模式:通信以轮询模式进行。所有数据处理的 HAL 状态在传输完成后由同一函数返回。
(++) 非阻塞模式:通信使用中断或 DMA 进行。这些 API 返回 HAL 状态。
数据处理的结束将通过专用的 USART IRQ(使用中断模式)或 DMA IRQ(使用 DMA 模式)指示。
当使用中断模式时,将分别执行 HAL_USART_TxCpltCallback()、HAL_USART_RxCpltCallback() 和 HAL_USART_TxRxCpltCallback() 用户回调函数,
在传输或接收过程结束时执行 HAL_USART_ErrorCallback() 用户回调函数,以侦测通信错误。
(#) 阻塞模式的 API 包括:
(++) HAL_USART_Transmit() 单工模式下
(++) HAL_USART_Receive() 全双工接收模式下
(++) HAL_USART_TransmitReceive() 全双工模式下
(#) 使用中断的非阻塞模式 API 包括:
(++) HAL_USART_Transmit_IT() 单工模式下
(++) HAL_USART_Receive_IT() 全双工接收模式下
(++) HAL_USART_TransmitReceive_IT() 全双工模式下
(++) HAL_USART_IRQHandler()
(#) Non Blocking mode functions with DMA are :
(++) HAL_USART_Transmit_DMA() 单工模式下
(++) HAL_USART_Receive_DMA() 全双工接收模式下
(++) HAL_USART_TransmitReceive_DMA() 全双工模式下
(++) HAL_USART_DMAPause()
(++) HAL_USART_DMAResume()
(++) HAL_USART_DMAStop()
(#) 非阻塞模式提供了一组传输完成回调函数:
(++) HAL_USART_TxHalfCpltCallback()
(++) HAL_USART_TxCpltCallback()
(++) HAL_USART_RxHalfCpltCallback()
(++) HAL_USART_RxCpltCallback()
(++) HAL_USART_ErrorCallback()
(++) HAL_USART_TxRxCpltCallback()
(#) 可以使用中止 API 中止非阻塞模式传输:
(++) HAL_USART_Abort()
(++) HAL_USART_Abort_IT()
(#) 对于基于中断的中止服务(HAL_USART_Abort_IT),提供了中止完成回调函数:
(++) HAL_USART_AbortCpltCallback()
(#) 在非阻塞模式传输中,可能出现的错误分为两类。
错误处理如下:
(++) 错误被视为可恢复且非阻塞:传输可以继续进行,但错误严重程度由用户评估:这涉及中断模式接收中的帧错误、奇偶校验错误或噪声错误。
然后检索接收到的字符并将其存储在 Rx 缓冲区中,设置错误代码以便用户识别错误类型,并执行 HAL_USART_ErrorCallback() 用户回调函数。
传输在 USART 端保持进行中。如果用户希望中止它,应由用户调用中止服务。
(++) 错误被视为阻塞:传输无法正确完成并被中止。这涉及中断模式接收中的溢出错误和 DMA 模式中的所有错误。
设置错误代码以便用户识别错误类型,并执行 HAL_USART_ErrorCallback() 用户回调函数。
@endverbatim
* @{
*/
/**
* @brief 单工 发送一定数量的数据(阻塞模式)
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 发送的数据将被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pTxData 提供的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pTxData 指向数据缓冲区的指针(u8 或 u16 数据元素)
* @param Size 要发送的数据(u8 或 u16)的数量。
* @param Timeout 超时持续时间。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size, uint32_t Timeout)
{
const uint8_t *ptxdata8bits;
const uint16_t *ptxdata16bits;
uint32_t tickstart;
if (husart->State == HAL_USART_STATE_READY)
{
if ((pTxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_TX;
/* 为超时管理初始化滴答 */
tickstart = HAL_GetTick();
husart->TxXferSize = Size;
husart->TxXferCount = Size;
/* 在使用 9 位&无奇偶校验传输时,pTxData 需要被视为 uint16_t 指针处理。 */
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
{
ptxdata8bits = NULL;
ptxdata16bits = (const uint16_t *) pTxData;
}
else
{
ptxdata8bits = pTxData;
ptxdata16bits = NULL;
}
while (husart->TxXferCount > 0U)
{
/* 等待 TXE(发送缓冲空)标志位以便向数据寄存器(DR)写入数据 */
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
if (ptxdata8bits == NULL)
{
husart->Instance->DR = (uint16_t)(*ptxdata16bits & (uint16_t)0x01FF);
ptxdata16bits++;
}
else
{
husart->Instance->DR = (uint8_t)(*ptxdata8bits & (uint8_t)0xFF);
ptxdata8bits++;
}
husart->TxXferCount--;
}
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
husart->State = HAL_USART_STATE_READY;
/* 进程解锁 */
__HAL_UNLOCK(husart);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 全双工 接收一定数量的数据(阻塞模式)
* @note 为了接收同步数据,同时传输虚拟数据。
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 接收到的数据被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pRxData 可用的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pRxData 指向数据缓冲区的指针(u8 或 u16 数据元素)
* @param Size 要接收的数据(u8 或 u16)的数量。
* @param Timeout 超时持续时间。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
{
uint8_t *prxdata8bits;
uint16_t *prxdata16bits;
uint32_t tickstart;
if (husart->State == HAL_USART_STATE_READY)
{
if ((pRxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_RX;
/* 为超时管理初始化滴答 */
tickstart = HAL_GetTick();
husart->RxXferSize = Size;
husart->RxXferCount = Size;
/* 在使用 9 位&无奇偶校验传输时,pRxData 需要被视为 uint16_t 指针处理。 */
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
{
prxdata8bits = NULL;
prxdata16bits = (uint16_t *) pRxData;
}
else
{
prxdata8bits = pRxData;
prxdata16bits = NULL;
}
/* 检查剩余待接收的数据 */
while (husart->RxXferCount > 0U)
{
/* 等待直到 TXE(发送缓冲空)标志位设置,以发送虚拟字节以生成时钟,以便从设备发送数据。
* 无论帧长度(7、8 或 9 位),都可以为所有情况写入相同的虚拟值。 */
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x0FF);
/* 等待直到 RXNE(接收缓冲非空)标志位设置以接收字节 */
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
if (prxdata8bits == NULL)
{
*prxdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
prxdata16bits++;
}
else
{
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
{
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x0FF);
}
else
{
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x07F);
}
prxdata8bits++;
}
husart->RxXferCount--;
}
husart->State = HAL_USART_STATE_READY;
/* 进程解锁 */
__HAL_UNLOCK(husart);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 全双工 发送并接收一定数量的数据(阻塞模式)
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 发送的数据和接收的数据被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pTxData 和 pRxData 可用的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pTxData 指向 TX 数据缓冲区(u8 或 u16 数据元素)的指针。
* @param pRxData 指向 RX 数据缓冲区(u8 或 u16 数据元素)的指针。
* @param Size 要发送的数据(u8 或 u16)的数量(接收的数量与发送的数量相同)。
* @param Timeout 超时时长
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
uint16_t Size, uint32_t Timeout)
{
uint8_t *prxdata8bits;
uint16_t *prxdata16bits;
const uint8_t *ptxdata8bits;
const uint16_t *ptxdata16bits;
uint16_t rxdatacount;
uint32_t tickstart;
if (husart->State == HAL_USART_STATE_READY)
{
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 在进行 9 位&无奇偶校验传输时,作为输入参数提供的 pTxData 和 pRxData 缓冲区应该在 u16 边界上对齐,
因为要填入 TDR / 从 RDR 检索的数据将通过 u16 强制转换处理。*/
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
{
if (((((uint32_t)pTxData) & 1U) != 0U) || ((((uint32_t)pRxData) & 1U) != 0U))
{
return HAL_ERROR;
}
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_RX;
/* 为超时管理初始化滴答 */
tickstart = HAL_GetTick();
husart->RxXferSize = Size;
husart->TxXferSize = Size;
husart->TxXferCount = Size;
husart->RxXferCount = Size;
/* 在使用 9 位&无奇偶校验传输时,pRxData 需要被视为 uint16_t 指针处理。 */
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
{
prxdata8bits = NULL;
ptxdata8bits = NULL;
ptxdata16bits = (const uint16_t *) pTxData;
prxdata16bits = (uint16_t *) pRxData;
}
else
{
prxdata8bits = pRxData;
ptxdata8bits = pTxData;
ptxdata16bits = NULL;
prxdata16bits = NULL;
}
/* 检查剩余待接收的数据 */
/* rxdatacount 是用于 MISRA C 2012 规则 13.5 的临时变量。 */
rxdatacount = husart->RxXferCount;
while ((husart->TxXferCount > 0U) || (rxdatacount > 0U))
{
if (husart->TxXferCount > 0U)
{
/* 等待 TXE(发送缓冲空)标志位以便向数据寄存器(DR)写入数据 */
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
if (ptxdata8bits == NULL)
{
husart->Instance->DR = (uint16_t)(*ptxdata16bits & (uint16_t)0x01FF);
ptxdata16bits++;
}
else
{
husart->Instance->DR = (uint8_t)(*ptxdata8bits & (uint8_t)0xFF);
ptxdata8bits++;
}
husart->TxXferCount--;
}
if (husart->RxXferCount > 0U)
{
/* 等待 RXNE(接收缓冲非空)标志置位 */
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
if (prxdata8bits == NULL)
{
*prxdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
prxdata16bits++;
}
else
{
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
{
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x0FF);
}
else
{
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x07F);
}
prxdata8bits++;
}
husart->RxXferCount--;
}
rxdatacount = husart->RxXferCount;
}
husart->State = HAL_USART_STATE_READY;
/* 进程解锁 */
__HAL_UNLOCK(husart);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 单工 发送一定数量的数据 - 中断(非阻塞模式)
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 发送的数据将被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pTxData 提供的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pTxData 指向数据缓冲区的指针(u8 或 u16 数据元素)
* @param Size 要发送的数据(u8 或 u16)的数量。
* @retval HAL status
* @note 未对 USART 错误进行处理,以避免溢出错误。
*/
HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size)
{
if (husart->State == HAL_USART_STATE_READY)
{
if ((pTxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->pTxBuffPtr = pTxData;
husart->TxXferSize = Size;
husart->TxXferCount = Size;
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_TX;
/* USART 错误中断(帧错误、噪声错误、溢出错误)未由 USART 发送过程进行管理,以避免溢出中断。
当 USART 模式配置为发送和接收 "USART_MODE_TX_RX" 时,应该仅配置为仅发送以充分利用帧错误和噪声中断。
可以使用 __HAL_USART_ENABLE_IT(husart, USART_IT_ERR) 来启用帧错误、噪声错误中断。 */
/* 进程解锁 */
__HAL_UNLOCK(husart);
/* 启用 USART 发送数据寄存器空中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 单工 接收一定数量的数据 - 中断(非阻塞模式)
* @note 为了接收同步数据,同时传输虚拟数据。
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 接收到的数据被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pRxData 可用的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pRxData 指向数据缓冲区的指针(u8 或 u16 数据元素)
* @param Size 要接收的数据(u8 或 u16)的数量。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size)
{
if (husart->State == HAL_USART_STATE_READY)
{
if ((pRxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->pRxBuffPtr = pRxData;
husart->RxXferSize = Size;
husart->RxXferCount = Size;
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_RX;
/* 进程解锁 */
__HAL_UNLOCK(husart);
if (husart->Init.Parity != USART_PARITY_NONE)
{
/* 启用 USART 奇偶校验错误 和 接收数据寄存器非空中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
}
else
{
/* 启用 USART 接收数据寄存器非空中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
}
/* 启用 USART 错误中断: (帧错误,噪声错误,溢出错误) */
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
/* 发送虚拟字节以生成时钟,以便从设备发送数据。 */
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x01FF);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 全双工 发起并接收一定数量的数据 - (非阻塞模式)
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 发送的数据和接收的数据被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pTxData 和 pRxData 可用的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pTxData 指向 TX 数据缓冲区(u8 或 u16 数据元素)的指针。
* @param pRxData 指向 RX 数据缓冲区(u8 或 u16 数据元素)的指针。
* @param Size 要发送的数据(u8 或 u16)的数量(接收的数量与发送的数量相同)。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
uint16_t Size)
{
if (husart->State == HAL_USART_STATE_READY)
{
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->pRxBuffPtr = pRxData;
husart->RxXferSize = Size;
husart->RxXferCount = Size;
husart->pTxBuffPtr = pTxData;
husart->TxXferSize = Size;
husart->TxXferCount = Size;
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_TX_RX;
/* 进程解锁 */
__HAL_UNLOCK(husart);
/* 启用 USART 数据寄存器非空中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
if (husart->Init.Parity != USART_PARITY_NONE)
{
/* 启用 USART 奇偶校验位错误中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
}
/* 启用 USART 错误中断: (帧错误,噪声错误,溢出错误) */
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
/* 启用 USART 发送数据寄存器空中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 单工 发送一定数量的数据 - DMA(非阻塞模式)
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 发送的数据将被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pTxData 提供的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pTxData 指向数据缓冲区的指针(u8 或 u16 数据元素)
* @param Size 要发送的数据(u8 或 u16)的数量。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size)
{
const uint32_t *tmp;
if (husart->State == HAL_USART_STATE_READY)
{
if ((pTxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->pTxBuffPtr = pTxData;
husart->TxXferSize = Size;
husart->TxXferCount = Size;
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_TX;
/* 设置 USART DMA 发送完成回调 */
husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt;
/* 设置 USART DMA 发送过半回调 */
husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt;
/* 设置 DMA 错误回调 */
husart->hdmatx->XferErrorCallback = USART_DMAError;
/* 设置 DMA 中止回调 */
husart->hdmatx->XferAbortCallback = NULL;
/* 启用 USART 发送 DMA 通道 */
tmp = (const uint32_t *)&pTxData;
HAL_DMA_Start_IT(husart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
/* 通过向 SR(状态)寄存器写入 0 来清除 TC(发送完成)标志 */
__HAL_USART_CLEAR_FLAG(husart, USART_FLAG_TC);
/* 进程解锁 */
__HAL_UNLOCK(husart);
/* 通过在 USART CR3(控制寄存器3)中设置 DMAT(DMA使能发送)位来启用 DMA 传输发送请求。 */
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 全双工 接收一定数量的数据 - DMA(非阻塞模式)
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 接收到的数据被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pRxData 可用的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pRxData 指向数据缓冲区的指针(u8 或 u16 数据元素)
* @param Size 要接收的数据(u8 或 u16)的数量。
* @retval HAL status
* @note 必须配置 USART DMA 发送通道以生成从机的时钟。
* @note 当启用 USART 奇偶校验 (PCE = 1) 时,接收到的数据包含奇偶校验位。
*/
HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size)
{
uint32_t *tmp;
if (husart->State == HAL_USART_STATE_READY)
{
if ((pRxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->pRxBuffPtr = pRxData;
husart->RxXferSize = Size;
husart->pTxBuffPtr = pRxData;
husart->TxXferSize = Size;
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_RX;
/* 设置 USART DMA 接收完成回调 */
husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt;
/* 设置 USART DMA 接收过半回调 */
husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt;
/* 设置 USART DMA 接收错误回调 */
husart->hdmarx->XferErrorCallback = USART_DMAError;
/* 设置 DMA 中止回调 */
husart->hdmarx->XferAbortCallback = NULL;
/* 将 USART Tx DMA 传输完成回调函数设置为 NULL,因为通信的关闭是在 DMA 接收完成回调函数中执行的。 */
husart->hdmatx->XferHalfCpltCallback = NULL;
husart->hdmatx->XferCpltCallback = NULL;
/* 设置 DMA 错误回调 */
husart->hdmatx->XferErrorCallback = USART_DMAError;
/* 设置 DMA AbortCpltCallback 中止完成回调 */
husart->hdmatx->XferAbortCallback = NULL;
/* 设置 USART 接收 DMA 通道 */
tmp = (uint32_t *)&pRxData;
HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->DR, *(uint32_t *)tmp, Size);
/* 启用 USART 发送 DMA 通道:发送通道用于以非阻塞模式为从机设备生成时钟,这种模式不是单工接收模式,而是全双工接收模式。 */
HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
/* 在启用 DMA Rx 请求之前清除溢出标志:这对于第二次传输是必需的。 */
__HAL_USART_CLEAR_OREFLAG(husart);
/* 进程解锁 */
__HAL_UNLOCK(husart);
if (husart->Init.Parity != USART_PARITY_NONE)
{
/* 启用 USART 奇偶校验错误中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
}
/* 启用 USART 错误中断: (帧错误,噪声错误,溢出错误) */
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
/* 通过在 USART CR3(控制寄存器3)中设置 DMAR(DMA发送使能)位来启用接收请求的 DMA 传输。 */
SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
/* 通过在 USART CR3(控制寄存器3)中设置 DMAT(DMA发送使能)位来启用发送请求的 DMA 传输。 */
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 全双工 发送并接收一定数量的数据 - 中断(非阻塞模式)
* @note 当 USART 奇偶校验未启用(PCE = 0)且字长配置为 9 位(M1-M0 = 01)时,
* 发送的数据和接收的数据被视为一组 u16。
* 在这种情况下,Size 必须指示通过 pTxData 和 pRxData 可用的 u16 数量。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param pTxData 指向 TX 数据缓冲区(u8 或 u16 数据元素)的指针。
* @param pRxData 指向 RX 数据缓冲区(u8 或 u16 数据元素)的指针。
* @param Size 要接收/发送的数据数量(u8 或 u16)
* @note 当启用了 USART 奇偶校验 (PCE = 1) 时,接收到的数据会包含奇偶校验位。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
uint16_t Size)
{
const uint32_t *tmp;
if (husart->State == HAL_USART_STATE_READY)
{
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
{
return HAL_ERROR;
}
/* 进程锁定 */
__HAL_LOCK(husart);
husart->pRxBuffPtr = pRxData;
husart->RxXferSize = Size;
husart->pTxBuffPtr = pTxData;
husart->TxXferSize = Size;
husart->ErrorCode = HAL_USART_ERROR_NONE;
husart->State = HAL_USART_STATE_BUSY_TX_RX;
/* 设置 USART DMA 接收完成回调 */
husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt;
/* 设置 USART DMA 发送过半回调 */
husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt;
/* 设置 USART DMA 发送完成回调 */
husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt;
/* 设置 USART DMA 发送过半回调 */
husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt;
/* 设置 USART DMA 发送错误回调 */
husart->hdmatx->XferErrorCallback = USART_DMAError;
/* 设置 USART DMA 接收传输错误回调 */
husart->hdmarx->XferErrorCallback = USART_DMAError;
/* 设置 DMA 中止回调 */
husart->hdmarx->XferAbortCallback = NULL;
/* 启用 USART 接收 DMA 通道 */
tmp = (uint32_t *)&pRxData;
HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->DR, *(const uint32_t *)tmp, Size);
/* 启用 USART 发送 DMA 通道 */
tmp = (const uint32_t *)&pTxData;
HAL_DMA_Start_IT(husart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
/* 通过向 SR(状态)寄存器写入 0 来清除 TC(发送完成)标志 */
__HAL_USART_CLEAR_FLAG(husart, USART_FLAG_TC);
/* 清除溢出标志:在循环模式下进行第二次传输时是必需的。 */
__HAL_USART_CLEAR_OREFLAG(husart);
/* 进程解锁 */
__HAL_UNLOCK(husart);
if (husart->Init.Parity != USART_PARITY_NONE)
{
/* 启用 USART 奇偶校验错误中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
}
/* 启用 USART 错误中断: (帧错误,噪声错误,溢出错误) */
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
/* 通过在 USART CR3(控制寄存器3)中设置 DMAR 位来启用接收请求的 DMA 传输。 */
SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
/* 通过在 USART CR3(控制寄存器3)寄存器中设置 DMAT 位来启用发送请求的 DMA 传输。 */
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 暂停 DMA 传输
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart)
{
/* 进程锁定 */
__HAL_LOCK(husart);
/* 禁用 USART DMA Tx 请求 */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
/* 进程解锁 */
__HAL_UNLOCK(husart);
return HAL_OK;
}
/**
* @brief 启用 DMA 传输
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart)
{
/* 进程锁定 */
__HAL_LOCK(husart);
/* 启用 USART DMA Tx 请求 */
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
/* 进程解锁 */
__HAL_UNLOCK(husart);
return HAL_OK;
}
/**
* @brief 停止 DMA 传输
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_DMAStop(USART_HandleTypeDef *husart)
{
uint32_t dmarequest = 0x00U;
/* 此 API 中未实现锁定功能,以允许用户应用程序在回调 HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback() 中调用 HAL USART API。
当调用 HAL_DMA_Abort() API 时,将会生成 DMA TX/RX 传输完成中断,并执行相应的回调 HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback()。*/
/* 停止 USART DMA 发送请求,如果正在进行中 */
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT);
if ((husart->State == HAL_USART_STATE_BUSY_TX) && dmarequest)
{
USART_EndTxTransfer(husart);
/* 中止 USART DMA Tx 通道 */
if (husart->hdmatx != NULL)
{
HAL_DMA_Abort(husart->hdmatx);
}
/* 禁用 USART Tx DMA 请求 */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
}
/* 停止 USART DMA 接收请求,如果正在进行中。 */
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
if ((husart->State == HAL_USART_STATE_BUSY_RX) && dmarequest)
{
USART_EndRxTransfer(husart);
/* 中止 USART DMA 传输通道 */
if (husart->hdmarx != NULL)
{
HAL_DMA_Abort(husart->hdmarx);
}
/* 禁用 USART 输入请求 */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
}
return HAL_OK;
}
/**
* @brief 中止正在进行的传输(则是模式)
* @param husart usart 句柄.
* @note 该过程可用于中止在中断或 DMA 模式下启动的任何正在进行的传输(如由 TransferType 参数描述的 Tx 或 Rx)。
* 该过程执行以下操作:
* - 禁用 PPP 中断(取决于传输方向)
* - 在外设寄存器中禁用 DMA 传输(如果已启用)
* - 通过调用 HAL_DMA_Abort 中止 DMA 传输(在 DMA 模式下的传输情况)
* - 将句柄状态设置为 READY
* @note 该过程以阻塞模式执行:在退出函数时,中止被视为已完成。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_Abort(USART_HandleTypeDef *husart)
{
/* 禁用 TXEIE(发送非空)、TCIE(发送完成)、ERR(错误) (帧错误,噪声错误,溢出错误) 中断 */
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
/* 禁用 USART DMA Tx 请求(如果使能了) */
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
{
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
/* 中止 USART DMA Tx 通道 : 使用阻塞的 DMA 中止 API(无回调) */
if (husart->hdmatx != NULL)
{
/* 将 USART DMA 中止回调设置为 Null。
将 USART DMA 中止在 DMA 中止过程结束时不执行回调。调设置为 Null。 */
husart->hdmatx->XferAbortCallback = NULL;
HAL_DMA_Abort(husart->hdmatx);
}
}
/* 禁用 USART DMA Rx 请求(如果启用了)*/
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
{
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
/* 中止 USART DMA 传输通道 : 使用阻塞的 DMA 中止 API(无回调) */
if (husart->hdmarx != NULL)
{
/* 将 USART DMA 中止回调设置为 Null。
将 USART DMA 中止在 DMA 中止过程结束时不执行回调。调设置为 Null。 */
husart->hdmarx->XferAbortCallback = NULL;
HAL_DMA_Abort(husart->hdmarx);
}
}
/* 重置 发送和接收传输计数器 */
husart->TxXferCount = 0x00U;
husart->RxXferCount = 0x00U;
/* 将 husart->State 恢复为 Ready 状态 */
husart->State = HAL_USART_STATE_READY;
/* 重置错误代码为 无错误 */
husart->ErrorCode = HAL_USART_ERROR_NONE;
return HAL_OK;
}
/**
* @brief 中止正在进行的传输 - 中断
* @param husart usart 句柄.
* @note 该过程可用于中止在中断或 DMA 模式下启动的任何正在进行的传输(如由 TransferType 参数描述的 Tx 或 Rx)
* 该过程执行以下操作:
* - 禁用 PPP 中断(取决于传输方向)
* - 在外设寄存器中禁用 DMA 传输(如果已启用)
* - 通过调用 HAL_DMA_Abort_IT 中止 DMA 传输(在 DMA 模式下的传输情况)。
* - 将句柄状态设置为 READY
* - 在中止完成时,调用用户中止完成回调
* @note 该过程以中断模式执行,这意味着中止过程只有在执行用户中止完成回调时才被视为已完成(而不是在退出函数时)。
* @retval HAL status
*/
HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart)
{
uint32_t AbortCplt = 0x01U;
/* 禁用 TXEIE(发送非空)、TCIE(发送完成)、ERR(错误) (帧错误,噪声错误,溢出错误) 中断 */
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
/* 如果 DMA Tx 和/或 DMA Rx 句柄与 USART 句柄相关联,则应在调用任何 DMA 中止函数之前初始化 DMA 中止完成回调。 */
/* DMA Tx 句柄无效 */
if (husart->hdmatx != NULL)
{
/* 如果启用了 USART DMA Tx 请求,则设置 DMA 中止完成回调。否则,将其设置为 NULL。 */
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
{
husart->hdmatx->XferAbortCallback = USART_DMATxAbortCallback;
}
else
{
husart->hdmatx->XferAbortCallback = NULL;
}
}
/* DMA Rx 句柄无效 */
if (husart->hdmarx != NULL)
{
/* 如果启用了 USART DMA Rx 请求,则设置 DMA 中止完成回调。否则,将其设置为 NULL。 */
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
{
husart->hdmarx->XferAbortCallback = USART_DMARxAbortCallback;
}
else
{
husart->hdmarx->XferAbortCallback = NULL;
}
}
/* 禁用 USART DMA Tx 请求(如果启用了) */
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
{
/* 禁用 DMA Tx 请求 */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
/* 中止 USART DMA Tx 通道 : 使用非阻塞 DMA 中止 API(回调) */
if (husart->hdmatx != NULL)
{
/* USART Tx DMA 中止回调已经被初始化:
将在 DMA 中止过程结束时调用 HAL_USART_AbortCpltCallback()。 */
/* 中止 DMA 发送 */
if (HAL_DMA_Abort_IT(husart->hdmatx) != HAL_OK)
{
husart->hdmatx->XferAbortCallback = NULL;
}
else
{
AbortCplt = 0x00U;
}
}
}
/* 禁用 USART DMA Rx 请求(如果启用了) */
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
{
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
/* 中止 USART DMA 传输通道 : 使用非阻塞 DMA 中止 API(回调) */
if (husart->hdmarx != NULL)
{
/* USART Rx DMA 中止回调已经被初始化:
将在 DMA 中止过程结束时调用 HAL_USART_AbortCpltCallback()。 */
/* Abort DMA 接收 */
if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK)
{
husart->hdmarx->XferAbortCallback = NULL;
AbortCplt = 0x01U;
}
else
{
AbortCplt = 0x00U;
}
}
}
/* 如果不需要执行 DMA 中止完成回调,则调用用户中止完成回调。 */
if (AbortCplt == 0x01U)
{
/* 重置 Tx 和 Rx 传输计数器 */
husart->TxXferCount = 0x00U;
husart->RxXferCount = 0x00U;
/* 重置错误代码 */
husart->ErrorCode = HAL_USART_ERROR_NONE;
/* 将 husart->State 恢复为 Ready 状态 */
husart->State = HAL_USART_STATE_READY;
/* 由于没有要中止的 DMA,直接调用用户中止完成回调。 */
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的中止完成回调 */
husart->AbortCpltCallback(husart);
#else
/* 调用预定义弱中止完成回调函数 */
HAL_USART_AbortCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
return HAL_OK;
}
/**
* @brief 处理 USART 中断请求的函数
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
void HAL_USART_IRQHandler(USART_HandleTypeDef *husart)
{
uint32_t isrflags = READ_REG(husart->Instance->SR);
uint32_t cr1its = READ_REG(husart->Instance->CR1);
uint32_t cr3its = READ_REG(husart->Instance->CR3);
uint32_t errorflags = 0x00U;
uint32_t dmarequest = 0x00U;
/* 如果无错误发生 */
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
if (errorflags == RESET)
{
/* USART 处于接收机 -------------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
if (husart->State == HAL_USART_STATE_BUSY_RX)
{
USART_Receive_IT(husart);
}
else
{
USART_TransmitReceive_IT(husart);
}
return;
}
}
/* 如果有错误发生 */
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
{
/* USART 奇偶校验错误中断发生 ----------------------------------*/
if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
{
husart->ErrorCode |= HAL_USART_ERROR_PE;
}
/* USART 噪声错误中断发生 --------------------------------*/
if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
husart->ErrorCode |= HAL_USART_ERROR_NE;
}
/* USART 帧错误中断发生 --------------------------------*/
if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
{
husart->ErrorCode |= HAL_USART_ERROR_FE;
}
/* USART 溢出中断发生 -----------------------------------*/
if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
{
husart->ErrorCode |= HAL_USART_ERROR_ORE;
}
if (husart->ErrorCode != HAL_USART_ERROR_NONE)
{
/* USART 处于接收机 -----------------------------------------------*/
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
{
if (husart->State == HAL_USART_STATE_BUSY_RX)
{
USART_Receive_IT(husart);
}
else
{
USART_TransmitReceive_IT(husart);
}
}
/* 如果发生溢出错误,或者在DMA模式接收中发生任何错误,则将错误视为阻塞错误 */
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
if (((husart->ErrorCode & HAL_USART_ERROR_ORE) != RESET) || dmarequest)
{
/* 将 USART 状态设置为准备就绪,以便能够重新开始该过程,如果正在进行中,禁用 Rx 中断并禁用 Rx DMA 请求。 */
USART_EndRxTransfer(husart);
/* 禁用 USART DMA 接收请求(如果启用了) */
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
{
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
/* 中止 USART DMA 传输通道 */
if (husart->hdmarx != NULL)
{
/* 设置 USART DMA 中止回调:
将导致在DMA中止过程结束时调用 HAL_USART_ErrorCallback() */
husart->hdmarx->XferAbortCallback = USART_DMAAbortOnError;
if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK)
{
/* 在发生错误时直接调用XferAbortCallback函数 */
husart->hdmarx->XferAbortCallback(husart->hdmarx);
}
}
else
{
/* 调用用户错误回调 */
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的错误回调 */
husart->ErrorCallback(husart);
#else
/* 调用预定义弱错误回调函数 */
HAL_USART_ErrorCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
}
else
{
/* 调用用户错误回调 */
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的错误回调 */
husart->ErrorCallback(husart);
#else
/* 调用预定义弱错误回调函数 */
HAL_USART_ErrorCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
}
else
{
/* 调用用户错误回调 */
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的错误回调 */
husart->ErrorCallback(husart);
#else
/* 调用预定义弱错误回调函数 */
HAL_USART_ErrorCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
husart->ErrorCode = HAL_USART_ERROR_NONE;
}
}
return;
}
/* USART 处于发送机 -----------------------------------------------*/
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
{
if (husart->State == HAL_USART_STATE_BUSY_TX)
{
USART_Transmit_IT(husart);
}
else
{
USART_TransmitReceive_IT(husart);
}
return;
}
/* USART 处于发送机 (发送结束) ----------------------------*/
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
{
USART_EndTransmit_IT(husart);
return;
}
}
/**
* @brief 发送完成回调
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
__weak void HAL_USART_TxCpltCallback(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE: 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
/**
* @brief 发送过半回调
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
__weak void HAL_USART_TxHalfCpltCallback(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE: 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
/**
* @brief 接收完成回调
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
__weak void HAL_USART_RxCpltCallback(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE: 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
/**
* @brief 接收过半回调
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
__weak void HAL_USART_RxHalfCpltCallback(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE: 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
/**
* @brief 发送接收完成回调
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
__weak void HAL_USART_TxRxCpltCallback(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE: 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
/**
* @brief USART 错误回调
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
__weak void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE: 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
/**
* @brief USART 中止完成回调
* @param husart usart 句柄.
* @retval None
*/
__weak void HAL_USART_AbortCpltCallback(USART_HandleTypeDef *husart)
{
/* 防止未使用参数的编译警告 */
UNUSED(husart);
/* NOTE : 当需要回调函数时,不应修改此函数,可以在用户文件中重写以覆盖此函数。
*/
}
/**
* @}
*/
/** @defgroup USART_Exported_Functions_Group3 外设状态和错误函数
* @brief USART 状态和错误函数
*
@verbatim
==============================================================================
##### 外设状态和错误函数 #####
==============================================================================
[..]
本节提供了一组函数,用于返回 USART 通信过程的状态,返回通信过程中发生的外设错误。
(+) HAL_USART_GetState() API 可以帮助在运行时检查 USART 外设的状态。
(+) HAL_USART_GetError() 在运行时检查可能发生的通信错误。
@endverbatim
* @{
*/
/**
* @brief 获取 USART 状态
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL state
*/
HAL_USART_StateTypeDef HAL_USART_GetState(const USART_HandleTypeDef *husart)
{
return husart->State;
}
/**
* @brief 获取 USART 错误代码
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval USART 错误代码
*/
uint32_t HAL_USART_GetError(const USART_HandleTypeDef *husart)
{
return husart->ErrorCode;
}
/**
* @}
*/
/** @defgroup USART_Private_Functions USART 私有函数
* @{
*/
/**
* @brief 初始化回调为默认值
* @param husart usart 句柄.
* @retval none
*/
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart)
{
/* 初始化 USART 回调设置 */
husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* 预定义弱回调函数 TxHalfCpltCallback */
husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* 预定义弱回调函数 TxCpltCallback */
husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* 预定义弱回调函数 RxHalfCpltCallback */
husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* 预定义弱回调函数 RxCpltCallback */
husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* 预定义弱回调函数 TxRxCpltCallback */
husart->ErrorCallback = HAL_USART_ErrorCallback; /* 预定义弱回调函数 ErrorCallback */
husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* 预定义弱回调函数 AbortCpltCallback */
}
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
/**
* @brief DMA USART 发送完成回调
* @param hdma 指向包含指定DMA模块的配置信息的DMA_HandleTypeDef结构体的指针
* @retval None
*/
static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* DMA 普通模式 */
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
husart->TxXferCount = 0U;
if (husart->State == HAL_USART_STATE_BUSY_TX)
{
/* 通过在USART的CR3(控制寄存器3)中设置DMAT(DMA使能发送)位来禁用发送请求的DMA传输 */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
/* 启用 USART 发送完成中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_TCIE);
}
}
/* DMA 循环模式 */
else
{
if (husart->State == HAL_USART_STATE_BUSY_TX)
{
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的发送完成回调 */
husart->TxCpltCallback(husart);
#else
/* 调用预定义的弱发送完成回调 */
HAL_USART_TxCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
}
}
/**
* @brief DMA USART 发送过半回调
* @param hdma 指向包含指定DMA模块的配置信息的DMA_HandleTypeDef结构体的指针
* @retval None
*/
static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
{
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的发送过半回调 */
husart->TxHalfCpltCallback(husart);
#else
/* 调用预定义的弱发送过半回调 */
HAL_USART_TxHalfCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
/**
* @brief DMA USART 接收完成回调
* @param hdma 指向包含指定DMA模块的配置信息的DMA_HandleTypeDef结构体的指针
* @retval None
*/
static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
{
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* DMA 普通模式 */
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
husart->RxXferCount = 0x00U;
/* 禁用 RXNE(接收缓冲非空), PE(奇偶校验)和 ERR(错误)(帧错误, 噪声错误, 溢出错误) 中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
/* 通过在USART的CR3寄存器中设置DMAR(DMA接收使能)位来禁用接收请求的DMA传输 */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
/* 如果 USART 状态为 HAL_USART_STATE_BUSY_RX */
if (husart->State == HAL_USART_STATE_BUSY_RX)
{
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的接收完成回调 */
husart->RxCpltCallback(husart);
#else
/* 调用预定义弱接收完成回调函数 */
HAL_USART_RxCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
/* The USART state is HAL_USART_STATE_BUSY_TX_RX */
else
{
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的发送接收完成回调 */
husart->TxRxCpltCallback(husart);
#else
/* 调用预定义弱发送接收完成回调函数 */
HAL_USART_TxRxCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
husart->State = HAL_USART_STATE_READY;
}
/* DMA 循环模式 */
else
{
if (husart->State == HAL_USART_STATE_BUSY_RX)
{
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的接收完成回调 */
husart->RxCpltCallback(husart);
#else
/* 调用预定义弱接收完成回调函数 */
HAL_USART_RxCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
/* USART 状态为 HAL_USART_STATE_BUSY_TX_RX */
else
{
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的发送接收完成回调 */
husart->TxRxCpltCallback(husart);
#else
/* 调用预定义弱发送接收完成回调函数 */
HAL_USART_TxRxCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
}
}
/**
* @brief DMA USART 接收过半回调
* @param hdma 指向包含指定DMA模块的配置信息的DMA_HandleTypeDef结构体的指针
* @retval None
*/
static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
{
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的接收过半回调 */
husart->RxHalfCpltCallback(husart);
#else
/* 调用预定义弱接收过半回调函数 */
HAL_USART_RxHalfCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
/**
* @brief DMA USART communication 错误回调
* @param hdma 指向包含指定DMA模块的配置信息的DMA_HandleTypeDef结构体的指针
* @retval None
*/
static void USART_DMAError(DMA_HandleTypeDef *hdma)
{
uint32_t dmarequest = 0x00U;
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
husart->RxXferCount = 0x00U;
husart->TxXferCount = 0x00U;
/* 停止 USART DMA 发送请求,如果正在进行中 */
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT);
if ((husart->State == HAL_USART_STATE_BUSY_TX) && dmarequest)
{
USART_EndTxTransfer(husart);
}
/* 停止 USART DMA 接收请求,如果正在进行中。 */
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
if ((husart->State == HAL_USART_STATE_BUSY_RX) && dmarequest)
{
USART_EndRxTransfer(husart);
}
husart->ErrorCode |= HAL_USART_ERROR_DMA;
husart->State = HAL_USART_STATE_READY;
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的错误回调 */
husart->ErrorCallback(husart);
#else
/* 调用预定义弱错误回调函数 */
HAL_USART_ErrorCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
/**
* @brief 这个函数处理USART通信超时。它会等待直到标志不再处于指定的状态。
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @param Flag 指定要检查的 USART 标志
* @param Status 实际的标志状态 (SET 或 RESET).
* @param Tickstart 滴答起始值
* @param Timeout 超时持续时间。
* @retval HAL status
*/
static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status,
uint32_t Tickstart, uint32_t Timeout)
{
/* 等待,直到标志为非指定状态 */
while ((__HAL_USART_GET_FLAG(husart, Flag) ? SET : RESET) == Status)
{
/* 检查超时 */
if (Timeout != HAL_MAX_DELAY)
{
if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
{
/* 禁用 USART 发送缓冲空中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
/* 禁用 USART RXNE(接收缓冲非空)中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
/* 禁用 USART 奇偶校验错误中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
/* 禁用 USART 错误中断: (帧错误,噪声错误,溢出错误) */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
husart->State = HAL_USART_STATE_READY;
/* 进程解锁 */
__HAL_UNLOCK(husart);
return HAL_TIMEOUT;
}
}
}
return HAL_OK;
}
/**
* @brief 结束USART外设上正在进行的Tx传输(在错误检测或传输完成后)。
* @param husart usart 句柄.
* @retval None
*/
static void USART_EndTxTransfer(USART_HandleTypeDef *husart)
{
/* 禁用 TXEIE(发送缓冲空)和 TCIE(发送完成)中断 */
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
/* 在发送过程结束时, 将 husart->State 恢复为 Ready 状态 */
husart->State = HAL_USART_STATE_READY;
}
/**
* @brief 结束USART外设上正在进行的Rx传输(在错误检测或接收完成后)
* @param husart usart 句柄.
* @retval None
*/
static void USART_EndRxTransfer(USART_HandleTypeDef *husart)
{
/* 禁用 RXNE(接收缓冲非空), PE(奇偶校验)和 ERR(错误)(帧错误, 噪声错误, 溢出错误) 中断 */
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
/* 在接收过程结束时, 将 husart->State 恢复为 Ready 状态 */
husart->State = HAL_USART_STATE_READY;
}
/**
* @brief 当由HAL服务在出现错误时启动时,DMA USART通信中止回调(在发生错误后DMA中止过程结束时调用)
* @param hdma DMA 句柄
* @retval None
*/
static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma)
{
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
husart->RxXferCount = 0x00U;
husart->TxXferCount = 0x00U;
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的错误回调 */
husart->ErrorCallback(husart);
#else
/* 调用预定义弱错误回调函数 */
HAL_USART_ErrorCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
/**
* @brief 当由用户发起时,DMA USART Tx通信中止回调(在用户发起中止请求后DMA Tx中止过程结束时调用)
* @note 当执行此回调时,仅当Rx DMA句柄没有仍在进行中止时,才会调用用户中止完成回调。
* @param hdma DMA 句柄
* @retval None
*/
static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
{
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
husart->hdmatx->XferAbortCallback = NULL;
/* 检查中止程序是否正在进行 */
if (husart->hdmarx != NULL)
{
if (husart->hdmarx->XferAbortCallback != NULL)
{
return;
}
}
/* 没有仍在进行中止的过程:所有DMA通道都已中止,调用用户中止完成回调 */
husart->TxXferCount = 0x00U;
husart->RxXferCount = 0x00U;
/* 重置错误 */
husart->ErrorCode = HAL_USART_ERROR_NONE;
/* 将 husart->State 恢复为 Ready 状态 */
husart->State = HAL_USART_STATE_READY;
/* 调用用户中止完成回调*/
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的中止完成回调 */
husart->AbortCpltCallback(husart);
#else
/* 调用预定义弱中止完成回调函数 */
HAL_USART_AbortCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
/**
* @brief 当由用户发起时,DMA USART Rx通信中止回调(在用户发起中止请求后DMA Rx中止过程结束时调用)
* @note 当执行此回调时,仅当Tx DMA句柄没有仍在进行中止时,才会调用用户中止完成回调。
* @param hdma DMA 句柄
* @retval None
*/
static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
{
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
husart->hdmarx->XferAbortCallback = NULL;
/* 检查中止程序是否正在进行 */
if (husart->hdmatx != NULL)
{
if (husart->hdmatx->XferAbortCallback != NULL)
{
return;
}
}
/* 没有仍在进行中止的过程:所有DMA通道都已中止,调用用户中止完成回调 */
husart->TxXferCount = 0x00U;
husart->RxXferCount = 0x00U;
/* 重置错误 */
husart->ErrorCode = HAL_USART_ERROR_NONE;
/* 将 husart->State 恢复为 Ready 状态 */
husart->State = HAL_USART_STATE_READY;
/* 调用用户中止完成回调 */
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的中止完成回调 */
husart->AbortCpltCallback(husart);
#else
/* 调用预定义弱中止完成回调函数 */
HAL_USART_AbortCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
}
/**
* @brief 单工 发送一定数量的数据(非阻塞模式)
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
* @note 未对 USART 错误进行处理,以避免溢出错误。
*/
static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart)
{
const uint16_t *tmp;
if (husart->State == HAL_USART_STATE_BUSY_TX)
{
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
{
tmp = (const uint16_t *) husart->pTxBuffPtr;
husart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
husart->pTxBuffPtr += 2U;
}
else
{
husart->Instance->DR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0x00FF);
}
if (--husart->TxXferCount == 0U)
{
/* 禁用 USART 发送数据寄存器空 中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
/* 启用 UART 发送完成中断 */
SET_BIT(husart->Instance->CR1, USART_CR1_TCIE);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 以非阻塞模式完成发送
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
*/
static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart)
{
/* 禁用 USART 发送完成中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TCIE);
/* 禁用 USART 错误中断: (帧错误,噪声错误,溢出错误) */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
husart->State = HAL_USART_STATE_READY;
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的发送完成回调 */
husart->TxCpltCallback(husart);
#else
/* 调用预定义的弱发送完成回调 */
HAL_USART_TxCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
return HAL_OK;
}
/**
* @brief 单工 接收一定数量的数据(非阻塞模式)
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
*/
static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart)
{
uint8_t *pdata8bits;
uint16_t *pdata16bits;
if (husart->State == HAL_USART_STATE_BUSY_RX)
{
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
{
pdata8bits = NULL;
pdata16bits = (uint16_t *) husart->pRxBuffPtr;
*pdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
husart->pRxBuffPtr += 2U;
}
else
{
pdata8bits = (uint8_t *) husart->pRxBuffPtr;
pdata16bits = NULL;
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
{
*pdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x00FF);
}
else
{
*pdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x007F);
}
husart->pRxBuffPtr += 1U;
}
husart->RxXferCount--;
if (husart->RxXferCount == 0U)
{
/* 禁用 USART RXNE(接收缓冲非空)数据寄存器非空中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
/* 禁用 USART 奇偶校验错误中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
/* 禁用 USART 错误中断: (帧错误,噪声错误,溢出错误) */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
husart->State = HAL_USART_STATE_READY;
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的 Rx 事件回调 */
husart->RxCpltCallback(husart);
#else
/* 调用预定义弱 Rx 事件回调函数k */
HAL_USART_RxCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
return HAL_OK;
}
else
{
/* 发送虚拟字节以生成时钟,以便从机发送下一个数据。
无论帧长度为多少位(7、8或9位),对于所有情况都可以写入相同的虚拟值。 */
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x0FF);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 全双工发送接收一定数量的数据 - 中断
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval HAL status
*/
static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart)
{
const uint16_t *pdatatx16bits;
uint16_t *pdatarx16bits;
if (husart->State == HAL_USART_STATE_BUSY_TX_RX)
{
if (husart->TxXferCount != 0x00U)
{
if (__HAL_USART_GET_FLAG(husart, USART_FLAG_TXE) != RESET)
{
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
{
pdatatx16bits = (const uint16_t *) husart->pTxBuffPtr;
husart->Instance->DR = (uint16_t)(*pdatatx16bits & (uint16_t)0x01FF);
husart->pTxBuffPtr += 2U;
}
else
{
husart->Instance->DR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0x00FF);
}
husart->TxXferCount--;
/* 检查最后一位发送 */
if (husart->TxXferCount == 0U)
{
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
}
}
}
if (husart->RxXferCount != 0x00U)
{
if (__HAL_USART_GET_FLAG(husart, USART_FLAG_RXNE) != RESET)
{
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
{
pdatarx16bits = (uint16_t *) husart->pRxBuffPtr;
*pdatarx16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
husart->pRxBuffPtr += 2U;
}
else
{
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
{
*husart->pRxBuffPtr = (uint8_t)(husart->Instance->DR & (uint8_t)0x00FF);
}
else
{
*husart->pRxBuffPtr = (uint8_t)(husart->Instance->DR & (uint8_t)0x007F);
}
husart->pRxBuffPtr += 1U;
}
husart->RxXferCount--;
}
}
/* 检查最后一位接收*/
if (husart->RxXferCount == 0U)
{
/* 禁用 USART RXNE(接收缓冲非空)中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
/* 禁用 USART 奇偶校验错误中断 */
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
/* 禁用 USART 错误中断: (帧错误,噪声错误,溢出错误) */
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
husart->State = HAL_USART_STATE_READY;
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
/* 调用注册的 Tx Rx 完成回调 */
husart->TxRxCpltCallback(husart);
#else
/* 调用预定义弱 Tx Rx 完回调函数 */
HAL_USART_TxRxCpltCallback(husart);
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
return HAL_OK;
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief 配置 USART 外设
* @param husart 指向包含指定USART模块的配置信息的USART_HandleTypeDef结构的指针
* @retval None
*/
static void USART_SetConfig(USART_HandleTypeDef *husart)
{
uint32_t tmpreg = 0x00U;
uint32_t pclk;
/* 清除参数 */
assert_param(IS_USART_INSTANCE(husart->Instance));
assert_param(IS_USART_POLARITY(husart->Init.CLKPolarity));
assert_param(IS_USART_PHASE(husart->Init.CLKPhase));
assert_param(IS_USART_LASTBIT(husart->Init.CLKLastBit));
assert_param(IS_USART_BAUDRATE(husart->Init.BaudRate));
assert_param(IS_USART_WORD_LENGTH(husart->Init.WordLength));
assert_param(IS_USART_STOPBITS(husart->Init.StopBits));
assert_param(IS_USART_PARITY(husart->Init.Parity));
assert_param(IS_USART_MODE(husart->Init.Mode));
/* LBCL(最后一位时钟脉冲)、CPOL(时钟极性)和CPHA(时钟相位)位必须在发送和接收都被禁用时选择(TE=RE=0),以确保时钟脉冲能够正确运行 */
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
/*---------------------------- USART CR2(控制寄存器2)配置 ---------------------*/
tmpreg = husart->Instance->CR2;
/* 清除 CLKEN(CK引脚使能), CPOL(时钟极性), CPHA(时钟相位)和 LBCL(最后一位时钟脉冲) 位 */
tmpreg &= (uint32_t)~((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_LBCL | USART_CR2_STOP));
/* 配置 USART 时钟, CPOL(时钟极性), CPHA(时钟相位)和 LBCL(最后一位时钟脉冲) -----------------------*/
/* 根据husart->Init.CLKPolarity 的值设置CPOL(时钟极性)位 */
/* 根据husart->Init.CLKPhase 的值设置CPHA(时钟相位)位 */
/* 根据husart->Init.CLKLastBit 的值设置LBCL(最后一位时钟脉冲)位 */
/* 设置停止位:根据husart->Init.StopBits 的值设置STOP[13:12]位 */
tmpreg |= (uint32_t)(USART_CLOCK_ENABLE | husart->Init.CLKPolarity |
husart->Init.CLKPhase | husart->Init.CLKLastBit | husart->Init.StopBits);
/* Write to USART CR2 */
WRITE_REG(husart->Instance->CR2, (uint32_t)tmpreg);
/*-------------------------- USART CR1(控制寄存器1)配置 -----------------------*/
tmpreg = husart->Instance->CR1;
/* 清除 M(数据长度), PCE(奇偶校验控制使能), PS(奇偶校验选择), TE(发送使能)和 RE(接收使能)位 */
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE));
/* 配置USART的数据位长度、奇偶校验和模式:
根据husart->Init.WordLength 的值设置M(数据长度)位
根据husart->Init.Parity 的值设置PCE(奇偶校验控制使能)和PS(奇偶校验选择)位
根据husart->Init.Mode 的值设置TE(发送使能)和RE(接收使能)位
*/
tmpreg |= (uint32_t)husart->Init.WordLength | husart->Init.Parity | husart->Init.Mode;
/* 写入 USART CR1(控制寄存器1) */
WRITE_REG(husart->Instance->CR1, (uint32_t)tmpreg);
/*-------------------------- USART CR3(控制寄存器3)配置 -----------------------*/
/* 清除 CTSE(CTS使能)和 RTSE(RTS使能)位 */
CLEAR_BIT(husart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE));
/*-------------------------- USART BRR(波特率寄存器)配置 -----------------------*/
if((husart->Instance == USART1))
{
pclk = HAL_RCC_GetPCLK2Freq();
husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate);
}
else
{
pclk = HAL_RCC_GetPCLK1Freq();
husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate);
}
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_USART_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/