今天总结一下DMA(Direct Memory Access,直接存储器存储),在以往我们从串口读取数据到内存的流程是,cpu通过串口读取导数据,然后CPU再将数据写入固定的内存。这种读取方式占用了大量的cpu资源,如果数据量非常大,CPU将耗费大量的时间来进行数据的读写操作。因此DMA应运而生。DMA的作用是啥呢?从名字能看出来一二,它可以直接从串口读取数据存储在内存中,几乎不占用CPU的资源。打个比方来说,一个砌墙的工人,他的主要工作是砌墙,但他首先需要耗费大量时间去搬砖到自己身边,然后才开始砌墙,这样他砌墙的进度肯定很慢。现在砌墙的工人不自己去搬砖了,他雇佣了另外一个人来帮助他去把砖搬过来,在搬之前砌墙的工人告诉搬砖的工人,他要去哪里搬砖、搬什么样的砖、搬砖的速度、搬过来后放在那里等问题。这样虽然在开始耗费了点时间去告诉搬砖工人一些要求,看起来比较繁琐,其实这些所占用的时间比起自己去搬砖耗费的时间少多了。在这个例子中,砌墙的工人就是我们所说的CPU,砖就是需要读写数据,搬砖工人就是DMA,DMA的引入为CPU读写数据节省了大量的时间,CPU只需要在开始耗费极少的时间对DMA进行相关的配置,就可以去做其他的事情。

我在做实验的过程中,遇到了很多狗血的bug,不过最终都得以解决。今天做的实验是利用DMA通过USART1向发送数据,同时LED持续点亮,当发送数据完成时,进入中断将LED熄灭,从而来验证DMA工作时CPU可以去做别的事情,而没有影响。下面来总结一下DMA的开发流程:

  1. NVIC中断优先级的配置
  2. DMA_InitTypeDef结构体的配置(记得调用NVIC配置的函数,我多次忘记调用)
  3. 初始化DMA,DMA_Init(DMA1_Channel4,&结构体)(DMA1_Channel4为串口1的发送,具体的可以看手册)
  4. 使能DMA,DMA_Cmd(DMA1_Channel4,ENABLE)
  5. 配置并使能中断DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE)
  6. 开始利用DMA进行串口发送数据USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
  7. 在中断中DMA_GetFlagStatus(DMA1_FLAG_TC4) == SET来确定发送数据完成

根据以上步骤进行先关的配置,其他的比如串口和LED的配置在前面已经配置过了直接把USART和LED的配置文件添加在该项目中即可。下面来看代码,代码中只有DMA的配置和主函数。

下面这是dma.c文件中的内容:

#include"dma.h"uint16_t SendBuff[SENDSBUFF_SIZE];static void NVIC_Config(void)
{NVIC_InitTypeDef nvic_struct;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);nvic_struct.NVIC_IRQChannel = DMA1_Channel4_IRQn;nvic_struct.NVIC_IRQChannelPreemptionPriority = 1;nvic_struct.NVIC_IRQChannelSubPriority = 1;nvic_struct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvic_struct);
}void DMA1_Config(void)
{DMA_InitTypeDef dma_struct;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);NVIC_Config();dma_struct.DMA_PeripheralBaseAddr = USART1_BASE + 0x04;//数据要到达的地址dma_struct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//每次发送数据的大小dma_struct.DMA_MemoryBaseAddr = (u32)SendBuff;//数据所在的地址dma_struct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//每次读取数据的大小dma_struct.DMA_BufferSize = SENDSBUFF_SIZE;//总共传输的数据的大小dma_struct.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储数据的地址是否自动增加dma_struct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//数据到达的地址是否自动增加dma_struct.DMA_DIR = DMA_DIR_PeripheralDST;//传输的方向内存到外设dma_struct.DMA_M2M = DMA_M2M_Disable;//内存到内存是否允许dma_struct.DMA_Mode = DMA_Mode_Normal;//传输方式,发送一次还是循环发送dma_struct.DMA_Priority = DMA_Priority_Medium;//优先级DMA_Init(DMA1_Channel4,&dma_struct);//初始化DMA_Cmd(DMA1_Channel4,ENABLE);//使能DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//中断配置并使能}

SendBuff数组存储的是要发送的数据,两个函数为中断配置函数,在前面的外部中断中已经配置过了。第二个函数为DMA的配置函数,与其他外设的配置类似,先定义一个结构体,然后开启时钟。这个DMA1的时钟和之前的都不一样,在AHB上,配置时需要注意。

在main.c文件中:

#include"led.h"
#include"usart.h"
#include"dma.h"extern uint16_t SendBuff[SENDSBUFF_SIZE];//引用外部定义的变量
int i;int main(void)//主函数
{GPIO_LED_Config();USART1_Config();DMA1_Config();for(i = 0;i < SENDSBUFF_SIZE;i++)//为发送数据赋值{SendBuff[i] = 0xff;}printf("Send start!");USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);LED(ON);printf("wait interrupt!");while(1);
}void DMA1_Channel4_IRQHandler(void)//中断函数
{printf("into interrupt!");if(DMA_GetFlagStatus(DMA1_FLAG_TC4) == SET)//判断是否发送完成{printf("send success");LED(OFF);DMA_ClearFlag(DMA1_FLAG_TC4);//清除标志位}
}

在实验的过程中,编译出现symbol multiply defined错误的原因,因为在xxx.h中定义了许多变量,xxx.c中调用xxx.h中的变量,在主文件中也调用了xxx.h中的变量,导致变量被重复定义。

解决办法:不应该在xxx.h中定义xxx.c中使用的变量,应该在xxx.c中定义所需要的变量,然后再在主程序中将调用xxx.c中定义的变量使用extern 例:extern u32 test.

STM32----摸石头过河系列(五)相关推荐

  1. oCPC实践录 | 摸石头过河,oCPC先跑起来再说

    oCPC才开始的实践基本上是摸着石头过河,不断测试实验.不过也可以参考已有的oCPC产品设计,oCPC首要需要解决的是转化目标和转化数据. 在解决转化数据之前,可以先看一下申探社:深入互联网广告中的出 ...

  2. 58同城如何摸石头过河?

    本文转自:http://www.huxiu.com/article/4397/1.html 这家典型"鼠标+水泥".不愿复制Cragslist模式的创业公司,摸爬滚打间的经验教训 ...

  3. STM32----摸石头过河系列(一)

    在学习stm32之前,我较为熟练的掌握了51单片机的开发,可以运用51中的输入.输出,以及定时器.中断等.今天第一天,学习stm32点亮LED灯. 在本次学习中使用的是stm32f103RC系列单片机 ...

  4. STM32----摸石头过河系列(八)

    在STM32中定时器(TIM)是很重要的外设,具有相当多的作用,并且用法多样,内容多.今天来分析一下定时器的理论知识,没有实例. 在STM32中定时可以分为三类:基本定时器.通用定时器.高级定时器. ...

  5. STM32----摸石头过河系列(六)

    今天了解一下ADC,stm32中的模数转换利用的是逐次逼近的方法,这个当时在考研时特别熟,现在又忘了,又去问了一下万能的百度.先是多少了解一下这个转换过程,在32的开发过程中用不到,但毕竟从事这个的, ...

  6. STM32----摸石头过河系列(四)

    今天分析STM32一个相当重要的外设--串口,在我使用的这款单片机中有三个串口分别为USART1,USART2,USART3.其中USART1挂载在总线APB2上,USART2,3挂载在APB1上.这 ...

  7. 中台,都他妈被你们说糊涂了,文内才是正宗解释,别摸石头过河了,石头早就有了

    (1)我们先说说技术架构分层 我们按技术架构通常是这样的: 1.UI交互层:Windows UI.PC Web UI.移动App UI.微信小程序UI.摄像头视觉识别人机界面.语音交互人机界面 2.逻 ...

  8. STM32----摸石头过河系列(七)

    今天练习了32中的SysTick定时器,通常叫做滴答定时器.定时器的作用,用过51的想必都知道.定时器主要用来处理一些周期性的,时间间隔固定的事件.同时定时器也可以用来得到一个事件所耗费的时间.下面来 ...

  9. STM32----摸石头过河系列(三)

    前两次了解了LED的打开和关闭,以及按键的检测和按键作为输入的中断.今天来了解一下SysTick系统定时器.玩过51的想必对定时器一定不会陌生.定时器可以让我们隔着固定的时间的去做一些事情,比如让LE ...

最新文章

  1. mysql基本命令总结_mysql 常用基本命令总结
  2. c++,不能声明为虚函数的函数
  3. 自定义TabHost,TabWidget样式 .
  4. ASP.NET2.0通用数据访问类
  5. Deepin、Debian、Ubuntu恢复误删除的/var/lib/dpkg
  6. 【代码实现接口测试】Requests库
  7. eclipse搜索框太小
  8. docker将容器设置与宿主机为同一局域网
  9. Hadoop--Linux环境下JDK/Hadoop的安装与配置
  10. linux 取消nologin_Linux中nologin的应用 转
  11. 湖仓一体是否会掀起金融业的下一波数字浪潮?
  12. VUE 响应式原理源码:带你一步精通 VUE | 原力计划
  13. Ansible 详细用法部署安装
  14. ajax jsonp不触发后台_JsonP
  15. Handler源码阅读
  16. 人工智能与计算机发展史
  17. Windows 10 如何修改桌面路径位置
  18. Unity Twitter登录接入
  19. 怎样把已经做好的网页传到网上去?
  20. c语言结构体简单试题,C语言6结构体练习题6

热门文章

  1. 老spring3.2版本 redistemplate 报错_植物大战僵尸加强版本
  2. 作者:吴城文,男,清华大学计算机科学与技术系硕士生。
  3. 加括号改变连除式结果(洛谷P2651题题解,Java语言描述)
  4. 面试基础算法、及编程 第一弹
  5. 日志单例log4cpp简述
  6. windows安装mysql5.7
  7. ajax核心技术1---XMLHttpRequset对象的使用
  8. 《Java 20年:道路与梦想》迷你书发布
  9. linux小白-基础命令-cd
  10. 42.对话框插件——dialog