STM32实验DMA数据搬运小助手

本次实验做的是将一个数组的内容利用DMA数据搬运小助手搬运到另外一个数组中去。

最后的实验结果:

可以看到第四行的数据就都不是0了,成功搬运了过来。

DMA实现搬运的步骤其实不是很复杂,复杂的是结构体参数:

整个步骤为:

第一步:RCC开启DMA的时钟

第二步:调用DMA_Init,初始化各个参数 (包括外设和存储器的起始地址,数据宽度,地址是否自增,方向,传输计数器,是否需要自动重装,选择触发源,通道优先级)

第三步:调用DMA_CMD,通道使能(要在对应的外设调用XXX_DMACmd开启一下触发信号的输出,如果需要DMA的中断,就调用DMA_ITConfig,开启中断输出,再在NVIC里,配置中断通道,最后写中断函数就行了)

下面介绍一下DMA相关的库函数:

void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);

//恢复缺省配置

void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct); //DMA初始化

void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);

//DMA结构体初始化

void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);

//DMA使能/失能

void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);

//中断输出使能/失能

void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); //DMA设置当前数据寄存器

uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);

//DMA获取当前数据寄存器的值

FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);  //获取标志位状态 void DMA_ClearFlag(uint32_t DMAy_FLAG);  //清除状态标志位

ITStatus DMA_GetITStatus(uint32_t DMAy_IT);  //获取中断标志位状态 void DMA_ClearITPendingBit(uint32_t DMAy_IT);//清除中断标志位状态

下面是MyDMA.c的文件:

#include "stm32f10x.h"                  // Device headervoid MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{//第一步:RCC开启DMA的时钟RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//第二步:调用DMA_Init,初始化各个参数(包括外设和存储器的起始地址,数据宽度,地址是否自增,方向,传输计数器,是否需要自动重装,选择触发源,通道优先级)DMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_PeripheralBaseAddr = AddrA;DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;   //数据宽度,按字节的宽度搬运DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable;    //启用地址++自增// 以上是外设站点(数据来源)的起始地址、数据宽度、是否自增。DMA_InitStruct.DMA_MemoryBaseAddr = AddrB;DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;  //数据宽度,按字节的宽度粘贴DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;       //启用地址++自增//以上3条是存储器(目的地)的起始地址、数据宽度、是否自增。DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;    //传输方向DMA_InitStruct.DMA_BufferSize = Size;  //缓存区大小,其实就是传输计数器   取用传进来的参数DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;   //传输模式,其实就是是否启用自动重装     不自动重装DMA_InitStruct.DMA_M2M = DMA_M2M_Enable;   //选择是硬件触发还是软件触发    软件触发DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;   // 优先级    选择中等优先级DMA_Init(DMA1_Channel1, &DMA_InitStruct);  //第一个参数选择了是哪个DMA到哪个DMA通道,第二个参数结构体//第三步:调用DMA_CMD,通道使能(要在对应的外设调用XXX_DMACmd开启一下触发信号的输出,如果需要DMA的中断,就调用DMA_ITConfig,开启中断输出,再在NVIC里,配置中断通道,最后写中断函数就行了)DMA_Cmd(DMA1_Channel1, ENABLE);
}

下面是MyDMA.h文件:

#ifndef __MYDMA_H
#define __MYDMA_Hvoid MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size);#endif

下面是main.c文件:

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "MyDMA.h"uint8_t dataA[]={0x01, 0x02, 0x03, 0x04};
uint8_t dataB[]={0,0,0,0};int main(void)
{OLED_Init();       //oled  屏幕初始化OLED_ShowHexNum(1,1, dataA[0], 2);OLED_ShowHexNum(1,4, dataA[1], 2);OLED_ShowHexNum(1,7, dataA[2], 2);OLED_ShowHexNum(1,10, dataA[3], 2);OLED_ShowHexNum(2,1, dataB[0], 2);OLED_ShowHexNum(2,4, dataB[1], 2);OLED_ShowHexNum(2,7, dataB[2], 2);OLED_ShowHexNum(2,10, dataB[3], 2);MyDMA_Init((uint32_t)dataA, (uint32_t)dataB, 4);OLED_ShowHexNum(3,1, dataA[0], 2);OLED_ShowHexNum(3,4, dataA[1], 2);OLED_ShowHexNum(3,7, dataA[2], 2);OLED_ShowHexNum(3,10, dataA[3], 2);OLED_ShowHexNum(4,1, dataB[0], 2);OLED_ShowHexNum(4,4, dataB[1], 2);OLED_ShowHexNum(4,7, dataB[2], 2);OLED_ShowHexNum(4,10, dataB[3], 2);while(1){}
}

这样就实现了最简单的DMA数据搬运的小功能了。看似没有什么用,其实这功能是在硬件上自动完成的,可以在不浪费软件资源的前提下,把外设上的数据搬运到内存中来,软件就能直接用了,还是非常的方便的。

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

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

相关文章

三级等保技术建议书

1信息系统详细设计方案 1.1安全建设需求分析 1.1.1网络结构安全 1.1.2边界安全风险与需求分析 1.1.3运维风险需求分析 1.1.4关键服务器管理风险分析 1.1.5关键服务器用户操作管理风险分析 1.1.6数据库敏感数据运维风险分析 1.1.7“人机”运维操作行为风险综合分析 1.2…

JEDI:变形下分子和周期系统应变分析的通用代码

JEDI:变形下分子和周期系统应变分析的通用代码 拉伸或压缩会引起材料显着的能量、几何和光谱变化。为了在机械或压致变色材料、自修复聚合物和其他机械响应装置的设计中充分利用这些效应,必须详细了解材料中机械应变的分布。在过去的十年中,能…

PSCA系统控制集成之复位层次结构

PPU 提供以下对复位控制的支持。 • 复位信号Reset signals:PPU 提供冷复位和热复位输出信号。PPU 还为实现部分保留的电源域管理提供了额外的热复位输出信号。 • 电源模式控制Power mode control:PPU 硬件适当地管理每个支持的电源模式转换的复位信号…

代码随想录算法训练营第day29|491.递增子序列、 46.全排列、 47.全排列 II

目录 491.递增子序列 46.全排列 47.全排列 II 491.递增子序列 力扣题目链接 给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7]输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7,…

《前端系列》之前端学习路线

目录 1 前言2 前端学习路线2.1 入门阶段2.1.1 HTML2.1.2 CSS2.1.3 JavaScript2.1.4 网络基础 2.2 基础阶段2.2.1 前端框架2.2.2 深入JavaScript2.2.3 ES62.2.4 工程化知识 2.3 进阶阶段2.3.1 CSS2.3.2 Javascript2.3.3 单元测试2.3.4 性能优化 3 总结 1 前言 在技术更新迭代发…

Android Studio:你的主机中的软件终止了一个已建立的连接

我不喜欢等人也不喜欢被别人等——赤砂之蝎 一、提出问题 二、分析问题 搜索网上的教程尝试解决 1、任务管理器结束adb进程无用 2、电脑没有开启热点排除热点问题 3、校园网切换到热点 4、项目重新解压打开 5、更换国内镜像源 上述方法全部无法解决问题 分析问题原因在于之前A…

c语言文件操作(中)

目录 1. 文件的顺序读写1.1 顺序读写函数1.2 顺序读写函数的原型和介绍 结语 1. 文件的顺序读写 1.1 顺序读写函数 函数名功能适用于fgetc字符输入函数所有输出流fputc字符输出函数所有输出流fgets文本行输入函数所有输出流fputs文本行输出函数所有输出流fscanf格式化输入函数…

yocto系列之针对从git仓库获取源代码编写recipe

回顾 针对借助yocto构建linux 镜像我们已经讲述了7部分, 简单回顾如下: Yocto: 第1部分 - yocto系列之yocto是个什么东东 https://mp.csdn.net/mp_blog/creation/editor/136742286 Yocto: 第2部分 - yocto系列之配置ubuntu主机 https://mp.csdn.net…

yolov8训练自己的数据集以及权重转化为.engine格式(超详细)

文章目录 1 获取.mp42 pycharm切换文件2 .mp4文件提取帧图片3 帧图片筛选规则4 图片重命名5 图片名指定长度6 labelme使用规则7 标注人体关节点8 检测关键点标注的准确性9 json文件转化成txt文件10 划分数据集、验证集2 pycharm切换文件11 调整训练参数12 .pt文件转化.onnx13 .…

最新WordPress网址导航设计师主题风格网站源码

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 最新WordPress精品网址导航主题整站源码WAP端修复tab标签ajax加载模式会显示未审核的网址的bug小屏幕热搜采用水平滚动优化子主题支持添加文章分页 二、效果展示 1.部分代码 代码如…

【React】Vite创建React+TS项目

前提条件 有node环境,且node版本>18.0.0 创建项目 npm create vitelatest1.起项目名 2.选择框架 3.选择语言 TypeScript SWC 是指 Vite 使用 SWC(Speedy Web Compiler)作为 TypeScript 的编译器。 SWC 是一个针对 JavaScript 和 Ty…

操作系统知识-存储管理+文件管理管理-嵌入式系统设计师备考笔记

0、前言 本专栏为个人备考软考嵌入式系统设计师的复习笔记,未经本人许可,请勿转载,如发现本笔记内容的错误还望各位不吝赐教(笔记内容可能有误怕产生错误引导)。 本章的主要内容见下图: 1、存储管理&#…