STM32H7 串口 空闲中断 硬件FIFO 任意长接收 Hal库 IDLE

STM32H7 串口 空闲中断 硬件FIFO 任意长接收 Hal库 IDLE

由于工作原因好久不接触ST的芯片了,所以断更ST的东西了,不过偶尔玩玩也挺好的。

接着上篇继续说串口的事儿,这次是FIFO,STM32H7的串口都是带硬件FIFO,大小是发送和接收各16个字节,其他新出的系列,例如H5的串口带8字节的硬件FIFO,这种情况下DMA咱就可以省略了,直接用FIFO就行。

使用之前呢,先要说明本次使用的环境以及库版本,编译环境是MDK5.27 ,hal库版本是1.11版本。这个很重要。

前两篇文章里边用的hal库版本比较老,缺失了很多。例如新版本已经增加了对idle的支持。并且修复了一些错误,例如硬件FIFO深度宏定义。

好,进入正题。

插个题外话,未经允许不得转载哦。

我们的目标呢,依旧是接收任意长数据。

我们拆解开来看,里边是有两个点需要注意,一个是IDLE,一个是硬件FIFO。

首先是IDLE,这个中断在hal库中定义为事件。我们在这里称为空闲中断。目前看这个中断是ST的芯片独有的,其他的芯片不一定有,可能有其他方式实现。空闲中断嘛,顾名思义就是串口在闲的时候发出中断,有闲就有忙,那这里的忙是什么?按照hal库里的实现,可以理解为,只要串口在收发数据的过程中就是忙,反之所谓的空闲就是没有在收发数据中。这个IDLE空闲中断特指的是串口在没有接收数据,注意啊,不关发送的事儿,因为串口本身就是异步全双工的,可以理解为发送是一个硬件,接收是一个硬件,两个是互相不干扰的。

再说说IDLE空闲中断发生的时机。我记得之前在103的手册中看到过,说是串口接收到最后一个字节后,在超过一个字节的时间里没有收到数据,会发生这个中断。当然H743里边也有单独实现超时机制(指定超时时间,硬件实现哦,题外话:soc中常用这个,soc的FIFO一般是64字节),不在本次实现验证说明中。这段主要就是想说IDLE发生在接收到最后一字节之后的一个字节时间之后且一次传输只发生一次。

然后是串口的硬件FIFO,F7 我没有看手册,就当作没有实现哈,就当作H7是ST公司首次在STM32系列MCU中加入硬件FIFO的功能。在不考虑DMA的情况下,我们通过串口接收接收数据,每收到一个数据就要发生一次中断。在cortexM3手册中是明确说明的,从触发中断到响应中断的第一条指令开始,是需要12个cpu周期的,cortexM7,我就懒得翻了,不知道有没有这个说明,STM32F103系列在72MHz主频下,中断频率最高是200Khz。说这些东西呢,是想让各位读者知道,中断对单片很重要,但不能滥用,要好好的规划才行,尤其是你的系统很复杂的时候, 这里用FIFO和IDLE的目的就是减少中断,还不影响实时性。

相关的知识点就先说这么多。

接下来就说怎么实现了,这次就不分析hal库了,大概前两篇的差不多。剩下的我就直接贴代码了。

这是C文件里的涉及到的宏定义以及全局变量。

#define BuffSize	128ul

UART_HandleTypeDef hUart1 = {0};

uint8_t RxData[2][BuffSize];

这段是uart1的初始化。

void Uart1_Init(void)
{
	hUart1.Instance = USART1;
	hUart1.Init.BaudRate = 115200;
	hUart1.Init.ClockPrescaler = UART_PRESCALER_DIV2;
	hUart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	hUart1.Init.Mode = UART_MODE_TX_RX;
	hUart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
	hUart1.Init.OverSampling = UART_OVERSAMPLING_8;
	hUart1.Init.Parity = UART_PARITY_NONE;
	hUart1.Init.StopBits = UART_STOPBITS_1;
	hUart1.Init.WordLength = UART_WORDLENGTH_8B;
	
	HAL_UART_Init(&hUart1);
	
	HAL_UARTEx_EnableFifoMode(&hUart1);
	HAL_UARTEx_SetTxFifoThreshold(&hUart1,UART_TXFIFO_THRESHOLD_8_8);
	HAL_UARTEx_SetRxFifoThreshold(&hUart1,UART_RXFIFO_THRESHOLD_8_8);
	
	__HAL_UART_ENABLE_IT(&hUart1,UART_IT_IDLE);
	HAL_NVIC_EnableIRQ(USART1_IRQn);
	HAL_NVIC_SetPriority(USART1_IRQn,14,0);
	HAL_UARTEx_ReceiveToIdle_IT(&hUart1,RxData[0],BuffSize);
}

这段是uart1引脚配置。

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
	if(huart == &hUart1)//串口1
	{
		GPIO_InitTypeDef GPIO_InitStruct;
		
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
		GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
		GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_9;
		
		__HAL_RCC_GPIOA_CLK_ENABLE();
		__HAL_RCC_USART1_CLK_ENABLE();
		
		HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
	}
}

这是中断相关处理。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UARTEx_RxEventCallback(huart,BuffSize);
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart == &hUart1)
	{
		if(huart->pRxBuffPtr <= RxData[1])
		{
			HAL_UARTEx_ReceiveToIdle_IT(huart,RxData[1],BuffSize);
			Uart1_RxData_NotifityISR(RxData[0],Size);
		}
		else
		{
			HAL_UARTEx_ReceiveToIdle_IT(huart,RxData[0],BuffSize);
			Uart1_RxData_NotifityISR(RxData[1],Size);
		}
	}
}

void USART1_IRQHandler(void)
{
	HAL_UART_IRQHandler(&hUart1);
}

这是对外接口部分,也就收发数据接口。

__weak void Uart1_RxData_NotifityISR(uint8_t *pRxData,uint32_t Count)
{
}

uint32_t Uart1_TxData(uint8_t *pTxData,uint32_t Count)
{
	if(HAL_UART_GetState(&hUart1) & 0x01)return 1;
	HAL_UART_Transmit_IT(&hUart1,pTxData,Count);
	return 0;
}

c文件呢一共就这么多。

下边这段是h文件,是不是非常简洁。

#ifndef __Uart_H_
#define __Uart_H_

#include "stdint.h"

void Uart1_Init(void);
void Uart1_RxData_NotifityISR(uint8_t *pRxData,uint32_t Count);
uint32_t Uart1_TxData(uint8_t *pTxData,uint32_t Count);

#endif

下边这段是测试代码,功能是回显。

static uint8_t *pvRxData;
static volatile uint32_t RxCount = 0;

void Uart1Step(void)//Rate:10ms
{
	if(RxCount > 0)
	{
		if(Uart1_TxData(pvRxData,RxCount) == 0)RxCount = 0;
	}
}

void Uart1_RxData_NotifityISR(uint8_t *pRxData,uint32_t Count)
{
	pvRxData = pRxData;
	RxCount = Count;
}

测试结果,如图所示
在这里插入图片描述

好了,今天就这么多,有问题可以联系我,共同探讨,单片机疑难杂症就可以找我探讨哦。

<think>首先,用户的问题是关于使用STM32 HAL实现FIFO循环接收数据,具体要求是带有帧头的30字节度数据。用户提到了“FIFO循环接收”,参考引用中提到了STM32H7硬件FIFO,所以我需要基于STM32 HAL来实现这个功能。 关键点: - **硬件FIFO**:STM32H7系列有16字节的硬件FIFO(如引用[1]所述),其他系列可能不同。用户没有指定具体型号,但引用提到了H7,所以我假设使用STM32H7。 - **帧头检测**:数据以帧头开始,用户需要检测帧头并接收完整的30字节数据。 - **循环接收**:意味着持续接收数据,可能使用中断或DMA来处理数据流。 - **HAL**:使用STM32 HAL实现。 从引用中提取相关信息: - 引用[1]:提到STM32H7串口硬件FIFO(16字节),可以用于接收数据,减少DMA需求。 - 引用[2]:强调学习串口硬件框图开始,介绍了USART的高级特性,如超时接收检测。部分中断标志通过操作寄存器清除。 - 引用[3]:使用STM32CubeMX设置串口,包括异步模式、波特率等,并提到使能接收中断。 用户需求:实现FIFO循环接收带帧头的30字节数据。这涉及到: 1. 配置串口使用硬件FIFO。 2. 设置中断来处理数据接收,特别是帧头检测。 3. 实现一个循环缓冲区或FIFO队列来存储接收到的数据。 4. 检测帧头并提取完整帧。 步骤实现: - **初始化**:使用STM32CubeMX配置USART。 - 设置模式为异步。 - 启用硬件FIFO(如果支持)。 - 设置波特率、数据位等。 - 使能接收中断(NVIC)。 - **中断处理**:在接收中断中处理数据。 - 使用HAL_UART_RxCpltCallback或自定义中断服务例程。 - 由于数据有帧头,需要检查每个接收字节是否匹配帧头。 - **FIFO管理**:硬件FIFO有限(16字节),所以需要软件FIFO来缓冲数据。创建一个循环缓冲区存储接收数据。 - **帧检测**:当检测到帧头时,开始收集后续字节直到30字节完整帧。 具体实现思路: 1. **配置串口**: - 使用CubeMX设置USART,启用接收中断。 - 配置硬件FIFO(如果可用),通过设置控制寄存器。 2. **定义数据结构**: - 创建一个软件FIFO缓冲区,例如一个数组或环形缓冲区。 - 定义变量跟踪缓冲区状态(头指针、尾指针、计数)。 3. **中断服务**: - 在USART中断中,读取接收数据寄存器(RDR)。 - 将数据存入软件FIFO。 - 检查接收到的字节是否为帧头。如果是,重置帧接收状态。 - 如果帧头检测到,开始计数接收字节直到30字节。 4. **帧处理**: - 当完整帧接收后(30字节包括帧头),处理数据(例如,解析、存储或发送)。 - 使用超时机制处理不完整帧(如引用[2]提到的超时接收检测)。 在HAL中,可以使用HAL_UART_Receive_IT函数启动中断接收,但它是针对固定度。对于可变度或帧检测,需要自定义接收。 推荐方法: - 使用HAL_UART_Receive_IT启动接收一个字节。 - 在接收完成回调中,处理数据并重新启动接收。 - 但为了效率,硬件FIFO可以一次接收多个字节。 由于硬件FIFO存在,可以启用FIFO中断(如RXNE中断或空闲中断)来处理数据块。 引用[1]提到空闲中断IDLE),可以用于检测帧结束。但用户指定了帧头和固定度30字节,所以空闲中断可能不直接适用,但可以用于检测数据流空闲。 实现步骤: 1. **初始化**: - 配置USART:异步模式,115200波特率,8数据位,无校验,1停止位。 - 启用硬件FIFO:通过设置CR3寄存器的ONEBIT、DMAR等位(参考引用[2])。 - 使能接收中断和空闲中断IDLE)。 2. **定义缓冲区**: - 创建一个大 enough 的软件环形缓冲区,例如512字节,用于存储接收数据。 - 定义变量:`rx_buffer`, `head`, `tail`, `count`。 - 定义帧接收状态:`frame_started`, `bytes_received`, `frame_buffer`(30字节数组)。 3. **中断处理**: - 在USART中断服务例程(ISR)中,检查中断源。 - 如果是RXNE中断(接收寄存器非空),读取数据直到FIFO为空。 - 如果是IDLE中断(空闲检测),表示数据流停止,可以处理接收数据。 - 在RXNE处理中,将每个字节存入软件缓冲区。 - 在软件中,检查帧头:如果检测到帧头字节(例如0xAA),设置`frame_started = true`, `bytes_received = 0`。 - 如果`frame_started`,将字节存入`frame_buffer`,增加`bytes_received`。 - 当`bytes_received == 30`,帧完整,进行处理并重置状态。 4. **错误处理**: - 处理溢出、错误中断。 - 使用超时:如果接收部分帧后超时,重置状态。 在HAL中,可以重写HAL_UART_RxCpltCallback或使用自定义ISR。 代码示例: - 使用CubeMX生成代码。 - 在main.c中添加自定义代码。 伪代码: ```c // 定义全局变量 #define RX_BUFFER_SIZE 512 uint8_t rx_buffer[RX_BUFFER_SIZE]; volatile uint16_t rx_head = 0; volatile uint16_t rx_tail = 0; volatile uint8_t frame_started = 0; volatile uint8_t frame_index = 0; uint8_t frame_buffer[30]; // 帧头定义,例如0x55 #define FRAME_HEADER 0x55 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // 当接收完成一个字节时调用,但我们需要处理多个字节 } // 更好的方法是自定义ISR void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&huart1); // 调用HAL处理 // 然后添加自定义处理 if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE)) { uint8_t data = (uint8_t)(huart1.Instance->RDR & 0xFF); // 存储到软件FIFO rx_buffer[rx_head] = data; rx_head = (rx_head + 1) % RX_BUFFER_SIZE; // 帧检测 if (!frame_started) { if (data == FRAME_HEADER) { frame_started = 1; frame_index = 0; frame_buffer[frame_index++] = data; } } else { frame_buffer[frame_index++] = data; if (frame_index >= 30) { // 完整帧接收 process_frame(frame_buffer); // 处理帧 frame_started = 0; frame_index = 0; } } } if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&huart1); // 处理空闲状态,可能重置帧检测 } } ``` 在初始化中,启动接收中断: ```c HAL_UART_Receive_IT(&huart1, &temp, 1); // 启动接收一个字节 ``` 但为了效率,使用硬件FIFO,可以读取多个字节。 参考引用[2],USART有FIFO中断,可以配置为当FIFO达到一定水平时触发。 在STM32H7,可以设置接收FIFO阈值中断(例如,当FIFO中有4个字节时触发中断)。 在CubeMX中,配置USART中断和FIFO。 最终,回答应该结构清晰,逐步解释。 相关问题生成: 根据用户问题,生成相关问题如: 1. 如何配置STM32硬件FIFO? 2. 帧头检测的优化方法? 3. 如何处理接收错误或超时? 4. 使用DMA与硬件FIFO的比较? 回答结构: 1. 介绍需求:实现FIFO循环接收带帧头的30字节数据。 2. 硬件配置:使用STM32H7硬件FIFO。 3. 软件实现:初始化、中断处理、帧检测。 4. 代码示例。 5. 注意事项。</think>### 使用STM32 HAL实现FIFO循环接收带帧头的30字节数据 以下是基于STM32 HAL实现串口FIFO循环接收的完整方案。STM32H7系列(如引用[1]所述)内置16字节硬件FIFO,可显著提升接收效率。本方案结合硬件FIFO和软件环形缓冲区实现循环接收,支持帧头检测和固定30字节数据帧处理。方案分为硬件配置、软件实现和代码示例三部分。 --- ### 1. 硬件配置(使用STM32CubeMX) 引用[2]强调从硬件框图开始配置,以下是关键设置: - **串口模式**:异步通信(Asynchronous),波特率115200(可自定义),8位数据位,无校验,1停止位(引用[3])。 - **硬件FIFO**:使能USART的硬件FIFOSTM32H7默认支持16字节FIFO)。 - **中断配置**: - 使能接收中断(RXNEIE)和空闲中断IDLEIE),用于数据块检测。 - 在NVIC中启用USART全局中断。 - **GPIO**:自动配置USART_RX/USART_TX引脚(引用[3])。 - **CubeMX操作**: 1. 在"Pinout & Configuration"中启用USART。 2. 在"Parameter Settings"中设置通信参数。 3. 在"NVIC Settings"中勾选"USARTx global interrupt"。 > **注意**:STM32H7硬件FIFO通过CR3寄存器控制,需设置`FIFOEN=1`(CubeMX自动完成)[^1][^2]。 --- ### 2. 软件实现步骤 #### (1) 定义全局数据结构 创建软件环形缓冲区(FIFO)和帧处理变量: ```c #define RX_BUFFER_SIZE 128 // 软件缓冲区大小(建议大于30字节) #define FRAME_HEADER 0x55 // 帧头字节(例如0x55,可自定义) #define FRAME_SIZE 30 // 固定帧度 // 软件环形缓冲区 uint8_t rx_buffer[RX_BUFFER_SIZE]; volatile uint16_t rx_head = 0; // 缓冲区写入位置 volatile uint16_t rx_tail = 0; // 缓冲区读取位置 // 帧处理状态 volatile uint8_t frame_started = 0; // 帧头检测标志 volatile uint8_t frame_index = 0; // 当前帧字节计数 uint8_t frame_data[FRAME_SIZE]; // 帧数据存储 ``` #### (2) 初始化串口和中断 在`main.c`中初始化并启动接收: ```c // 初始化USART(CubeMX生成的代码) MX_USART1_UART_Init(); // 启动空闲中断接收中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 使能空闲中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // 使能接收中断 // 首次启动接收HAL会处理后续中断) HAL_UART_Receive_IT(&huart1, (uint8_t*)&dummy, 1); // 触发中断链 ``` #### (3) 中断服务函数 在`stm32h7xx_it.c`中自定义中断处理: ```c void USART1_IRQHandler(void) { // 处理空闲中断(检测数据流结束) if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&huart1); // 清除空闲标志 process_received_data(); // 处理缓冲区数据(见步骤4) } // 处理接收中断(硬件FIFO非空时触发) if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE)) { uint8_t data = (uint8_t)(huart1.Instance->RDR & 0xFF); // 读取数据 // 存入软件环形缓冲区 rx_buffer[rx_head] = data; rx_head = (rx_head + 1) % RX_BUFFER_SIZE; } HAL_UART_IRQHandler(&huart1); // 调用HAL默认处理 } ``` #### (4) 帧头检测与数据处理 在`main.c`中添加数据处理函数: ```c void process_received_data(void) { while (rx_tail != rx_head) { // 环形缓冲区非空 uint8_t data = rx_buffer[rx_tail]; rx_tail = (rx_tail + 1) % RX_BUFFER_SIZE; // 帧头检测 if (!frame_started) { if (data == FRAME_HEADER) { // 检测到帧头 frame_started = 1; frame_index = 0; frame_data[frame_index++] = data; // 存储帧头 } } else { // 存储帧数据 frame_data[frame_index++] = data; // 完整帧接收 if (frame_index >= FRAME_SIZE) { // 此处处理完整帧(例如解析数据或发送) // 示例:通过串口回传帧数据 HAL_UART_Transmit(&huart1, frame_data, FRAME_SIZE, 100); // 重置状态 frame_started = 0; frame_index = 0; } } } } ``` #### (5) 错误处理(可选) 在中断中添加错误检测: ```c // 在USART1_IRQHandler中添加 if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE)) { __HAL_UART_CLEAR_OREFLAG(&huart1); // 清除溢出错误 // 重置接收状态 frame_started = 0; frame_index = 0; } ``` --- ### 3. 关键优化与注意事项 - **硬件FIFO优势**:STM32H7的16字节硬件FIFO减少中断频率(引用[1]),当FIFO满或空闲时触发中断,提升效率[^2]。 - **帧头检测逻辑**:在软件缓冲区中检测帧头,避免硬件依赖。 - **超时处理**:结合空闲中断IDLE)自动处理帧边界,无需外部定时器。 - **资源占用**:软件环形缓冲区大小(`RX_BUFFER_SIZE`)可根据数据流量调整。 - **中断优先级**:确保串口中断优先级高于非实时任务(通过CubeMX设置)。 - **跨系列兼容**:若使用STM32H5(8字节FIFO)或F4系列(无硬件FIFO),需调整缓冲区大小或启用DMA(引用[1][^3])。 > **警告**:STM32H7的中断标志需通过寄存器操作清除(引用[2]),直接操作`RDR`寄存器可避免标志残留[^2]。 --- ### 完整代码示例 ```c /* main.c */ #include "main.h" UART_HandleTypeDef huart1; #define RX_BUFFER_SIZE 128 #define FRAME_HEADER 0x55 #define FRAME_SIZE 30 uint8_t rx_buffer[RX_BUFFER_SIZE]; volatile uint16_t rx_head = 0; volatile uint16_t rx_tail = 0; volatile uint8_t frame_started = 0; volatile uint8_t frame_index = 0; uint8_t frame_data[FRAME_SIZE]; void process_received_data(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); // 启动中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); HAL_UART_Receive_IT(&huart1, (uint8_t*)&dummy, 1); while (1) { // 主循环可添加其他任务 } } void process_received_data(void) { while (rx_tail != rx_head) { uint8_t data = rx_buffer[rx_tail]; rx_tail = (rx_tail + 1) % RX_BUFFER_SIZE; if (!frame_started) { if (data == FRAME_HEADER) { frame_started = 1; frame_index = 0; frame_data[frame_index++] = data; } } else { frame_data[frame_index++] = data; if (frame_index >= FRAME_SIZE) { // 示例:处理完整帧 HAL_UART_Transmit(&huart1, frame_data, FRAME_SIZE, 100); frame_started = 0; frame_index = 0; } } } } /* stm32h7xx_it.c */ void USART1_IRQHandler(void) { if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&huart1); process_received_data(); } if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE)) { uint8_t data = (uint8_t)(huart1.Instance->RDR & 0xFF); rx_buffer[rx_head] = data; rx_head = (rx_head + 1) % RX_BUFFER_SIZE; } if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE)) { __HAL_UART_CLEAR_OREFLAG(&huart1); frame_started = 0; frame_index = 0; } HAL_UART_IRQHandler(&huart1); } ``` --- ### 相关问题 1. **如何优化硬件FIFO的阈值设置以提升性能?** (例如:配置FIFO接收阈值减少中断频率) 2. **帧头检测失败时如何处理数据丢失或错误帧?** (例如:添加CRC校验或超时重置机制) 3. **在无硬件FIFOSTM32系列(如F1)中如何实现相同功能?** (需结合DMA和软件缓冲区) 4. **如何扩展此方案处理可变度数据帧?** (例如:添加帧尾检测或度字段解析) 5. **空闲中断与DMA传输相比有何优劣?** (引用[1][^3]提到FIFO可替代DMA,但需评估资源占用) [^1]: STM32H7 串口 空闲中断 硬件FIFO 任意接收 Hal IDLE。接着上篇继续说串口的事儿,这次是FIFOSTM32H7串口都是带硬件FIFO,大小是发送和接收各16个字节,其他新出的系列,例如H5的串口带8字节的硬件FIFO,这种情况下DMA咱就可以省略了,直接用FIFO就行。 [^2]: 【STM32H7教程】第29章 STM32H7的USART串口基础知识和HALAPI。 29.1 初学者重要提示 学习串口外设推荐从硬件框图开始了解基本的功能特性,然后逐步深入了解各种特性,这种方式方便记忆和以后查阅。而串口的通信学习,推荐看时序图。 STM32H7串口STM32F4和F1的串口支持了更多高级特性。比如超时接收检测、自适应波特率、TX和RX引脚互换等功能。 部分中断标志是可以通过操作发送数据寄存器TDR或者接收数据寄存器RDR实现清除,这点要特别注意。 [^3]: HAL STM32CubeMX 实现串口 DMA 通信。设置串口 点击 USATR1; 设置 MODE 为 Asynchronous(异步通信); 基础参数:波特率为115200 Bits/s、传输数据度为8 Bit、奇偶检验无、停止位1 接收和发送; GPIO 引脚自动设置 USART1_RX / USART_TX,不用处理; NVIC Settings 一栏使能接收中断。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值