STM32入门学习之DMA

1.直接存储访问DMA(Direct Memory Access):DMA传输不需要CPU的参与,直接在内存和I/O设备间开辟了一条新的数据传输通道,不仅提高数据传输的速率,还因为不需要CPU的干预,从而提高了CPU的利用率。(注:文中的资料参考于正点原子)

STM32最多有2个DMA通道(只有大容量的STM32才有DMA2)。DMA1有7个通道,DMA2有5个通道,每个通道用来管理一个或者多个外设对存储器的访问请求。还有一个通道用来仲裁协调各个DMA请求的优先级。STM32的DMA特性如下:

STM32F103RCT6的DMA1通道表如下:

每个通道同一时刻只能有一个外设使用DMA进行数据传输。比如DMA1的通道1中有三个外设(ADC1、TIM2_CH3、TIM4_CH1),同一时刻只能使用其中的一个外设进行DMA数据传输。本文是利用USART1进行数据传输,由表可知,需要使用的DMA1的通道4。

DMA配置的基本步骤:

(1)使能DMA的时钟,并配置DMA的初始结构体。

(2)开启DMA。

(3)开启对应外设的DMA数据传输。

2.DMA相关的寄存器:

(1)DMA中断状态寄存器(DMA_ISR):当开启DMA_ISR的这些中断后,产生中断触发条件时会跳转到相应的中断服务函数。即使没有开启这些中断,也可以通过这些位来判断当前DMA的传输状态。比如可以用TCIFx来判断DMA是否传输完成。此寄存器为只读寄存器,所以当被置位之后,需要通过其他的操作来清除。

(2)DMA中断标志清除寄存器(DMA_IFCR):DMA_IFCR 的各位就是用来清除 DMA_ISR 的对应位的,通过写 0 清除。在 DMA_ISR 被置位后,必须通过向该位寄存器对应的位写入 0 来清除。

(3)DMA的其他寄存器:

3.DMA的初始化配置:

DMA的初始化函数为:void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)。参数1是DMA的通道号,参数2是一个结构体,其定义如下:

如下为DMA的一个配置实列:

初始化DMA后,然后需要使能外设的DMA功能:

最后,再使能DMA传输通道:

当需要查下DMA的状态时,可使用如下的函数:

4.代码:本文只展示DMA和main部分的代码,如果需要完整的代码,可以结合前面的文章来获取。

(1)dma.h:

#ifndef __DMA_H
#define __DMA_H#include "stm32f10x.h"//DMA_CHx:DMAͨµÀCHx
//cpar:ÍâÉèµØÖ·
//cmar:´æ´¢Æ÷µØÖ·
//cndtr:Êý¾Ý´«ÊäÁ¿ 
void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr );#endif

(2)dma.c:

#include "dma.h"DMA_InitTypeDef DMA_InitStructure;
u16 DMA1_LEN;											//DMA´«ÊäµÄÊý¾Ý³¤¶Èvoid MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr )
{//1.ʹÄÜʱÖÓ£ºRCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//2.ÅäÖÃDMAµÄÏà¹Ø¼Ä´æÆ÷£ºDMA_DeInit(DMA_CHx);   			//½«DMAµÄͨµÀ1¼Ä´æÆ÷ÖØÉèΪȱʡֵDMA1_LEN = cndtr;DMA_InitStructure.DMA_PeripheralBaseAddr = cpar;		//ÍâÉè»ùµØÖ·DMA_InitStructure.DMA_MemoryBaseAddr = cmar;			//´æ·ÅDMAÊý¾ÝµÄµØÖ·DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//DMA´«Êä·½ÏòDMA_InitStructure.DMA_BufferSize = cndtr;		//Ò»´Î´«ÊäµÄÊý¾ÝÁ¿DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;	//ÍâÉèµØÖ·ÊÇ·ñµÝÔöDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;			//Êý¾Ý´«ÊäʱÄÚ´æµØÖ·ÊÇ·ñµÝÔöDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;	//ÍâÉèÊý¾Ý¿í¶ÈDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;			//ÄÚ´æÊý¾Ý¿í¶ÈDMA_InitStructure.DMA_Mode = DMA_Mode_Normal;						//DMA¹¤×÷ģʽDMA_InitStructure.DMA_Priority = DMA_Priority_Medium;				//DMAÓÅÏȼ¶DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;					//ÉèÖÃÊÇ·ñÊÇ´æ´¢Æ÷µ½´æ´¢Æ÷µÄ´«ÊäģʽDMA_Init(DMA_CHx,&DMA_InitStructure);					//½«ÉÏÊöÅäÖÃÐÅϢдÈëDMAµÄ¼Ä´æÆ÷ÖÐ//¿ªÆôDMA£ºDMA_Cmd(DMA_CHx,DISABLE);													//Ïȸ´Î»Ò»ÏÂDMA_SetCurrDataCounter(DMA1_Channel4,DMA1_LEN);		//ÉèÖÃDMAͨµÀµÄDMA»º´æ´óСDMA_Cmd(DMA_CHx,ENABLE);
}

(3) main.c:

#include "led.h"
#include "usart.h"
#include "delay.h"
#include "lcd.h"
#include "dma.h"
#include "key.h"const u8 TEXT_TO_SEND[]={"hello world,there are many good things,so we should hold on,hold on"};
#define TEXT_LENGTH sizeof(TEXT_TO_SEND) - 1				//-1ÊDz»°üº¬½áÊø·û
u8 SendBuff[(TEXT_LENGTH+2)*100];int main(void)
{float pro = 0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);LED_Init();LCD_Init();usart_init(9600);KEY_Init();USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);			//¿ªÆô´®¿ÚµÄDMA//DMA1ͨµÀ4,ÍâÉèΪ´®¿Ú1,´æ´¢Æ÷ΪSendBuff,³¤(TEXT_LENTH+2)*100MYDMA_Config(DMA1_Channel4,(u32)&USART1->DR,(u32)SendBuff,(TEXT_LENGTH+2)*100);GPIO_SetBits(GPIOA,GPIO_Pin_8);GPIO_ResetBits(GPIOD,GPIO_Pin_2);while(1){//printf("test\r\n");POINT_COLOR=RED;	  if(KEY_2){LCD_ShowString(60,150,200,16,16,"Start Transimit....");LCD_ShowString(30,40,200,24,24,"hello world");LCD_ShowString(60,170,200,16,16,"   %");//ÏÔʾ°Ù·ÖºÅwhile(1){if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=RESET)//µÈ´ýͨµÀ4´«ÊäÍê³É{DMA_ClearFlag(DMA1_FLAG_TC4);//Çå³ýͨµÀ4´«ÊäÍê³É±êÖ¾break; }pro=DMA_GetCurrDataCounter(DMA1_Channel4);//µÃµ½µ±Ç°»¹Ê£Óà¶àÉÙ¸öÊý¾Ýpro=1-pro/((TEXT_LENGTH+2)*100);//µÃµ½°Ù·Ö±È	  pro*=100;      //À©´ó100±¶LCD_ShowNum(60,170,pro,3,16);	  }LCD_ShowNum(60,170,100,3,16);//ÏÔʾ100%	  LCD_ShowString(60,150,200,16,16,"Transimit Finished!");//Ìáʾ´«ËÍÍê³Édelay_ms(1000);}}
}

5.运行结果:

6.总结:

本文介绍了DMA使用方法,并实验了串口的DMA功能。使用DMA的基本步骤是:

(1)开启时钟,并初始化DMA

(2)配置初始化的结构体信息,调用函数进行初始化

(3)开启DMA数据传输,并使能外设的MDA功能。

本文中理论部分介绍较多,下一节会利用DNM和ADC来进行实验。

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

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

相关文章

小红书API接口封装 | 根据笔记链接采集笔记详情,含正文内容、发布时间、转评赞藏等

一、背景介绍 1.1 爬取目标 用python开发的爬虫采集软件,可自动按笔记链接抓取笔记的详情数据。 为什么有了源码还开发界面软件呢?方便不懂编程代码的小白用户使用,无需安装python,无需改代码,双击打开即用&#xf…

零基础学习数据库SQL语句之操作表中数据的DML语句

我们的数据库是根据页面原型和相关需求完成相关开发的 在表中添加数据 删除数据 修改数据 添加数据 页面模型 当点击保存的时候就能将表单数据提交到服务端 服务端将数据添加到数据库 我们要用insert语句 将数据添加到数据库中 代码演示 CREATE DATABASE Dduo; USE Dduo…

在2-3-4树上实现连接与分裂操作的算法与实现

在2-3-4树上实现连接与分裂操作的算法与实现 引言1. 维护2-3-4树结点的高度属性伪代码示例 2. 实现连接操作伪代码示例 3. 证明简单路径p的划分性质4. 实现分裂操作伪代码示例 C代码示例结论 引言 2-3-4树是一种平衡搜索树,它保证了树的高度被有效控制,…

git学习指南

文章目录 一.版本控制1.认识版本控制2.版本控制功能3.集中式版本控制4.分布式版本控制 二.Git的环境安装搭建1.Git的安装2.Git配置分类3.Git配置选项 三.Git初始化本地仓库1. git init/git clone-获取Git仓库2. 本地仓库文件的划分3. git status-检测文件的状态4. git add-文件…

【Redis面试题】Redis常见的一些高频面试题

分享几个Redis入门级常见面试过程中遇到的题目! 你项目中哪里使用到了redis?可以讲一讲嘛 这个题目无论是大公司还是小公司都经常考,建议大家根据自己的项目做总结 redis的几种基础数据结构 redis为什么那么快? 1.基于内存实现:我们都知道内存读写是…

【neteq】tgcall的调用、neteq的创建及接收侧统计

G:\CDN\P2P-DEV\Libraries\tg_owt\src\call\call.cc基本是按照原生webrtc的来的:G:\CDN\P2P-DEV\tdesktop-offical\Telegram\ThirdParty\tgcalls\tgcalls\group\GroupInstanceCustomImpl.cpptg对neteq的使用 worker 线程创建call Call的config需要neteqfactory Call::CreateAu…

STM32单片机实战开发笔记-EXIT外部中断检测

嵌入式单片机开发实战例程合集: 链接:https://pan.baidu.com/s/11av8rV45dtHO0EHf8e_Q0Q?pwd28ab 提取码:28ab EXIT模块测试 功能描述 外部中断/事件控制器由19个产生事件/中断要求的边沿检测器组成。每个输入线可以独立地配置输入类型&a…

【C++】学习笔记——string_5

文章目录 六、string类7. string类的模拟实现8. string类的模拟实现的完整代码string.h头文件test.c源文件 9. string收尾写时拷贝 未完待续 六、string类 7. string类的模拟实现 我们之前讲了实现 insert ,但是那个插入函数仅仅是在 pos 位置插入一个字符而且&am…

二、nodejs连接数据库实现登录功能

// 数据库下载可以用这个 DBeaver安装与使用教程(超详细安装与使用教程),好用免费的数据库管理工具_dbeaver使用教程-CSDN博客 模块化 (1)新建一个叫Dao的文件夹,存接数据库代码 // 参考数据库 &#xf…

自动驾驶-第02课软件环境基础(ROSCMake)

1. 什么是ros 2. 为什么使用ros 3. ROS通信 3.1 Catkin编译系统

prometheus的安装与部署及其有点

一、Prometheus 的优点 1、非常少的外部依赖,安装使用超简单; 2、已经有非常多的系统集成 例如:docker HAProxy Nginx JMX等等; 3、服务自动化发现; 4、直接集成到代码; 5、设计思想是按照分布式、微服…

Flutter笔记:Widgets Easier组件库(10)快速处理承若型对话

Flutter笔记 使用Widgets Easier组件库快速处理承若型对话 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://…

小程序账号设置以及request请求的封装

一般开发在小程序时,都会有测试版和正式版,这样在开发时会比较方便。 在开发时。产品经理都会给到测试账号和正式账号,后端给的接口也都会有测试环境用到的接口和正式环境用到的接口。 这里讲一讲我这边如何去做的。 1.在更目录随便命名一…

一机游领航旅游智慧化浪潮:借助前沿智能设备,革新旅游服务效率,构建高效便捷、生态友好的旅游服务新纪元,开启智慧旅游新时代

目录 一、引言 二、一机游的定义与特点 (一)一机游的定义 (二)一机游的特点 三、智能设备在旅游服务中的应用 (一)旅游前的信息查询与预订支付 (二)旅游中的导航导览与互动体…

MATLAB中功率谱密度计算pwelch函数使用详解

MATLAB中功率谱密度计算pwelch函数使用详解 目录 前言 一、pwelch函数简介 二、pwelch函数参数说明 三、pxx pwelch(x)示例 四、[pxx,f]pwelch(x,window,noverlap,nfft,fs)示例 四、[pxx,f] pwelch(x,window,noverlap,nfft,fs,freqrange,spectrumtype)示例 五、多通道功…

Springboot(SSM)项目实现数据脱敏

目录 一、引入hutool的依赖 二、sql脚本 三、自定义注解代码 3.1 自定义注解 3.2 自定义一个枚举,用于定义脱敏的类型 3.3 序列化 四、使用脱敏注解 4.1 Person.java 4.2 controller 4.3 dao 五、源代码参考 一、引入hutool的依赖 <dependency><groupId>…

FIFO Generate IP核使用——Native读写接口信号详解

Native FIFO接口信号是用于FIFO IP核与外部电路进行通信的信号。当FIFO支持独立的写和读时钟时&#xff0c;这些信号可以包括标准端口和可选端口。 1 当FIFO具有独立时钟时的接口信号 当FIFO具有独立的时钟时&#xff0c;其接口信号会相应地有所变化。特别是关于复位信号rst…

计算机等级考试2级(Python)知识点整理

计算机等级考试2级&#xff08;Python&#xff09;知识点整理 1.基础知识点&#xff08;记忆、理解&#xff09; 第1讲Python概述 01. 源代码 02. 目标代码 03. 编译和解释 04. 程序的基本编写方法 第2讲 Python语言基础&#xff08;一&#xff09; 01. 用缩进表示代码…

[数据结构]——非比较排序—计数排序

该篇文章 所涉及代码收录仓库&#xff1a;登录 - Gitee.com 目录 1.非比较排序——计数排序 2.最终实现 1.解析 2.以int a[] { 1,3,9,1,5,1,2,3,-5,-5,-2 };为例&#xff0c;手撕分析 3.代码实现 4.计数排序具有以下主要特性&#xff1a; 1.非比较排序——计数排序 思想…

Linux IP Forwarding路由转发实验

linux 路由转发功能 Linux 操作系统具备路由转发功能&#xff0c;路由功能是指 Linux 操作系统提供的路由管理和转发功能&#xff0c;它允许 Linux 主机在网络中正确地转发数据包&#xff0c;并确保数据包能够达到其目的地。 出于安全考虑&#xff0c;Linux系统默认是禁止数据…