0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

直接存储器存取(DMA)简介及程序设计

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-06-01 09:01 次阅读

1.DMA简介

直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。
STM32F10x中有两个DMA控制器(DMA1有7个通道,DMA2有5个通道)每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。

DMA1请求映像
  USART1_TX – DMA1_Chnanel4
  USART1_RC – DMA1_Channel5
  利用DMA功能完成串口数据处理,无需CPU干预,减少CPU占用。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70#pic_center

2.程序设计

 1.DMA1_CH4配置

/******DMA配合串口1发送数据************
**形参:u32 cpar -- 外设地址
**
**例:DMA_CH4_Init(&USART1->DR,buff)
**外设地址:USART1->DR的地址
**					buff的地址
**************************************/
void DMA_CH4_Init(u32 cpar)
{
	RCC->AHBENR|=1<<0;//dma1时钟使能
	DMA1_Channel4->CCR&=~(1<<14);//非存储器到存储器模式
	DMA1_Channel4->CCR|=0x3<<12;//设置CH4优先级为最高
	DMA1_Channel4->CCR&=~(0x3<<10);//存储器数据宽度8位
	DMA1_Channel4->CCR&=~(0x3<<8);//外设数据宽度8位	
	DMA1_Channel4->CCR|=1<<7;//存储器地址增量
	DMA1_Channel4->CCR&=~(1<<6);//外设地址不增量
	DMA1_Channel4->CCR&=~(1<<5);//不执行循环操作
	DMA1_Channel4->CCR|=1<<4;//从存储器读
	DMA1_Channel4->CPAR=cpar;//外设地址
}
/**********开启DMA1_CH4数据传输*************
***
***形参:u16 data_len -- DMA要传输数目
***********************************************/
void DMA_CH4_Start(u8 *buff,u16 data_len)
{
	DMA1_Channel4->CMAR=(u32)buff;//存储器地址
	DMA1_Channel4->CCR&=~(1<<0);//关闭通道传输
	DMA1_Channel4->CNDTR=data_len;//设置传输数量
	DMA1_Channel4->CCR|=1<<0;//开启通道传输
}

  2.DMA1_CH5配置

/******DMA配合串口1接收数据************
**形参:u32 cpar -- 外设地址
**			u32 cmar -- 存储器地址
**
**例:DMA_CH5_Init(&USART1->DR,buff)
**外设地址:USART1->DR的地址
**					buff的地址
**************************************/
void DMA_CH5_Init(u32 cpar,u32 cmar)
{
	RCC->AHBENR|=1<<0;//dma1时钟使能
	DMA1_Channel5->CCR&=~(1<<14);//非存储器到存储器模式
	DMA1_Channel5->CCR|=0x3<<12;//设置CH4优先级为最高
	DMA1_Channel5->CCR&=~(0x3<<10);//存储器数据宽度8位
	DMA1_Channel5->CCR&=~(0x3<<8);//外设数据宽度8位	
	DMA1_Channel5->CCR|=1<<7;//存储器地址增量
	DMA1_Channel5->CCR&=~(1<<6);//外设地址不增量
	DMA1_Channel5->CCR&=~(1<<5);//执行循环操作
	DMA1_Channel5->CCR&=~(1<<4);//从外设读
	DMA1_Channel5->CPAR=cpar;//外设地址
	DMA1_Channel5->CMAR=cmar;//存储器地址
	DMA1_Channel5->CCR&=~(1<<0);//关闭通道传输
	DMA1_Channel5->CNDTR=1024;//设置传输数量
	DMA1_Channel5->CCR|=1<<0;//开启通道传输
}

  3.USART1配置

/********************串口初始化函数封装*********************
****硬件接口:USART1_TX -- PA9(发送)
**						USART1-RX --PA10(接收)
**						USART2_TX -- PA2(发送)
**						USART2-RX --PA3(接收)
**						USART3_TX -- PB10(发送)
**						USART3_RX -- PB11(接收)
形参:USART_TypeDef *USARTx -- 要配置的哪个串口
**			u32 baud  --波特率
**			u32 sysclk --时钟频率(USART1 --72MHZ ,USAT2USART3 --36MHZ)
**
***********************************************************/
void Usartx_Init(USART_TypeDef *USARTx,u32 baud,u32 sysclk)
{
	if(USART1 == USARTx)
	{
			/*1.开时钟*/
		RCC->APB2ENR|=1<<2;//PA时钟
		RCC->APB2ENR|=1<<14;//串口时钟
		RCC->APB2RSTR|=1<<14;//串口复位
		RCC->APB2RSTR&=~(1<<14);//取消复位
		/*2.配置GPIO口*/
		GPIOA->CRH&=0xFFFFF00F;
		GPIOA->CRH|=0x000008B0;//上下拉输入,复用推挽输出	
		USART1->CR3|=1<<7;//DMA发送
		USART1->CR3|=1<<6;//DMA接收
		USART1->CR1|=1<<4;//IDLE(空闲帧中断)
		STM32_NVIC_SetPriority(USART1_IRQn,0,1);//设置优先级
	}
	else if(USART2 == USARTx)
	{
		/*1.开时钟*/
		RCC->APB2ENR|=1<<2;//PA时钟
		RCC->APB1ENR|=1<<17;//USART2时钟
		RCC->APB1RSTR|=1<<17;//开复位时钟
		RCC->APB1RSTR&=~(1<<17);//取消复位
		/*2.配置GPIO口*/
		GPIOA->CRL&=0xFFFF00FF;//清除原来寄存器中的值
		GPIOA->CRL|=0x00008B00;		
		#ifdef USART2_IRQ
			USART2->CR1|=1<<5;//串口2接收中断
			STM32_NVIC_SetPriority(USART2_IRQn,1,2);//设置优先级
		#endif
	}
	else if(USART3 == USARTx)
	{
		/*1.开时钟*/
		RCC->APB2ENR|=1<<3;//PB时钟
		RCC->APB1ENR|=1<<18;//USART3时钟
		RCC->APB1RSTR|=1<<18;//开复位时钟
		RCC->APB1RSTR&=~(1<<18);//取消复位
		/*2.配置GPIO口*/
		GPIOB->CRH&=0xFFFF00FF;
		GPIOB->CRH|=0x00008B00;	
		#ifdef USART3_IRQ
			USART3->CR1|=1<<5;//开启接收中断
			STM32_NVIC_SetPriority(USART3_IRQn,0,0);//设置优先级
		#endif
	}
	else return;
	/*3.配置串口核心寄存器*/
	USARTx->BRR=sysclk*1000000/baud;//设置波特率
	USARTx->CR1|=1<<2;//接收使能
	USARTx->CR1|=1<<3;//发送使能
	USARTx->CR1|=1<<13;//使能串口3
	#ifdef DMA_USART1_SEND //利用DMA完成数据收发
		DMA_CH5_Init((u32 )&USART1->DR,(u32 )usart1_rx_buff);//DMA配合串口1接收数据
		DMA_CH4_Init((u32 )&USART1->DR);
	#endif
}

4.串口1中断,DMA数据接收数据

u8 usart1_rx_buff[1024];//串口1接收数据缓冲区
u16 usart1_cnt=0;//保存数组下班
u8 usart1_flag;//接收完成标志符
void USART1_IRQHandler(void)
{
	U8 C;
	//清除标志:先读USART_SR,再读USART_DR
	if(USART1->SR&1<<4)//空闲帧
	{
		C=USART1->DR;
		C=c;
       // USART1->DR=c;
		Usart1_Receive_Data();//接收数据处理函数
	}
	USART1->SR=0;//清除标志位
}

/*************************串口接收数据函数********************/
void Usart1_Receive_Data(void)
{
	DMA1_Channel5->CCR&=~(1<<0);//关闭通道传输
	usart1_cnt=1024-DMA1_Channel5->CNDTR;//获取接收到是字符长度
	if(usart1_cnt>=1024)usart1_cnt=0;
	DMA1->IFCR|=1<<17;//清除标志位
	DMA1_Channel5->CNDTR=1024;//从新赋值
	DMA1_Channel5->CCR|=1<<0;//开启通道传输
	usart1_flag=1;
}

  5.串口数据发送

/****************串口发送字符串*****************************/
void Usart1_SendStr(u8 *str)
{
	#ifdef DMA_USART1_SEND
		DMA_CH4_Start(str,strlen((char *)str));
	#else
		while(*str!='�')
		{
			USART1->DR=*str++;
			while(!(USART1->SR&1<<7));
		}
	#endif
}

6.硬件初始化,DMA配合串口调试

int main()
{
	u8 key;
	Beep_Init();//蜂鸣器初始化
	Led_Init();//LED初始化
	Key_Init();//按键初始化
	Usartx_Init(USART1,115200,72);
	while(1)
	{
		key=Key_Scan();
		if(key)
		{
			Usart1_SendStr((u8 *)"DMA1配合串口收发数据不定长测试234556789rn");
		}
		if(usart1_flag)
		{
			usart1_rx_buff[usart1_cnt]='�';
			printf("%srn",usart1_rx_buff);
			usart1_flag=0;
		}
	}
}

7.运行效果

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70#pic_center

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 存储器
    +关注

    关注

    38

    文章

    7148

    浏览量

    161984
  • STM32F10x
    +关注

    关注

    1

    文章

    81

    浏览量

    20576
  • dma
    dma
    +关注

    关注

    3

    文章

    535

    浏览量

    99019
收藏 人收藏

    评论

    相关推荐

    DMA控制8237A 精选资料分享

    1 DMA系统简介DMA(direct memory access)是一种外设与存储器或者存储器存储器
    发表于 07-26 08:11

    DMA简介

    DMA直接存储器访问)目录文章目录DMA直接存储器访问)一、
    发表于 07-28 08:59

    DMA简介

    1. DMA简介直接存储器存取(DMA,Direct Memory Access)用来提供在外设
    发表于 08-16 08:30

    DMA直接存储器存取的主要功能是什么

    DMA 简介DMA(Direct Memory Access) —— 直接存储器存取,是单片机的
    发表于 01-26 06:35

    STM32的DMA简介

    1、DMA简介DMA(Direct Memory Access) :直接存储器存取,是单片机的一
    发表于 01-26 08:27

    DMA直接存储器访问与配置流程简介

    DMA配置流程三、DMA应用简单实例1. 存储器存储器(M2M)2. 存储器到USART串口(M2P)一、
    发表于 01-26 07:54

    DMA直接存储器访问过程是怎样的?

    DMA直接存储器访问过程是怎样的?
    发表于 02-15 06:21

    怎样使用DMA控制来实现串口通信呢

    DMA1.DMA简介DMA全称Direct Memory Access,即直接存储器访问。直接
    发表于 02-22 07:00

    STM32F2技术培训_直接存储器访问_DMA

    STM32F2技术培训_直接存储器访问_DMA
    发表于 12-03 17:51 0次下载

    DMA直接内存存取

    【*】程序简介 -工程名称:DMA直接内存存取 -实验平台: 秉火STM32 F429 开发板 -MDK版本:5.16 -ST固件库版本:1
    发表于 12-13 15:09 9次下载

    TMS320VC5505DSP直接存储器存取DMA)控制器特点和操作的概述

     该文档描述了在TMS3VC5505/5504数字信号处理器(DSP)上可用的直接存储器存取DMA)控制器的特点和操作。此DMA控制器允许
    发表于 04-26 10:34 3次下载
    TMS320VC5505DSP<b class='flag-5'>直接</b><b class='flag-5'>存储器</b><b class='flag-5'>存取</b>(<b class='flag-5'>DMA</b>)控制器特点和操作的概述

    TMS320VC5501和TMS320VC5502DSP直接存储器存取DMA)控制器详细描述

    本文描述了TMS320VC5501/TMS320VC5502数字信号处理器(DSPS)的直接存储器存取DMA)控制器。此DMA控制器允许数
    发表于 04-26 15:41 10次下载
    TMS320VC5501和TMS320VC5502DSP<b class='flag-5'>直接</b><b class='flag-5'>存储器</b><b class='flag-5'>存取</b>(<b class='flag-5'>DMA</b>)控制器详细描述

    STM32学习笔记(7)——DMA直接存储器访问

    DMA配置流程三、DMA应用简单实例1. 存储器存储器(M2M)2. 存储器到USART串口(M2P)一、
    发表于 12-02 14:06 3次下载
    STM32学习笔记(7)——<b class='flag-5'>DMA</b><b class='flag-5'>直接</b><b class='flag-5'>存储器</b>访问

    STM32F103 中级篇 22 DMA 直接存储器访问

    22.1直接存储器访问22.1.1 DMA功能框图讲解DMA(Direct Memory Access)—直接
    发表于 12-16 16:59 2次下载
    STM32F103 中级篇 22 <b class='flag-5'>DMA</b> <b class='flag-5'>直接</b><b class='flag-5'>存储器</b>访问

    STM系列学习(2)DMA直接存储区访问

    进入正题DMA(DIrect Memory Access)直接存储器存取是单片机的一个外设,主要用来搬运数据,在AD采集、DA输出、存储器
    发表于 12-31 19:26 4次下载
    STM系列学习(2)<b class='flag-5'>DMA</b><b class='flag-5'>直接</b><b class='flag-5'>存储</b>区访问