STM32 寄存器配置笔记——USART DMA发送

一、DMA介绍

直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传 输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。当产品对于时序要求较严格时,外设使用DMA的方式能够减轻CPU负担,从而提高整体效率。本文主要介绍USART1 DMA发送配置,以stm32f10系列为例。DMA每次发送固定字节数据保证主循环每次执行DMA发送是均匀的,避免高负载等特殊情况下处理异常。

二、USART1对应的通道

三、配置流程

1)配置DMA1时钟

复制代码
RCC->AHBENR |= 1 << 0;		//¿ªÆôDMA1ʱÖÓ

2)dma初始化配置

DMA初始化配置如下,串口DMA发送属于存储到外设模型,配置DMA单次模式发送,且每次发送存储地址自增1,这里开启了NVIC中断向量,如果要使用DMA中断的话则需要把下面注释段DMA_CHx->CCR |= 1 << 1;和MY_NVIC_Init(3,3,DMA1_Channel4_IRQn,2);打开。

复制代码
void DMA_Init(void)
{
    DMA_Config(DMA1_Channel4, (u32)&USART1->DR);
}

void DMA_Config(DMA_Channel_TypeDef* DMA_CHx, u32 cpar)
{
	DMA_CHx->CPAR = cpar;                    //cfg periph addr 
	DMA_CHx->CCR |= 3 << 12;                 //cfg channel prio 3
	DMA_CHx->CCR |= 1 << 4;                  //cfg mem to periph
	DMA_CHx->CCR &= ~(1 << 5);               //cfg dma single transfer
	DMA_CHx->CCR |= 1 << 7;                  //cfg mem transfer addr inc
	//DMA_CHx->CCR |= 1 << 1;                //cfg dma ie
	//MY_NVIC_Init(3,3,DMA1_Channel4_IRQn,2);  //cfg dma channel4 enable nvic if enable ie
}

打开后发现能够进入中断函数。这里并没有使用DMA中断方式,使用的轮询查标志。

复制代码
void DMA1_Channel4_IRQHandler(void)
{
	DMA1->IFCR|=1<<13;
}

3)创建dma发送任务

4)dma数据发送流程

基于前面写的博客STM32 寄存器配置笔记------USART配置中断接收乒乓缓存处理基础上加的dma流程设计。代码如下:

复制代码
static u32 dma_tx_single_len = 0;
static u32 dma_tx_total_len = 0;
static u32 dma_mem_offset = 0;
static u8 dma_tx_task = 0;
static u8 *g_pdma_tx_dat = NULL;
static DMA_UART_TX_STATUS dma_tx_status = DMA_UART_CHANNEL_IDLE;

void create_dma_tx_task(u8 *pDat, u32 len)
{
    if (dma_tx_task)
	{
	    printf("dma_tx_task is running\r\n");
	}
	else
	{
	    dma_tx_task = 1;
		g_pdma_tx_dat = pDat;
		dma_tx_total_len = len;
	}
}

void data_dma_tx(void)
{
	switch(dma_tx_status)
	{
		case DMA_UART_CHANNEL_IDLE:
		{
			if (dma_tx_task)
			{
				dma_tx_status = DMA_UART_SENDING;
				dma_mem_offset = 0;
				dma_tx_single_len = ((dma_tx_total_len >= DMA_UART_SINGLE_TX_LEN) ? DMA_UART_SINGLE_TX_LEN : dma_tx_total_len);
				DMA_UART_TX_ENABLE(DMA1_Channel4, (u32)g_pdma_tx_dat, dma_tx_single_len);
			}
		}
		break;
	
		case DMA_UART_SENDING:
		{
		    if (0 == (DMA1->ISR & (1 << 13)))
				return;
			
			DMA1->IFCR |= 1 << 13;
			dma_tx_total_len -= dma_tx_single_len;
			if (dma_tx_total_len)
			{
				dma_mem_offset += dma_tx_single_len;
				dma_tx_single_len = ((dma_tx_total_len >= DMA_UART_SINGLE_TX_LEN) ? DMA_UART_SINGLE_TX_LEN : dma_tx_total_len);
				DMA_UART_TX_ENABLE(DMA1_Channel4, (u32)g_pdma_tx_dat + dma_mem_offset, dma_tx_single_len);
			}
			else
			{
			    dma_tx_status = DMA_UART_SENDED;
			}
		}
		break;
	
		case DMA_UART_SENDED:
		{
		    dma_tx_status = DMA_UART_CHANNEL_IDLE;
			dma_tx_task = 0;
		}
		break;
	
		default:
			break;
	}
}

具体调用如下:

相关推荐
笑鸿的学习笔记16 分钟前
虚幻引擎5-Unreal Engine笔记之`GameMode`、`关卡(Level)` 和 `关卡蓝图(Level Blueprint)`的关系
笔记·ue5·虚幻
aloneboyooo22 分钟前
STM32H7时钟树
stm32·单片机·嵌入式硬件
技术流浪者22 分钟前
PCB设计(十九)PCB设计中NPN/PNP选型策略
单片机·嵌入式硬件·硬件工程·pcb工艺
长流小哥1 小时前
STM32实战指南:SG90舵机控制原理与代码详解
stm32·单片机·嵌入式硬件·keil5
xduryan5 小时前
16.1 - VDMA视频转发实验之TPG
嵌入式硬件
向上的车轮7 小时前
MATLAB学习笔记(七):MATLAB建模城市的雨季防洪排污的问题
笔记·学习·matlab
躺着听Jay7 小时前
Oracle-相关笔记
数据库·笔记·oracle
田梓燊7 小时前
数学复习笔记 19
笔记·线性代数·机器学习
逼子格8 小时前
硬件工程师笔记——二极管Multisim电路仿真实验汇总
笔记·嵌入式硬件·硬件工程师·multisim·硬件工程师学习·电子器件·电路图
「QT(C++)开发工程师」8 小时前
STM32 | FreeRTOS 递归信号量
python·stm32·嵌入式硬件