5、DMA Demo(STM32F407)

DMA简介

DMA 全称Direct Memory Access,即直接存储器访问。 DMA传输将数据从一个地址空间复制到另一个地址空间。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。 DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。

作用:为CPU减负。

DMA原理

STM32F4最多有2个DMA控制器,2个DMA控制器总共有16个数据流(每个控制器8个)。每个DMA控制器都用于管理一个或者多个外设的存储器访问请求。每个数据流总共可以有多达8个通道(或请求),每个通道都有一个仲裁器,用于处理DMA请求间的优先级。

DMA框图

 

DMA配置参数

  1.  通道
  2. 优先级
  3. 数据传输方向
  4. 存储器/外设 数据宽度
  5. 存储器/外设 地址是否增量
  6. 循环模式
  7. 数据传输量

程序源码

dma.h

#ifndef __DMA_H
#define	__DMA_H	   
#include "sys.h"void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr);//配置DMAx_CHx
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr);	//使能一次DMA传输		   
#endif

dma.c

#include "dma.h"
#include "delay.h"// DMAx的各通道配置
// 这里的传输形式是固定的,这点要根据不同的情况来修改
// 从存储器->外设模式/8位数据宽度/存储器增量模式
// DMA_Streamx:DMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
// chx:DMA通道选择,@ref DMA_channel DMA_Channel_0~DMA_Channel_7
// par:外设地址
// mar:存储器地址
// ndtr:数据传输量
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx, u32 chx, u32 par, u32 mar, u16 ndtr)
{DMA_InitTypeDef DMA_InitStructure;if ((u32)DMA_Streamx > (u32)DMA2) // 得到当前stream是属于DMA2还是DMA1{RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); // DMA2时钟使能}else{RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); // DMA1时钟使能}DMA_DeInit(DMA_Streamx);while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){} // 等待DMA可配置/* 配置 DMA Stream */DMA_InitStructure.DMA_Channel = chx;                                    // 通道选择DMA_InitStructure.DMA_PeripheralBaseAddr = par;                         // DMA外设地址DMA_InitStructure.DMA_Memory0BaseAddr = mar;                            // DMA 存储器0地址DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                 // 存储器到外设模式DMA_InitStructure.DMA_BufferSize = ndtr;                                // 数据传输量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_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;         // 存储器突发单次传输DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // 外设突发单次传输DMA_Init(DMA_Streamx, &DMA_InitStructure);                          // 初始化DMA Stream
}
// 开启一次DMA传输
// DMA_Streamx:DMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
// ndtr:数据传输量
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx, u16 ndtr)
{DMA_Cmd(DMA_Streamx, DISABLE); // 关闭DMA传输while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){} // 确保DMA可以被设置DMA_SetCurrDataCounter(DMA_Streamx, ndtr); // 数据传输量DMA_Cmd(DMA_Streamx, ENABLE); // 开启DMA传输
}

main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "dma.h"#define SEND_BUF_SIZE 8200 // 发送数据长度,最好等于sizeof(TEXT_TO_SEND)+2的整数倍.u8 SendBuff[SEND_BUF_SIZE]; // 发送数据缓冲区
const u8 TEXT_TO_SEND[] = {"ALIENTEK Explorer STM32F4 DMA 串口实验"};int main(void)
{u16 i;u8 t = 0;u8 j, mask = 0;float pro = 0;									// 进度NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置系统中断优先级分组2delay_init(168);								// 初始化延时函数uart_init(115200);								// 初始化串口波特率为115200LED_Init();										// 初始化LEDLCD_Init();										// LCD初始化KEY_Init();										// 按键初始化// 配置DMA,使用DMA2的第7个数据流和第4个通道,将USART1的数据寄存器作为外设,SendBuff作为存储器,传输长度为SEND_BUF_SIZEMYDMA_Config(DMA2_Stream7, DMA_Channel_4, (u32)&USART1->DR, (u32)SendBuff, SEND_BUF_SIZE); // DMA2,STEAM7,CH4,外设为串口1,存储器为SendBuff,长度为:SEND_BUF_SIZE.POINT_COLOR = RED;LCD_ShowString(30, 50, 200, 16, 16, "Explorer STM32F4");LCD_ShowString(30, 70, 200, 16, 16, "DMA TEST");LCD_ShowString(30, 90, 200, 16, 16, "ATOM@ALIENTEK");LCD_ShowString(30, 110, 200, 16, 16, "2014/5/6");LCD_ShowString(30, 130, 200, 16, 16, "KEY0:Start");POINT_COLOR = BLUE; // 设置字体为蓝色// 显示提示信息j = sizeof(TEXT_TO_SEND);			// 获取TEXT_TO_SEND字符串的长度,并赋值给变量jfor (i = 0; i < SEND_BUF_SIZE; i++) // 循环从0到SEND_BUF_SIZE-1,填充SendBuff数组{if (t >= j) // 加入换行符{if (mask){SendBuff[i] = 0x0a; // 插入换行符t = 0;}else{SendBuff[i] = 0x0d; // 插入回车符mask++;}}else // 复制TEXT_TO_SEND语句{mask = 0;SendBuff[i] = TEXT_TO_SEND[t];t++;}}POINT_COLOR = BLUE; // 设置字体为蓝色i = 0;while (1){t = KEY_Scan(0);	// 清除按键标记if (t == KEY0_PRES) // KEY0按下{printf("\r\nDMA DATA:\r\n");LCD_ShowString(30, 150, 200, 16, 16, "Start Transimit....");LCD_ShowString(30, 170, 200, 16, 16, "   %");  // 显示百分号USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); // 使能串口1的DMA发送MYDMA_Enable(DMA2_Stream7, SEND_BUF_SIZE);	   // 启动一次DMA传输// 等待DMA传输完成,此时我们来做另外一些事,点灯// 实际应用中,传输数据期间,可以执行另外的任务while (1){// 通过DMA_GetCurrDataCounter函数获取当前还剩余多少个数据未传输,然后计算传输的百分比if (DMA_GetFlagStatus(DMA2_Stream7, DMA_FLAG_TCIF7) != RESET) // 等待DMA2_Steam7传输完成{DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7); // 清除DMA2_Steam7传输完成标志break;}pro = DMA_GetCurrDataCounter(DMA2_Stream7); // 得到当前还剩余多少个数据pro = 1 - pro / SEND_BUF_SIZE;				// 得到百分比pro *= 100;									// 扩大100倍LCD_ShowNum(30, 170, pro, 3, 16);}LCD_ShowNum(30, 170, 100, 3, 16);							 // 显示100%LCD_ShowString(30, 150, 200, 16, 16, "Transimit Finished!"); // 提示传送完成}i++;delay_ms(10);if (i == 20){LED0 = !LED0; // 提示系统正在运行i = 0;}}
}

实验效果

说明:

串口首先打印TFT屏的驱动IC(按下RESET键复位)

按下KEY0后,TFT屏显示“Transimit Finished!”并显示传输进度,串口重复打印“ALIENTEK Explorer STM32F4 DMA 串口实验”直至达到SEND_BUF_SIZE的值

DMA实验效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/235139.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

超详细!Opencv人脸识别!附源码!

一、新建环境 注意&#xff01;&#xff01;确定后需要关闭项目&#xff0c;重新打开&#xff0c;终端的环境才会变化&#xff01;&#xff01; 二、下载安装包&#xff08;只需要3个即可&#xff09; 1. 下载dlib包 pip install dlib-19.19.0-cp38-cp38-win_amd64.whl.whl …

【数据清洗 | 数据规约】数据类别型数据 编码最佳实践,确定不来看看?

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

030 - STM32学习笔记 - ADC(四) 独立模式多通道DMA采集

030 - STM32学习笔记 - ADC&#xff08;四&#xff09; 独立模式多通道DMA采集 中断模式和DMA模式进行单通道模拟量采集&#xff0c;这节继续学习独立模式多通道DMA采集&#xff0c;使用到的引脚有之前使用的PC3&#xff08;电位器&#xff09;&#xff0c;PA4&#xff08;光敏…

Linux下删除当前目录下的所有目录

Linux下删除当前目录下的所有目录 Linux下删除当前目录下的所有目录&#xff0c;可以使用命令&#xff1a;rm -rf ./* rm -rf ./*可以得知rm -rf ./命令是删除当前目录下的所有文件和文件夹&#xff0c;但不会删除根目录下的文件。其中&#xff0c;".“代表当前目录&…

Python中的sys模块详解

1. 简介 sys模块是Python标准库中的一个内置模块&#xff0c;提供了与Python解释器和运行环境相关的功能。它包含了一些与系统操作和交互相关的函数和变量&#xff0c;可以用于获取命令行参数、控制程序的执行、管理模块和包、处理异常等。 2. 常用函数和变量 2.1 命令行参数…

动手学深度学习(六)---权重衰退

文章目录 一、理论知识二、代码实现【相关总结】 主要解决过拟合 一、理论知识 1、使用均方范数作为硬性限制&#xff08;不常用&#xff09; 通过限制参数值的选择范围来控制模型容量 通常不限制偏移b 小的意味着更强的正则项 使用均方范数作为柔性限制 对于每个都可以找到使…

「Bomkus 博士的试炼」排行榜规则更新

亲爱的玩家们 为了回应我们从社区收到的宝贵反馈&#xff0c;我们希望与大家分享我们为防止在「Bomkus 博士的试炼」排行榜中作弊而采取的措施的最新进展&#xff0c;并就这一主题提供更多说明。 除了在活动开始前采取的反作弊措施外&#xff0c;我们还根据观察到的和报告的行为…

程序员也需要养生——程序员睡不好,重视一下你的情绪吧

程序员也需要养生——程序员睡不好&#xff0c;重视一下你的情绪吧 睡眠是一个复杂的系统工程&#xff0c;可以促进生长发育&#xff0c;修复受损的组织。促进大脑细胞的修复等等。在情绪的失调会影响到我们的睡眠状况。 一、心情差&#xff0c;压力大&#xff0c;睡不好跟这…

基于SpringBoot的在线视频教育平台的设计与实现

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于在线视频教育平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了在线视频教育平台&#xff0c;它彻底改变了过…

Pycharm新手开发指南

文章目录 前言一、常用功能介绍二、常用高效pycharm使用方法关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 前言…

Django二转Day03 04

0 cbv执行流程&#xff0c;self问题 path(index/, Myview.as_view()),Myview.as_view() 实例化后返回 变成return Myview.dispatch(request, *args, **kwargs)但是视图函数Myview中没有 dispatch 方法 所以去 父类View中寻找return View.dispatch(request, *args, **kwargs)调用…

XXL-Job详解(二):安装部署

目录 前言环境下载项目调度中心部署执行器部署 前言 看该文章之前&#xff0c;最好看一下之前的文章&#xff0c;比较方便我们理解 XXL-Job详解&#xff08;一&#xff09;&#xff1a;组件架构 环境 Maven3 Jdk1.8 Mysql5.7 下载项目 源码仓库地址链接: https://github.…