【STM32】DMA数据转运(存储器到外设)

本篇博客重点在于标准库函数的理解与使用,搭建一个框架便于快速开发

目录

前言

外设DMA请求使能

DMA1

DMA2 

常用的外设DMA使能库函数 

配置串口发送的DMA请求

驱动代码

MyDMA.h

MyDMA.c

main.c 


前言

【STM32】DMA数据转运(存储器到存储器)_stm32dma往ccr搬运-CSDN博客

【STM32】ADC模拟数字转换(规则组多通道)+ DMA数据转运(外设到存储器)-CSDN博客

本博客学习DMA将数据从存储器转运到外设的代码,其实就是外设到存储器反过来

外设DMA请求使能

DMA请求同时只能有一个请求有效 !!!

DMA1

DMA2 

注意: DMA2控制器及相关请求仅存在于大容量产品和互联型产品中

常用的外设DMA使能库函数 

void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq,FunctionalState NewState);
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState);
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void SDIO_DMACmd(FunctionalState NewState);
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);

void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength)
void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource,FunctionalState NewState);

配置串口发送的DMA请求

DMA请求同时只能有一个请求有效 

	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//USART1->DR寄存器为8位
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址指针不自增,固定为&USART1->DR
	DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器地址指针自增
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//外设为转运的目的地
	DMA_InitStructure.DMA_BufferSize = Size;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//单次转运
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//失能,存储器到存储器才使能
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	DMA_Init(DMA1_Channel4, &DMA_InitStructure);//USART1的Tx引脚位于DMA1的通道4

串口利用DMA发送

使用DMA进行发送,可以通过设置USART_CR3寄存器上的DMAT位激活。当TXE位被置为’1’ 时,DMA就从指定的SRAM区传送数据到USART_DR寄存器。为USART的发送分配一个DMA 通道的步骤如下(x表示通道号):

1. 在DMA控制寄存器上将USART_DR寄存器地址配置成DMA传输的目的地址。在每个TXE 事件后,数据将被传送到这个地址。

2. 在DMA控制寄存器上将存储器地址配置成DMA传输的源地址。在每个TXE事件后,将从 此存储器区读出数据并传送到USART_DR寄存器。

3. 在DMA控制寄存器中配置要传输的总的字节数。

4. 在DMA寄存器上配置通道优先级。

5. 根据应用程序的要求,配置在传输完成一半还是全部完成时产生DMA中断。

6. 在DMA寄存器上激活该通道。

当传输完成DMA控制器指定的数据量时,DMA控制器在该DMA通道的中断向量上产生一中断。 在发送模式下,当DMA传输完所有要发送的数据时,DMA控制器设置DMA_ISR寄存器的TCIF 标志;监视USART_SR寄存器的TC标志可以确认USART通信是否结束,这样可以在关闭 USART或进入停机模式之前避免破坏最后一次传输的数据;软件需要先等待TXE=1,再等待 TC=1。

USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);//使能USART1的Tx发送请求

驱动代码

配置串口发送的代码这里不再赘述,如有需要可以阅读下方博客。

【STM32】USART通用同步/异步收发器(串口数据的接收与发送)_stm32 usart同步时钟-CSDN博客

MyDMA.h

#ifndef __MYDMA_H
#define __MYDMA_H
 
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size);
void MyDMA_Transfer(void);
 
#endif

MyDMA.c

#include "stm32f10x.h"                  // Device header
#include "MyDMA.h"

uint16_t MyDMA_Size;
 
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{
	MyDMA_Size = Size;
	
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//USART1->DR寄存器为8位
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址指针不自增,固定为&USART1->DR
	DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器地址指针自增
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//外设为转运的目的地
	DMA_InitStructure.DMA_BufferSize = Size;
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//单次转运
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//失能,存储器到存储器才使能
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	DMA_Init(DMA1_Channel4, &DMA_InitStructure);//USART1的Tx引脚位于DMA1的通道4
	
	DMA_Cmd(DMA1_Channel4, DISABLE);//先不开始转运
}
 
void MyDMA_Transfer(void)
{
	USART_DMACmd(USART1, USART_DMAReq_Tx, DISABLE);
	DMA_Cmd(DMA1_Channel4, DISABLE);
	DMA_SetCurrDataCounter(DMA1_Channel4, MyDMA_Size);//设置数据转运的大小
	DMA_Cmd(DMA1_Channel4, ENABLE);
	
	USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);//使能USART1的Tx发送请求
	while (DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET);
	DMA_ClearFlag(DMA1_FLAG_TC4);
}

main.c 

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "MyDMA.h"
#include "Serial.h"
#include "Key.h"

uint8_t Buff_Send[200] = {0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D};
uint16_t Conuter, Percent;
uint8_t KeyNum;
int main(void)
{
	Serial_Init();
	Key_Init();
	MyDMA_Init((uint32_t)&USART1->DR, (uint32_t)Buff_Send, 200);
	
	while (1)
	{
		KeyNum = Key_GetNum();
		if(KeyNum)
		{
			printf("\r\nData:\r\n");
			MyDMA_Transfer();
			Conuter = DMA_GetCurrDataCounter(DMA1_Channel4);
			Percent = 100 - (float)Conuter * 100 / 200;
			printf("\r\nSend%d%%", Percent);//显示传输百分比
			if(Percent == 100)
			{
				printf("\r\n*************Send Finish!******************\r\n");
			}

		}
		

	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值