STM32F4学习(四)——Usart+DMA

本文介绍了在STM32F4上使用Usart和DMA进行串口通信的基本步骤,包括串口初始化、DMA配置以及中断函数的设定。作者在实践中遇到接收数据受限于2个十六进制数的问题,寻求解决方案。
摘要由CSDN通过智能技术生成

上一篇是STM32F4的初级例程,主要就是对GPIO的操作。接下来要进行的就是Usart了,有时候我把想把某些中间量或者其他程序状态信息打印出来显示在电脑上,那么这是串口的作用就可想而知了。

STM32F407xx内嵌四个通用同步/异步接收器​​(USART1,USART2,USART3 和USART6)和两个通用异步收发器(UART4和UART5)。这6个接口提供异步通信的IrDASIR ENDEC支持,多机通信模式,单线半双工通信模式LIN主/从功能。 USART1和USART6接口能够速度高达10.5 Mbit / s的通信其他可用的接口通信高达5.25bit/s。USART1,USART2,USART3和USART6还提供硬件管理的CTS,RTS信号,智能卡的模式(ISO7816兼容)和类似的SPI通信能力。所有接口都可以通过DMA控制器。

这里我使用了两个线的最简单串口设置。

首先第一步就是串口初始化,配置Usart的GPIO、工作模式

/*************************************************************************************
 * 函数名: USART2_Config
 * 描述  : USART2 GPIO、工作模式的配置
 * 输入  : 无
 * 输出  : 无
 * 批注  : PA2->TX PA3->RX
*************************************************************************************/
void USART2_Config(void)
{
  GPIO_InitTypeDef   GPIO_InitStructure;   //初始化GPIO结构体
  USART_InitTypeDef  USART_InitStructure;  //初始化Usart结构体
	
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);   //使能GPIOA的时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);   //使能USART2的时钟
	
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);
	
	/* 配置USART2的GPIO */
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStructu
STM32F4 系列中,串口接收不定长数据可以采用空闲中断和 DMA 相结合的方式来实现,其主要流程如下: 1. 配置串口3的接收缓冲区大小和波特率等参数。 2. 配置串口3的空闲中断,当串口接收到数据后触发中断,并将接收到的数据存储到接收缓冲区中。 3. 配置 DMA,将串口3的数据传输到内存中,使用循环模式,不断接收数据。 4. 在空闲中断中,判断是否接收到了完整的数据包,如果接收到了完整的数据包,则可以对数据进行处理;否则继续等待下一个数据包。 下面是实现该功能的代码示例,供参考: ``` // 定义串口接收缓冲区大小 #define RX_BUF_SIZE 256 // 定义串口接收缓冲区 uint8_t rx_buf[RX_BUF_SIZE]; // 定义 DMA 缓冲区 uint8_t dma_buf[RX_BUF_SIZE]; // 定义 DMA 传输完成标志 volatile uint8_t dma_transfer_complete = 0; // 串口空闲中断处理函数 void USART3_IRQHandler(void) { // 判断是否为接收空闲中断 if (USART_GetITStatus(USART3, USART_IT_IDLE) != RESET) { // 清除接收空闲中断标志位 USART_ClearITPendingBit(USART3, USART_IT_IDLE); // 关闭 DMA 传输 DMA_Cmd(DMA1_Stream1, DISABLE); // 计算接收到的数据长度 uint16_t len = RX_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Stream1); // 处理接收到的数据 process_data(rx_buf, len); // 重启 DMA 传输 DMA_Cmd(DMA1_Stream1, ENABLE); } } // DMA 传输完成中断处理函数 void DMA1_Stream1_IRQHandler(void) { // 判断是否为传输完成中断 if (DMA_GetITStatus(DMA1_Stream1, DMA_IT_TCIF1) != RESET) { // 清除传输完成中断标志位 DMA_ClearITPendingBit(DMA1_Stream1, DMA_IT_TCIF1); // 设置 DMA 传输完成标志 dma_transfer_complete = 1; } } // 初始化函数 void init(void) { // 初始化串口3 USART_InitTypeDef usart_init; USART_StructInit(&usart_init); usart_init.USART_BaudRate = 115200; USART_Init(USART3, &usart_init); // 配置串口3空闲中断 USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); NVIC_EnableIRQ(USART3_IRQn); // 配置 DMA DMA_InitTypeDef dma_init; DMA_StructInit(&dma_init); dma_init.DMA_Channel = DMA_Channel_4; dma_init.DMA_PeripheralBaseAddr = (uint32_t)&USART3->DR; dma_init.DMA_Memory0BaseAddr = (uint32_t)dma_buf; dma_init.DMA_DIR = DMA_DIR_PeripheralToMemory; dma_init.DMA_BufferSize = RX_BUF_SIZE; dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable; dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable; dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; dma_init.DMA_Mode = DMA_Mode_Circular; dma_init.DMA_Priority = DMA_Priority_VeryHigh; dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable; dma_init.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; dma_init.DMA_MemoryBurst = DMA_MemoryBurst_Single; dma_init.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Stream1, &dma_init); // 配置 DMA 传输完成中断 DMA_ITConfig(DMA1_Stream1, DMA_IT_TC, ENABLE); NVIC_EnableIRQ(DMA1_Stream1_IRQn); // 启动 DMA 传输 DMA_Cmd(DMA1_Stream1, ENABLE); } int main(void) { // 初始化 init(); while (1) { // 等待 DMA 传输完成标志被设置 while (!dma_transfer_complete); // 复制数据到接收缓冲区 memcpy(rx_buf, dma_buf, RX_BUF_SIZE); // 清除 DMA 传输完成标志 dma_transfer_complete = 0; } } ``` 相关问题: 1. 如何配置 STM32F4 的串口3接收缓冲区大小和波特率等参数? 2. 如何配置 STM32F4 的空闲中断? 3. 如何配置 STM32F4DMA
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值