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

  简单的来说,DMA功能指的就是,不需要程序控制,单片机内部自己可以控制数据从一个地方到另一个地方的传输。下面直接通过代码来看DMA功能如何实现。

#include "dma.h"u16 DMA1_MEM_LEN;              //保存DMA每次数据传送的长度//DMA1的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_CHx:DMA通道CHx
//cpar:外设地址
//cmar:存储器地址
//cndtr:数据传输量
void MYDMA_Config(DMA_Channel_TypeDef *DMA_Chx, u32 cpar, u32 cmar, u16 cndtr)
{DMA_InitTypeDef DMA_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                        //使能DMA传输DMA_DeInit(DMA_Chx);                                                   //将DMA的通道1寄存器重设为缺省值DMA1_MEM_LEN = cndtr;DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;                      //DMA外设基地址DMA_InitStructure.DMA_MemoryBaseAddr = cmar;                             //DMA内存基地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;                       //数据传输方向,从内存读取发送到外设DMA_InitStructure.DMA_BufferSize = cndtr;                                //DMA通道的DMA缓存的大小DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;       //外设地址寄存器不变DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                     //内存地址寄存器递增DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;     //数据宽度为8位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;           //数据宽度为8位DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                             //工作在正常模式DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                     //DMA通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                           //DMA通道x没有设置为内存到内存传输DMA_Init(DMA_Chx, &DMA_InitStructure);
}void MYDMA_Enable(DMA_Channel_TypeDef* DMA_CHx)
{DMA_Cmd(DMA_CHx,DISABLE);DMA_SetCurrDataCounter(DMA_CHx,DMA1_MEM_LEN);DMA_Cmd(DMA_CHx,ENABLE);
}

  这里使用了一个通用的DMA初始化,没有具体说明数据是从哪个内存发送到哪个外设,当哪个外设需要使用DMA功能时,在初始化的时候设置外设地址和内存地址就可以了。比如这里要使用串口发送的DMA功能。

#define SEND_BUF_SIZE 8200           //发送数据长度,最好等于sizeof(TEXT_TO_SEND)+2的整数倍.
u8 SendBuff[SEND_BUF_SIZE];const u8 TEXT_TO_SEND[] = {"DMA 串口实验,缓冲区的数据,用DMA功能,通过串口2发送出来。"};
int main(void)
{u16 i;u8 t = 0;u8 j, mask = 0;float pro = 0;delay_init();NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);uart_init(115200);UART2_Init(115200);LED_Init();KEY_Init();//MYDMA_Config(DMA1_Channel4, (u32)&USART1->DR, (u32)SendBuff, SEND_BUF_SIZE);  //DMA1通道4,外设为串口1,存储器为SendBuff,长度SEND_BUF_SIZE.MYDMA_Config(DMA1_Channel7, (u32)&USART2->DR, (u32)SendBuff, SEND_BUF_SIZE);     //DMA1通道7,外设为串口2,存储器为SendBuff,长度SEND_BUF_SIZE.j = sizeof(TEXT_TO_SEND);for(i = 0; i < SEND_BUF_SIZE; i++)    //填充数据到SendBuff{if(t >= j)                      //加入换行符{if(mask){SendBuff[i] = 0x0a;t = 0;}else{SendBuff[i] = 0x0d;mask++;}}else{mask = 0;SendBuff[i] = TEXT_TO_SEND[t];t++;}}printf("DMA test!!!\r\n");while(1)     //串口1打印信息  通过DMA功能将SendBuff中的数据,通过串口2发送出来{t = KEY_Sacn(0);if(t == KEY1_PRES){printf("Start Transimit....");printf("\r\nDMA DATA:\r\n");//串口1 DMA 发送
//            USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);            //使能串口1的DMA发送
//            MYDMA_Enable(DMA1_Channel4);                              //开始一次DMA传输//串口2 DMA 发送USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);               //使能串口1的DMA发送MYDMA_Enable(DMA1_Channel7);                               //开始一次DMA传输//等待DMA传输完成,此时我们来做另外一些事,点灯//实际应用中,传输数据期间,可以执行另外的任务while(1){//串口1 DMA 判断
//                if(DMA_GetFlagStatus(DMA1_FLAG_TC4) != RESET)            //判断通道4传输完成
//                {//                    DMA_ClearFlag(DMA1_FLAG_TC4);                 //清除通道4传输完成标志
//                    break;
//                }//串口2 DMA 判断if(DMA_GetFlagStatus(DMA1_FLAG_TC7) != RESET)           //判断通道7传输完成{DMA_ClearFlag(DMA1_FLAG_TC7);                       //清除通道7传输完成标志break;}//pro = DMA_GetCurrDataCounter(DMA1_Channel4);pro = DMA_GetCurrDataCounter(DMA1_Channel7);pro = 1 - pro / SEND_BUF_SIZE;pro *= 100;printf("%f %%\r\n", pro);}printf("100%%");printf("\r\nTransimit Finished!\r\n");}i++;delay_ms(10);if(i == 20){LED0 = !LED0;i = 0;}}
}

  在初始化的时候,将串口数据发送寄存器作为外设地址,将存储发送数据的地址作为内存地址。数据的传输方向是从内存读取数据然后发送到外设地址中去。也就是一旦开启DMA传输功能之后,单片机就会自动将数组中的数据依次传输到串口发送数据寄存器中。这样数据就自动从串口发送出来了。不需要程序控制。

  这里分别使用串口1和串口2进行了测试,每按一次按键,就启动一次DMA数据传输。在传输数据的过程中模拟程序执行其他操作。当DMA数据传输完成后,会打印出当前传输了多少字节的数据。

STM32F103DMA功能实现相关推荐

  1. 如果你没用过maven的install,你应该了解一下!maven中的install功能及用法。

    maven中有一个大多数人都忽视或者没有用到过的一个功能--install,大多数java开发人员都了解maven,使用maven进行依赖管理.但使用的大多数功能不过是clean清理.compile编 ...

  2. 一个form表单,多个提交按钮(实现不同功能和地址的提交)

    直接上代码 表单部分: <form action="" name="find" method="post" enctype=" ...

  3. nginx介绍及常用功能

    什么是nginx nginx跟Apache一样,是一个web服务器(网站服务器),通过HTTP协议提供各种网络服务. Apache:重量级的,不支持高并发的服务器.在Apache上运行数以万计的并发访 ...

  4. java action dao_java中Action层、Service层和Dao层的功能区分

    一.Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DA ...

  5. 窗口键 键位码_键盘上这些被冷落的键位居然有这么强大的功能

    各位小伙伴们大家好啊,又到了达尔优外设小课堂时间了,今天呢,我们将为大家带来的是键盘上的功能区按键小科普,也就是我们常说的F区按键. F区按键 F1~F12这个区域的按键我们通常称为功能键,而F的意思 ...

  6. app如何打开了request url_手机日历app内如何打开节日提醒功能?支持提前提醒节日的云便签...

    我们一年中要度过的节日有很多,除了法定节假日之外,还有其他的很多节日,例如西方传来的圣诞节.万圣节,国际性的节日例如父亲节.母亲节等,还有一些传统节日例如小寒.冬至.腊八等,这些都是不放假的. 有时候 ...

  7. etcd 笔记(05)— etcd 代码结构、各模块功能、整体架构、各模块之间的交互、请求和应答流程

    1. etcd 项目结构和功能 etcd 项目代码的目录结构如下: $ tree ├── auth ├── build ├── client ├── clientv3 ├── contrib ├── ...

  8. OpenCV 笔记(01)— OpenCV 概念、整体架构、各模块主要功能

    1. OpenCV 概念 图像处理( Image Processing )是用计算机对图像进行分析, 以达到所需结果的技术, 又称影像处理. 图像处理技术一般包括图像压缩, 增强和复原, 匹配.描述和 ...

  9. django自带的分页功能

    django自带的分页功能 django中自带的分页功能有缺陷,但是也是一种思路,所以在下做一个整理,方便以后使用,还有服务各位小伙伴. django视图部分的代码.(注释才是重点) from dja ...

最新文章

  1. 手动创建swap分区
  2. ubuntu phpinfo mysql_Ubuntu 16.04 apache+php+mysql环境搭建
  3. zabbix-3.0.4添加对windows 2008r2的监控
  4. Linkis生产部署服务器配置参考指南
  5. RuntimeError: dictionary changed size during iteration
  6. mac下安装brew下载非常慢解决方法
  7. python 正则使用笔记
  8. 【EPS精品教程】史上最牛EPS说明文档大全(23个PDF文档)
  9. gulp入坑系列(1)——安装gulp
  10. leetcode - 63. 不同路径 II
  11. Python使用numpy滤除图像中的低频信号
  12. 问题(二)--算法相关
  13. UE4之判断点是否在矩形内
  14. 你们一直吐槽的12306,你知道他们的的架构有多牛X吗
  15. 打造微信“智慧城市” 乌海率先开通城市公共微信服务
  16. Oracle大神资料索引
  17. 网页版 Facebook 第三方登录示例 Facebook网页登录
  18. 关于伪元素如何添加过渡动画功能
  19. 树莓派 teamviewer 使用代理服务器上网
  20. 2021年中国人工智能产业及其重点企业分析(阿里巴巴、百度、腾讯、科大讯飞)[图]

热门文章

  1. 运算符和||运算符的优先级问题 专题
  2. android IPC及原理简介
  3. 用socket来代替HttpWebRequest和HttpWebResponse
  4. 采用组策略Loopback功能限制文件夹重定向路径
  5. 《大道至简》阅读笔记02
  6. HDOJ---1267 下沙的沙子2[DP或卡特兰数]
  7. gdb调试多进程和多线程
  8. ajax servlet怎么接收_【百战程序员从开始到植发】之AJAX
  9. 我们应该如何写好HTMLCSS
  10. 资深前端开发工程师分享:关于前端学习路线的一些建议