STM32 UART+DMA接收数据错误

本文讲述了作者在配置USART1与DMA通信时,由于对DMA源地址设置的误解,导致数据接收错误。通过深入理解结构体指针和内存地址,分享了正确设置DMA源地址的方法,以及USART1结构体的细节。

按照网上的教程配置了串口和DMA,结果缓存数组里接收的所有字节始终是同一个字节,排查了好久,发现原来是对DMA源地址的设置有问题。我最开始的写法如下:

	// 设置DMA源地址:串口数据寄存器地址*/
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)USART1->DR; 

最后正确的写法如下:

	// 设置DMA源地址:串口数据寄存器地址*/
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR); 

UART+DMA接收数据发生错误就是这么一个小小的错误导致的...没有对USART1->DR变量先进行取地址操作。所以先对USART1->DR变量取地址后再强制类型转换为uint32_t类型就接收数据正常了。

详细解释:

USART1的定义是:

#define USART1              ((USART_TypeDef *) USART1_BASE)

USART1_BASE被强制转换为USART_TypeDef*类型。
USART_TypeDef是一个结构体定义如下:

typedef struct
{
  __IO uint16_t SR;
  uint16_t  RESERVED0;
  __IO uint16_t DR;
  uint16_t  RESERVED1;
  __IO uint16_t BRR;
  uint16_t  RESERVED2;
  __IO uint16_t CR1;
  uint16_t  RESERVED3;
  __IO uint16_t CR2;
  uint16_t  RESERVED4;
  __IO uint16_t CR3;
  uint16_t  RESERVED5;
  __IO uint16_t GTPR;
  uint16_t  RESERVED6;
} USART_TypeDef;

(uint32_t)(&USART1->DR)这句代码含义就是:
取了结构体指针USART1中的DR变量后,得到它的地址然后强转为uint32_t类型。

记录一下这个踩到的坑。

### UARTDMASTM32 上的结合应用 在 STM32 微控制器上使用 UART 结合 DMA 进行大量数据传输是一种高效的方式,能够显著降低 CPU 的负担,提高系统性能。以下是实现方法及问题排查的详细说明。 #### 1. UARTDMA 的配置 在 STM32 中,UART 通信可以通过 DMA 来实现高效的数据传输。DMA 的主要优势在于它可以在不占用 CPU 的情况下完成数据的传输任务。为了实现 UARTDMA 的结合,需要进行以下配置: - **初始化 UART**:设置 UART 的波特率、数据位、停止位和校验位等参数。 - **配置 DMA 通道**:选择合适的 DMA 通道,并设置传输方向、数据大小和传输模式(如循环模式或单次模式)。 - **启用中断**:确保启用相关的 UARTDMA 中断,以便在数据传输完成后能够触发中断处理程序[^2]。 #### 2. 数据传输的实现 在实际应用中,UARTDMA 的结合可以用于发送和接收大量数据。以下是一些关键点: - **发送数据**:使用 `HAL_UART_Transmit_DMA` 函数启动 DMA 发送。此函数会将数据从内存传输到 UART 的发送寄存器中。发送完成后,DMA 会触发中断,更新 HAL 库的状态。 - **接收数据**:对于接收操作,DMA 可以配置为循环模式,以便持续接收数据。使用 `HAL_UART_Receive_DMA` 函数启动 DMA 接收。接收到的数据将存储在指定的缓冲区中,DMA 完成后会触发中断[^1]。 #### 3. 问题排查 在使用 UARTDMA 进行大量数据传输时,可能会遇到一些常见问题。以下是问题排查的建议: - **帧错误(FE)问题**:在某些情况下,可能会出现帧错误。为了解决这个问题,可以在 UART 的中断处理程序中检查帧错误标志,并在检测到帧错误时停止 DMA 接收,恢复错误中断使能[^3]。 - **DMA 传输中断**:如果 DMA 传输过程中出现中断,确保在中断处理程序中正确处理中断标志,并重新启动 DMA 传输。 - **缓冲区溢出**:确保接收缓冲区足够大,以避免数据丢失。如果数据量较大,可以考虑使用双缓冲区技术[^4]。 #### 4. 示例代码 以下是一个简单的示例代码片段,展示了如何在 STM32 上使用 UARTDMA 进行数据发送: ```c void UART_DMA_Send(uint8_t *pData, uint16_t Size) { HAL_UART_Transmit_DMA(&huart2, pData, Size); } void UART_DMA_Receive(uint8_t *pData, uint16_t Size) { HAL_UART_Receive_DMA(&huart2, pData, Size); } ``` 在使用这些函数时,确保已经正确初始化了 UARTDMA,并且启用了相关的中断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值