野火STM32_HAL库版课程笔记-串口接收之空闲中断接收不定长数据
在之前的章节, 我们接收的都是定长的数据, 即设定好的四个或五个字节.
一旦接收到一定数量的字节之后, 就会触发中断.
而当我们不知道接收的数据有多长的时候, 我们希望在接收完这些数据之后再触发中断.
都要通过不定长数据接收的方法.
串口中断接收不定长数据
在之前的 STM32 HAL 库中, 是没有这种封装的, 需要手动配置空闲中断, 还要去判断并且清除寄存器标志位来管理状态, 并且触发中断.
而现在利用 HAL 库, 就能够自动处理以上的过程.

主要内容:
HAL_UARTEx_ReceiveToldle_IT() 开启不定长数据的中断接收
HAL_UARTEx_RxEventCallback() 不定长数据中断接收的回调函数
什么是空闲中断?
通过硬件自动检测一帧数据的接收结束, 当串口线路(RX引脚)在接收完一个字节后,持续保持高电平(空闲状态)的时间超过一个完整数据帧的传输时间时,硬件就会自动判定“一帧数据已经收完了”,并触发一个中断请求
HAL_UARTEx_ReceiveToldle_IT 详解
该函数在老版本 HAL 库是没有的, 就要我们自己去实现
/**
* @brief Receive an amount of data in interrupt mode till either the expected number of data is received or an IDLE event occurs.
* @note Reception is initiated by this function call. Further progress of reception is achieved thanks
* to UART interrupts raised by RXNE and IDLE events. Callback is called at end of reception indicating
* number of received data elements.
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
* the received data is handled as a set of uint16_t. In this case, Size must indicate the number
* of uint16_t available through pData.
* @param huart UART handle.
* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
* @param Size Amount of data elements (uint8_t or uint16_t) to be received.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
以中断的方式接收不定长数据.
其参数只有三个: hart 结构体, 数据接收区, 接收的长度
但是, 既然说是接收不定长数据, 那么这里为什么还要指定接收的长度呢?
因为它要保证有一个最大长度可以提前结束,
比如长度为 10, 当发送 5 个数据的时候, 就相当于不定长数据.
他就接受 5 个数据, 因为 5 个数据之后会有一个空闲中断,
而发送 20 个数据的话, 它就会在第 10 个数据, 也就是我们设定好的最大数据长度进行中断.
HAL_UARTEx_RxEventCallback 详解
/**
* @brief Reception Event Callback (Rx event notification called after use of advanced reception service).
* @param huart UART handle
* @param Size Number of data available in application reception buffer (indicates a position in
* reception buffer until which, data are available)
* @retval None
*/
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
这个函数是回调函数, 主要关注第二个参数.
其实第二个参数就是代表本次接收到的数据的长度. (<= 指定的接收的长度)
项目配置

同样需要配置 USART1 中断使能. 其他无异
代码部分
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h> // 使用 printf 函数
#include <string.h> // 使用 strncmp
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LENGTH 64 // 接收缓冲区大小
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t RxBuff[LENGTH] = { 0 };
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxBuff, LENGTH); // 使能接收中断
printf("当前已开启接收中断, 等待数据发送! \r\n");
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if (huart -> Instance == USART1)
{
HAL_UART_Transmit(&huart1, RxBuff, LENGTH, HAL_MAX_DELAY);
memset(RxBuff, 0, 20);
HAL_UARTEx_ReceiveToIdle_IT(&huart1, RxBuff, LENGTH);
}
}
/**
* @brief 重定向 printf 的输出到串口
* @param ch: 要发送的字符
* @param f: 文件指针 (标准库要求的参数, 一般不使用)
* @retval 返回发送的字符
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END 4 */
实验现象

当发送数据长度超出设定的 (最大) 接收长度时, 会在接收到指定长度的数据时触发中断回显数据
当发送数据小于设定的 (最大) 接收长度时, 空闲状态会直接触发中断回显数据.
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)