STM32入门学习之DMA

news2025/1/13 10:04:14

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)*100
	MYDMA_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.coloradmin.cn/o/1641460.html

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

相关文章

从永远到永远-和弦-挂留和弦

挂留和弦 1.概念2.指型1.Xsus2和弦2.Xsus4和弦 3.应用 1.概念 该篇说下和弦中的“渣男”、“绿茶”,挂留和弦。 挂留(suspended)和弦是将三和弦的三音替换成大二度或纯四度音形成的,包括挂留二和弦、挂留四和弦两种。 三音是一个…

【Android学习】简易计算器的实现

1.项目基础目录 新增dimens.xml 用于控制全部按钮的尺寸。图片资源放在drawable中。 另外 themes.xml中原来的 <style name"Theme.Learn" parent"Theme.MaterialComponents.DayNight.DarkActionBar">变为了&#xff0c;加上后可针对button中增加图片…

【nature review】用于非易失性射频开关技术的新兴存储电子器件

这篇文章是一篇关于非挥发性射频&#xff08;RF&#xff09;开关技术的综述文章&#xff0c;发表在《Nature Reviews Electrical Engineering》2024年1月的期刊上。文章详细介绍了新兴的基于记忆电子技术的RF开关技术&#xff0c;特别是在二维&#xff08;2D&#xff09;材料方…

Oracle23ai来了,23爱,全能、超级巨兽...

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、My…

一毛钱不到的FH8208C单节锂离子和锂聚合物电池一体保护芯片

前言 目前市场上电池保护板&#xff0c;多为分体方案&#xff0c;多数场合使用没有问题&#xff0c;部分场合对空间有进一步要求&#xff0c;或者你不想用那么多器件&#xff0c;想精简一些&#xff0c;那么这个芯片就很合适&#xff0c;对于充电电池来说&#xff0c;应在使用…

gige工业相机突破(一)

gige相机能不能绕开相机生产商提供的sdk&#xff0c;而直接取到像&#xff1f; 两种办法&#xff0c;第一&#xff0c;gige vision2.0说明书&#xff0c;第二&#xff0c;genicam 首先你会去干什么事&#xff1f; 好几年&#xff0c;我都没有突破&#xff0c;老虎吃天&#x…

Jenkins流水线部署springboot项目

文章目录 Jenkins流水线任务介绍Jenkins流水线任务构建Jenkins流水线任务Groovy脚本Jenkinsfile实现 Jenkins流水线任务实现参数化构建拉取Git代码构建代码制作自定义镜像并发布 Jenkins流水线任务介绍 之前采用Jenkins的自由风格构建的项目&#xff0c;每个步骤流程都要通过不…

InfiniFlow 創始人兼CEO張穎峰確認出席“邊緣智能2024 - AI開發者峰會”

隨著AI技術的迅猛發展&#xff0c;全球正逐步進入邊緣計算智能化與分布式AI深度融合的新時代&#xff0c;共同書寫著分布式智能創新應用的壯麗篇章。邊緣智能&#xff0c;作為融合邊緣計算和智能技術的新興領域&#xff0c;正逐漸成為推動AI發展的關鍵力量。借助分布式和去中心…

JavaScript 如何理解柯里化函数结构及调用

文章目录 柯里化函数是什么逐步理解柯里化函数 柯里化函数是什么 柯里化&#xff08;Currying&#xff09;函数&#xff0c;又称部分求值&#xff0c;是一种函数转换技术。这种技术将一个接受多个参数的函数转换为一系列接受单一参数的函数。具体来说&#xff0c;一个柯里化的…

AI大模型探索之路-训练篇11:大语言模型Transformer库-Model组件实践

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

C语言 | Leetcode C语言题解之第67题二进制求和

题目&#xff1a; 题解&#xff1a; void reserve(char* s) {int len strlen(s);for (int i 0; i < len / 2; i) {char t s[i];s[i] s[len - i - 1], s[len - i - 1] t;} }char* addBinary(char* a, char* b) {reserve(a);reserve(b);int len_a strlen(a), len_b st…

LeetCode 面试经典150题 28.找出字符串中第一个匹配项的下标

题目&#xff1a;给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 思路&#xff1a;暴力&#xff08;…

一个肉夹馍思考的零耦合设计

刷抖音听说知识付费是普通人的一个收入增长点&#xff0c;写了三十几篇文章一毛钱没赚&#xff0c;感觉有点沮丧。天上下着小雨雨&#xff0c;稀稀嗦嗦的&#xff0c;由于了很久还是买了一个&#x1f928;。 忽然觉得生活有点悲催&#xff0c;现在已经变得斤斤计较&#xff0c;…

「 网络安全常用术语解读 」SBOM主流格式CycloneDX详解

CycloneDX是软件供应链的现代标准。CycloneDX物料清单&#xff08;BOM&#xff09;可以表示软件、硬件、服务和其他类型资产的全栈库存。该规范由OWASP基金会发起并领导&#xff0c;由Ecma International标准化&#xff0c;并得到全球信息安全界的支持&#xff0c;如今CycloneD…

pg数据库学习知识要点分析-1

知识要点1 对象标识OID 在PostgreSQL内部&#xff0c;所有的数据库对象都通过相应的对象标识符&#xff08;object identifier&#xff0c;oid&#xff09;进行管理&#xff0c;这些标识符是无符号的4字节整型。数据库对象与相应oid 之间的关系存储在对应的系统目录中&#xf…

nginx--压缩https证书favicon.iconginx隐藏版本号 去掉nginxopenSSL

压缩功能 简介 Nginx⽀持对指定类型的⽂件进行压缩然后再传输给客户端&#xff0c;而且压缩还可以设置压缩比例&#xff0c;压缩后的文件大小将比源文件显著变小&#xff0c;这样有助于降低出口带宽的利用率&#xff0c;降低企业的IT支出&#xff0c;不过会占用相应的CPU资源…

【JVM】GC调优(优化JVM参数)、性能调优

GC调优 GC调优的主要目标是避免由垃圾回收引起程序性能下降。 GC调优的核心指标 垃圾回收吞吐量&#xff1a;执行用户代码时间/&#xff08;执行用户代码时间 GC时间&#xff09;延迟&#xff1a;GC延迟 业务执行时间内存使用量 GC调优步骤 发现问题&#xff1a;通过监控…

leetcode_43.字符串相乘

43. 字符串相乘 题目描述&#xff1a;给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 注意&#xff1a;不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: num1 &q…

python:用 mido 生成 midi文件,用 pygame 播放 mid文件

pip install mido Downloading mido-1.3.2-py3-none-any.whl (54 kB) Downloading packaging-23.2-py3-none-any.whl (53 kB) Installing collected packages: packaging, mido Successfully installed mido-1.3.2 packaging-23.2 mido 官网文档 pip intall pygame pygame…

Jenkins(超详细的Docker安装Jenkins教程!!!)

Jenkins Jenkins&#xff0c;原名 Hudson&#xff0c;2011 年改为现在的名字。它是一个开源的实现持续集成的软件工具。 官方网站&#xff1a;https://www.jenkins.io/ 中文文档&#xff1a;https://www.jenkins.io/zh/ 为什么需要Jenkins&#xff1f; 我们以前写完代码&a…