STM32F40X USART1 DMA串口数据收发

本文详细介绍了STM32F4微控制器USART1 DMA的配置过程及其实现串口数据收发的测试方法。通过具体的代码示例,展示了如何使用DMA进行高效的数据传输,避免中断方式带来的开销。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前的文章描述过STM32F10X USART DMA串口收发数据的文章,近期接触了STM32F4,使用习惯了USART DMA方式,就不愿意用中断的方式接收数据,了解了并习惯串口DMA后,还是觉得真香!

本文主要描述STM32F40X USART1 DMA的配置以及简单的测试。

相对于STM32F1的串口DMA配置,STM32F4的串口DMA相对更复杂一点儿,毕竟STM32F4的功能还是强大很多。

由于要配置STM32F4的USART1 DMA,根据datasheet的描述,做相应的配置

USART1的PA9-TX;PA10-RX

bsp_usart1_dma.c的配置代码

#include "bsp_usart1_dma.h"

uint8_t global_dma_recv_buf[LEN_USART1_RECV_BUF];
uint8_t global_dma_send_buf[LEN_USART1_RECV_BUF];

void init_usart1_dma(uint32_t bound)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	DMA_InitTypeDef DMA_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10, GPIO_AF_USART1);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	USART_InitStructure.USART_BaudRate = bound;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No ;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART1, &USART_InitStructure);	
		
	DMA_DeInit(DMA2_Stream5);
	while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE); 
	DMA_InitStructure.DMA_Channel = DMA_Channel_4;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)global_dma_recv_buf;
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
	DMA_InitStructure.DMA_BufferSize = LEN_USART1_RECV_BUF;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	DMA_Init(DMA2_Stream5, &DMA_InitStructure);
	DMA_Cmd(DMA2_Stream5, ENABLE);
	DMA_ClearITPendingBit(DMA2_Stream5, DMA_IT_TCIF5); 
	
	DMA_DeInit(DMA2_Stream7);
	while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE); 
	DMA_InitStructure.DMA_Channel = DMA_Channel_4;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)global_dma_send_buf;
	DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
	DMA_InitStructure.DMA_BufferSize = 0;
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	DMA_Init(DMA2_Stream7, &DMA_InitStructure);
	DMA_Cmd(DMA2_Stream7, DISABLE);
	DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7); 
	DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7);
	
	USART_ClearFlag(USART1, USART_FLAG_TC);
	USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
	USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
	USART_Cmd(USART1, ENABLE);
}

void fn_usart1_dma_send_bytes(uint8_t *bytes, uint8_t bytes_len)
{
	DMA_Cmd(DMA2_Stream7, DISABLE);
	memcpy(global_dma_send_buf, bytes, bytes_len);
	while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE); 
	DMA_SetCurrDataCounter(DMA2_Stream7, bytes_len);
	DMA_Cmd(DMA2_Stream7, ENABLE);
	while(DMA_GetCurrDataCounter(DMA2_Stream7));
	while(USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);
	DMA_ClearFlag(DMA2_Stream7 , DMA_FLAG_TCIF7 | DMA_FLAG_FEIF7 | DMA_FLAG_DMEIF7 | DMA_FLAG_TEIF7 | DMA_FLAG_HTIF7);
}

uint8_t fn_usart1_dma_recv_bytes(uint8_t *recv_buf, uint16_t *len_recv)
{
	uint16_t len_dma_recv = 0;
	if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) != RESET)
	{
		USART_ReceiveData(USART1);
		DMA_Cmd(DMA2_Stream5, DISABLE);
		len_dma_recv = LEN_USART1_RECV_BUF - DMA_GetCurrDataCounter(DMA2_Stream5);
		memcpy(recv_buf, global_dma_recv_buf, len_dma_recv);
		DMA_SetCurrDataCounter(DMA2_Stream5, LEN_USART1_RECV_BUF);
		USART_ClearFlag(USART1, USART_FLAG_IDLE);
		DMA_ClearFlag(DMA2_Stream5 , DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);
		DMA_Cmd(DMA2_Stream5, ENABLE);
	}
	if(len_dma_recv <= 0)
	{
		return 1;
	}
	else if(len_dma_recv > LEN_USART1_RECV_BUF)
	{
		return 2;
	}
	*len_recv = len_dma_recv;
	return 0;
}

bsp_usart1_dma.h的代码

#ifndef __BSP_USART1_H
#define __BSP_USART1_H

#include <stm32f4xx.h>	
#include <string.h>

#define LEN_USART1_RECV_BUF 256

void init_usart1_dma(uint32_t bound);
void fn_usart1_dma_send_bytes(uint8_t *bytes, uint8_t bytes_len);
uint8_t fn_usart1_dma_recv_bytes(uint8_t *recv_buf, uint16_t *len_recv);

#endif

main.c测试主函数代码(发啥回啥)

#include <stm32f4xx.h>	

#include "bsp_led.h" 
#include "bsp_beep.h"
#include "util_time.h" 
#include "bsp_usart1_dma.h"

int main(void)
{	
	uint8_t buf[256];
	uint16_t len;
	uint8_t suc;
	
	init_led();
	init_beep();
	init_usart1_dma(19200);
	
	func_beep_play();
	func_led0_on();
	delay_ms(200);
	func_beep_stop();
	delay_s(1);
	
	for(;;)
	{
		suc = fn_usart1_dma_recv_bytes(buf, &len);
		if(suc == 0)
		{
			fn_usart1_dma_send_bytes(buf, len);
		}
		func_led1_on();
		delay_ms(100);
		func_led1_off();
		delay_ms(100);
	}
}

测试效果如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值