LV16-18-DMA-02-DMA实例
本文主要是STM32开发——DMA实例的一些相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows | windows11 |
Ubuntu | Ubuntu16.04的64位版本 |
VMware® Workstation 16 Pro | 16.2.3 build-19376536 |
SecureCRT | Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日 |
开发板 | 正点原子 i.MX6ULL Linux阿尔法开发板 |
uboot | NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03) |
linux内核 | linux-4.15(NXP官方提供) |
STM32开发板 | 正点原子战舰V3(STM32F103ZET6) |
点击查看本文参考资料
- 通用
分类 | 网址 | 说明 |
官方网站 | https://www.arm.com/ | ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档 |
https://www.st.com/content/st_com/zh.html | ST官方网站,在这里我们可以找到STM32的相关文档 | |
https://www.stmcu.com.cn/ | 意法半导体ST中文官方网站,在这里我们可以找到STM32的相关中文参考文档 | |
http://elm-chan.org/fsw/ff/00index_e.html | FatFs文件系统官网 | |
教程书籍 | 《ARM Cortex-M3权威指南》 | ARM公司专家Joseph Yiu(姚文祥)的力作,中文翻译是NXP的宋岩 |
《ARM Cortex-M0权威指南》 | ||
《ARM Cortex-M3与Cortex-M4权威指南》 | ||
开发论坛 | http://47.111.11.73/forum.php | 开源电子网,正点原子的资料下载及问题讨论论坛 |
https://www.firebbs.cn/forum.php | 国内Kinetis开发板-野火/秉火(刘火良)主持的论坛,现也做STM32和i.MX RT | |
https://www.amobbs.com/index.php | 阿莫(莫进明)主持的论坛,号称国内最早最火的电子论坛,以交流Atmel AVR系列单片机起家,现已拓展到嵌入式全平台,其STM32系列帖子有70W+。 | |
http://download.100ask.net/index.html | 韦东山嵌入式资料中心,有些STM32和linux的相关资料也可以来这里找。 | |
博客参考 | http://www.openedv.com/ | 开源网-原子哥个人博客 |
http://blog.chinaaet.com/jihceng0622 | 博主是原Freescale现NXP的现场应用工程师 | |
cortex-m-resources | 这其实并不算是一个博客,这是ARM公司专家Joseph Yiu收集整理的所有对开发者有用的官方Cortex-M资料链接(也包含极少数外部资源链接) |
- STM32
STM32 | STM32 HAL库开发实战指南——基于F103系列开发板 | 野火STM32开发教程在线文档 |
STM32库开发实战指南——基于野火霸道开发板 | 野火STM32开发教程在线文档 |
- SD卡
SD Association | 提供了SD存储卡和SDIO卡系统规范 |
点击查看相关文件下载
STM32F103xx英文数据手册 | STM32F103xC/D/E系列的英文数据手册 |
STM32F103xx中文数据手册 | STM32F103xC/D/E系列的中文数据手册 |
STM32F10xxx英文参考手册(RM0008) | STM32F10xxx系列的英文参考手册 |
STM32F10xxx中文参考手册(RM0008) | STM32F10xxx系列的中文参考手册 |
Arm Cortex-M3 处理器技术参考手册-英文版 | Cortex-M3技术参考手册-英文版 |
STM32F10xxx Cortex-M3编程手册-英文版(PM0056) | STM32F10xxx/20xxx/21xxx/L1xxxx系列Cortex-M3编程手册-英文版 |
SD卡相关资料——最新版本 | 有关SD卡的一些资料可以从这里下载 |
SD卡相关资料——历史版本 | 有关SD卡的一些历史版本资料可以从这里下载,比如后边看的SD卡2.0协议 |
SD 2.0 协议标准完整版 | 这是一篇关于SD卡2.0协议的中文文档,还是比较有参考价值的,可以一看 |
这里的实例都是通过STM32CubeMX软件进行配置。
一、存储器到存储器
FLASH to SRAM,把内部FLASH的数据传输到内部的SRAM。在这里相当于将FLASH当做外设,将SRAM作为存储器,将数据从外设传输到存储器 。一般步骤如下:
(1)使能 DMA 时钟;
(2)配置 DMA 数据参数;
(3)使能 DMA,进行传输;
(4)等待传输完成,并对源数据和目标地址数据进行比较。
1. STM32CubeMX配置
①、选择DMA外设;
②、点击【Add】添加一个DMA请求,注意我们只能选择已经开启的外设;
③、配置DMA模式,对于MEMTOMEM来说我们只能选择Normal模式;
④、地址增量配置,勾选表示地址递增,不勾选表示地址不变;
⑤、数据宽度,看我们要传输的数据宽度了,可以选择字节、半字、字,分别代表8位、16位、32位。
2. 变量定义
1 | /* 定义aSRC_Const_Buffer数组作为DMA传输数据源 const关键字将aSRC_Const_Buffer数组变量定义为常量类型 */ |
我们需要定义一个静态的源数据,存放在内部 FLASH,然后使用 DMA 传输把源数据拷贝到目标地址上(内部 SRAM),最后对比源数据和目标地址的数据,看看是否传输准确。
3. 代码分析
3.1 DMA初始化
我们按照上图配置完成后,会生成下边的代码:
1 | DMA_HandleTypeDef hdma_memtomem_dma1_channel1; |
3.2 比较数据
1 | /** |
3.3 启动并等待DMA传输
1 | void dma_mem2mem_start(void) |
3.4 测试函数
1 | void dma_mem2mem_test(void) |
二、 存储器到外设
SRAM to 串口,同时LED灯闪烁,演示DMA传数据不需要占用CPU。 一般步骤如下:
(1)配置 USART 通信功能;
(2)设置串口 DMA 工作参数;
(3)使能 DMA;
(4)DMA 传输同时 CPU 可以运行其他任务。
1. STM32CubeMX配置
这里只写DMA的配置,串口和LED的可以根据以前的笔记来。
①、选择USART外设或者选择DMA外设,都可以进入DMA的配置界面;
②、点击【Add】添加一个DMA请求,注意我们只能选择已经开启的外设,我们这里选择USART1_TX,通道的话软件会主动帮我们选好;
③、配置DMA模式,对于MEMTOMEM来说我们只能选择Normal模式;
④、地址增量配置,勾选表示地址递增,不勾选表示地址不变,这里的外设地址不能勾选,因为串口的寄存器只有一个DR,根本没必要递增,软件中也直接无法勾选
⑤、数据宽度,看我们要传输的数据宽度了,可以选择字节、半字、字,分别代表8位、16位、32位,在这里我们需要选择8位,因为我们串口的数据寄存器就是8位有效的。
2. 变量定义
1 |
|
3. 代码分析
3.1 DMA初始化
1 | void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) |
因为数据是从存储器到串口,所以设置存储器为源地址,串口的数据寄存器为目标地址,要发送的数据有很多且都先存储在存储器中,则存储器地址指针递增,串口数据寄存器只有一个,则外设地址地址不变,两边数据单位设置成一致,传输模式可选一次或者循环传输,只有一个 DMA请求,优先级随便设,最后调用 HAL_DMA_Init 函数把这些参数写到 DMA 的寄存器中,然后使能 DMA 开始传输。
为演示DMA持续运行而CPU还能处理其它事情,持续使用DMA发送数据,量非常大,长时间运行可能会导致电脑端串口调试助手会卡死,鼠标乱飞的情况,所以这里将DMA配置中的循环模式改为单次模式。
3.2 中断处理函数
这里在软件中配置的时候好像自动开启DMA中断,中断的优先级我们可以在NVIC中进行设置:
1 | // 初始化函数 |
中断回调函数是需要在初始化的时候进行注册的,没有注册的话就不会被调用啦,这里我们暂时不用,就没有注册了。
3.3 启动传输
1 | /* USART1 向 DMA发出TX请求 */ |
HAL_UART_Transmit_DMA 函数用于启动 USART 的 DMA 传输,第一个参数为外设的初始化句柄而非dma初始化使用的句柄。。只需要指定源数据地址及长度,运行该函数后 USART 的 DMA 发送传输就开始了,根据配置它会通过 USART 循环发送数据。DMA 传输过程是不占用 CPU 资源的,可以一边传输一次运行其他任务。
3.4 测试函数
这个我们直接写到main函数中
1 |
|
4. 实验现象
这里描述一下现象,若是没有DMA的话,我们将上边的 60000 个 A 发送到串口需要占用大量的时间,此时我们需要等待传输完成才能看到LED1闪烁,但是有了DMA之后,只会在进入循环前开启DMA,然后LED1就能立刻进入闪烁状态,此时串口也可以看到有数据发送过来。
可以看到下方有60020个数据,这是因为我还加了个printf打印了一句话,这就说明我们发往串口的数据全部被打印出来了,而且注意观察的话,会发现LED1同时在闪烁,并不受串口数据传输的影响。