当前位置: 首页 > news >正文

STM32-UART-中断

UART简介:

UART(Universal Asynchronous Receiver/Transmitter)是一种通用异步收发传输器,作为一种串行、异步通信协议,它允许设备通过两条数据线(TX和RX)实现全双工通信。由于其简单、灵活和低成本的特点,UART被广泛应用于微控制器、计算机外围设备以及各种嵌入式系统中。

协议:

UART帧结构:
协议有关信息参考了如下地址信息:

https://dreamsourcelab.cn/logic-analyzer/uart/

1位低电平​(逻辑'0')。标志着数据帧的开始,通知接收方开始采样数据。

实际要传输的数据,​低位(LSB)先行​。长度可配置。5-9位​(通常为8位

可选,1位,用于简单的错误检测,奇校验、偶校验或无校验

高电平​(逻辑'1')。标志着数据帧的结束,并帮助校正时钟同步。

要使两个UART设备成功通信,它们的以下参数必须严格匹配​:

  • 波特率 (Baud Rate)​: 这是最重要的参数,表示每秒传输的比特数(bps)。常见值有9600, 19200, 115200等。​双方波特率必须一致,且误差通常需控制在10%以内(一些严格要求下需≤3%)。
  • 数据位长度: 通常设置为8位。
  • 校验位: 根据可靠性需求选择奇校验、偶校验或无校验。
  • 停止位长度: 通常设置为1位。

有效数据速率 (Byte/s) = 比特率 (bps) / 每帧总位数

  • 无校验位情况​(1起始位 + 8数据位 + 1停止位 = 10位):
    有效数据速率 = 波特率 / 10
    例如,波特率9600 bps时,有效数据速率 = 9600 / 10 = ​960 字节/秒

  • 有校验位情况​(1起始位 + 8数据位 + 1校验位 + 1停止位 = 11位):
    有效数据速率 = 波特率 / 11
    例如,波特率9600 bps时,有效数据速率 ≈ 9600 / 11 ≈ ​872.73 字节/秒

需要注意通信双方设备支持的波特率必须匹配,如果不匹配会导致如下情况

详细的过程如下:

  1. 空闲位:当没有信息的情况下为高电平,即高电平时为空闲信号:
  2. 起始位:当从高电平到低电平,即告知开始传输数据,结束空闲
  3. 数据位:如果使用了奇偶校验为5~8位,没有则为5~9位,默认为8位,起始位后开始传输数据  
  4. 校验位:提高传输的可靠性
  5. 停止位:1~2位的高电平表示结束      

中断:

stm32f1xx_it.c:USART1_IRQHandler

SART1_IRQHandler 是硬件中断的入口

这里是由硬件触发的中断,在内部调用了stm32f1xx_hal_uart.c的HAL_UART_IRQHandler方法

HAL_UART_IRQHandler

HAL_UART_IRQHandler 就像一个大管家,当中断发生时,它会检查是哪个标志位触发了中断,然后进行相应的处理,比如读取数据、填充下一个要发送的数据或清除标志位等,并在适当的时候调用对应的回调函数(Callback),用户的应用程序逻辑通常就在这些回调函数中实现

回调函数:

stm32f1xx_hal_uart.c内部存在如下回调函数:

__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)

__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
__weak void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)
__weak void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart)
__weak void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)

对应解释如下:

函数名称触发时机主要用途
HAL_UART_MspInit(UART_HandleTypeDef *huart)在 HAL_UART_Init() 中被调用完成特定MCU的底层初始化(如时钟、GPIO、NVIC)
HAL_UART_MspDeInit(UART_HandleTypeDef *huart)在 HAL_UART_DeInit() 中被调用反初始化MCU相关的底层设置(如关闭时钟)
HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)发送完成​(包括使用中断和DMA模式)处理数据发送完成后的工作,如通知主程序、启动下一次发送
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)接收完成​(达到预设长度,中断或DMA模式)处理接收到的数据,如解析协议、存储数据
HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)发生错误​(如溢出、帧错误、噪声、奇偶校验错误等)错误处理与恢复,如重新初始化串口、清除错误标志
HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)接收到特定字节数检测到总线空闲​(IDLE)处理不定长数据接收
HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)DMA发送完成一半​(如100字节才发完50字节)可用于双缓冲区操作,在发送一半数据时提前准备后半部分数据
HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)DMA接收完成一半可用于双缓冲区操作,在接收一半数据时提前处理前半部分数据
HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)中止传输操作完成​(如调用 HAL_UART_Abort处理传输被中止后的清理工作
HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart)中止发送操作完成处理发送中止后的特定工作
HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)中止接收操作完成处理接收中止后的特定工作

上述三个对应关系如下:

使用:

阻塞模式:

阻塞模式下,CPU会一直等待数据发送或接收完成,期间无法执行其他任务。

主要使用HAL_UART_Transmit和HAL_UART_Receive两个函数处理

int main(void)
{/* USER CODE END 2 */uint8_t txData[] = "Hello, UART (Blocking)!\r\n";uint8_t rxData[10];/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */// 发送数据,一直等待直到发送完成HAL_UART_Transmit(&huart1, txData, sizeof(txData)-1, HAL_MAX_DELAY);// 接收10字节数据,一直等待直到收齐HAL_UART_Receive(&huart1, rxData, 10, HAL_MAX_DELAY);/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

中断模式:

中断模式允许CPU在等待数据传输时处理其他任务,数据传输完成后由中断通知CPU。

#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"/* USER CODE BEGIN PV */
// 通常在初始化后启动一次接收中断,准备接收数据
// 用于中断接收的变量
uint8_t rx_byte; /* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP */// 接收中断回调函数(当数据接收到时自动调用)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {if (huart == &huart1) { // 判断是哪个串口触发的回调// 处理接收到的数据,例如回显或存入缓冲区// 注意:回调函数中应避免耗时操作 回显收到的字符HAL_UART_Transmit(&huart1, &rx_byte, 1, 100); // 重新启动接收中断,以便持续接收[1,5](@ref)HAL_UART_Receive_IT(&huart1, &rx_byte, 1);}
}// 发送完成回调函数(可选)
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {if (huart == &huart1) {// 发送完成,可进行后续操作}
}
/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{HAL_Init();/* Configure the system clock */SystemClock_Config();/* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_I2C2_Init();MX_SPI2_Init();MX_USART1_UART_Init();// 发送数据(非阻塞,完成后会进入中断回调函数)uint8_t txData[] = "Hello, UART (Interrupt)!\r\n";HAL_UART_Transmit_IT(&huart1, txData, sizeof(txData)-1);// 启动接收中断,期望接收1字节数据[1,5]HAL_UART_Receive_IT(&huart1, &rx_byte, 1);/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

DMA模式(CPU效率最高,适合大数据量)

DMA(直接存储器访问)模式允许外设和内存之间直接传输数据,几乎不占用CPU资源。

对应的设置如下:

#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"/* USER CODE BEGIN PV */
// 通常在初始化后启动一次接收中断,准备接收数据
uint8_t receiveData[50];// uint8_t received[2];
/* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *///检测到总线空闲(IDLE) 或接收满指定长度时,HAL库会自动调用此函数。huart为触发中断的串口句柄,Size为本次实际接收到的数据长度。
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {if (huart == &huart1) {// DMA发送数据。将存储在当前receiveData缓冲区中、长度为Size的数据,通过DMA方式从huart1发送出去。HAL_UART_Transmit_DMA(&huart1, receiveData, Size);// 重启DMA空闲中断接收。这是实现连续不定长接收的关键。它重新配置DMA,等待下一次空闲中断或缓冲区满的事件HAL_UARTEx_ReceiveToIdle_DMA(&huart1, receiveData, sizeof(receiveData));// 禁用DMA半传输中断。DMA_IT_HT(Half Transfer)中断在DMA传输完成一半时触发。由于此代码逻辑只在接收完成时处理,不需要在半传输时处理,因此禁用此中断可以避免不必要的干扰__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);}
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_I2C2_Init();MX_SPI2_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */// HAL_Delay(500);/* USER CODE END 2 */HAL_UARTEx_ReceiveToIdle_DMA(&huart1, receiveData, sizeof(receiveData));__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

其中__HAL_DMA_DISABLE_IT 通过操作 DMA 通道的配置控制寄存器 (CCR) 中的特定中断使能位来实现功能。

它的两个参数分别是:

​**__HANDLE__**​:指向 DMA_HandleTypeDef 结构体的指针,该结构体包含了所有配置信息。
​**__INTERRUPT__​:指定要禁用的中断类型**,可以是以下值的组合:
DMA_IT_TC:传输完成中断 (Transfer Complete)
DMA_IT_HT:半传输中断 (Half Transfer)
DMA_IT_TE:传输错误中断 (Transfer Error)

    http://www.xdnf.cn/news/1453717.html

    相关文章:

  • Qt QJsonObject
  • 数据库集成:使用 SQLite 与 Electron
  • uni 拍照上传拍视频上传以及相册
  • jenkins调用ansible部署lnmp平台-Discuz论坛
  • Java 流程控制:从入门到面试的全方位指南
  • C语言(长期更新)第14讲:指针详解(四)
  • 【图像处理基石】如何在频域对图像进行处理和增强?
  • VSCode中的扩展Extension说明
  • 《计算机网络安全》实验报告一 现代网络安全挑战 拒绝服务与分布式拒绝服务攻击的演变与防御策略(2)
  • 深度学习:ResNet 残差神经网络详解
  • C++ 面试高频考点 力扣 153. 寻找旋转排序数组中的最小值 二分查找 题解 每日一题
  • 2025年GEO优化供应商盘点:五大实力派助您抢占AI搜索先机
  • 大数据框架对比与选择指南
  • Vulkan计算着色器中Dispatch、workGroups、invocation之间的关系
  • Docker(③MobaXterm连接WSL Ubuntu)
  • Flowable——流程定义与部署(RepositoryService)
  • Gamma AI:AI演示文稿制作工具,高效解决PPT框架搭建难与排版耗时问题
  • C# HTTP请求最佳实践
  • 关于亚马逊账号关联的新思考——账号注册注意事项
  • 基于单片机矿井安全检测/煤矿环境安全监测设计
  • Vue 3 学习路线指南
  • NVIDIA Jetson 开发板使用
  • IBM穿孔卡片:现代计算技术的奠基之作
  • 第11章 分布式构建
  • 20.36 QLoRA微调实测:59%显存暴降+3倍提速,95%性能保留惊呆业界!
  • 从“下山”到AI引擎:全面理解梯度下降(上)
  • Mac开发第一步 - 安装Xcode
  • 趣味学RUST基础篇(测试)
  • Qt Creator 打包应用程序时经常会遇到各种问题
  • 【leetcode】64. 最小路径和