嵌入式单片机stm32之DMA实验
一. 对于大容量的STM32芯片有2个DMA控制器,控制器1有7个通道,控制器2有5个通道
每个通道都可以配置一些外设的地址。
二. 通道的配置过程:
1. 首先设置CPARx寄存器和CMARx寄存器。
通过DMA控制器把一个地址的值复制到另外一个地址,通过DMA控制器自动开启一条通道完成。
CPARx寄存器存放的是外设的地址
CMARx寄存器存储的是存储器的地址
2. 设置数据传输方向,是否循环模式,是不是开启外设和存储器的增量模式,还有数据宽度,是8位,16位还是32位。
比如设置成存储器的地址增量,那么传输一个数据过去后它的地址自动递增。
3. 设置要传输的数据量
4. 设置通道的优先级
5. 全部设置好后就可以启动DMA通道。
启动后数据就开始传输,传输的过程中可以读CNDTRx寄存器,可知道当前还剩多少个数据。数据传输到一半或全部传输完毕后有响应的标志位置1,如果开启了中断,可以进入相应的中断程序。
一。常用的DMA函数
1.DMA初始化函数
void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx); //设置要开启的通道,还有一些参数,包括外设基地址,存储器基地址,传输的数据量,增量模式,数据宽度等。
2.DMA使能函数
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);
3.开启相应中断的函数
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);
4.设置CNDTRx和读CNDTRx函数
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
二。常用的外设DMA使能函数
需要开启外设的DMA使能才能够使用DMA功能。
这些函数分布在外设各自的头文件中。
三。DMA初始化函数
对应下面的代码学习:
u16 DMA1_MEM_LEN; //保存DMA每次数据传送的长度 //DMA1的各通道配置 //这里的传输形式是固定的,这点要根据不同的情况来修改 //从存储器->外设模式/8位数据宽度/存储器增量模式 //DMA_CHx:DMA通道CHx //cpar:外设地址 //cmar:存储器地址 //cndtr:数据传输量 void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输 DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值 DMA1_MEM_LEN=cndtr; DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址 DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设 DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小 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通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMA_CHx, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道 USART1_Tx_DMA_Channel所标识的寄存器 }
四。DMA配置的一般过程
五。实验
使用串口1发送DMA
dma.h文件
#ifndef __DMA_H #define __DMA_H #include "sys.h" void MYDMA_Config(DMA_Channel_TypeDef*DMA_CHx,u32 cpar,u32 cmar,u16 cndtr);//配置DMA1_CHx void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);//使能DMA1_CHx #endif dma.c文件 #include "dma.h" DMA_InitTypeDef DMA_InitStructure; u16 DMA1_MEM_LEN;//保存DMA每次数据传送的长度 //DMA1的各通道配置 //这里的传输形式是固定的,这点要根据不同的情况来修改 //从存储器->外设模式/8位数据宽度/存储器增量模式 //DMA_CHx:DMA通道CHx //cpar:外设地址 //cmar:存储器地址 //cndtr:数据传输量 void MYDMA_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输,DMA在AHB总线上 DMA_DeInit(DMA_CHx); //将DMA的通道1寄存器重设为缺省值 DMA1_MEM_LEN=cndtr; DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外设ADC基地址 DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA内存基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //数据传输方向,从内存读取发送到外设 DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA缓存的大小 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通道 x拥有中优先级 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输 DMA_Init(DMA_CHx, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道 USART1_Tx_DMA_Channel所标识的寄存器 } //开启一次DMA传输 void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx) { DMA_Cmd(DMA_CHx, DISABLE ); //关闭USART1 TX DMA1 所指示的通道 DMA_SetCurrDataCounter(DMA1_Channel4,DMA1_MEM_LEN);//DMA通道的DMA缓存的大小 DMA_Cmd(DMA_CHx, ENABLE); //使能USART1 TX DMA1 所指示的通道 }
注:DMA每传输完成一次,要传输的数据量都要自动清零,因此每次开启都要重新设置要传输的数据量。
主程序中:
for(i=0;i { 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++; } }
这一段是 在每个字符串“ALIENTEK WarShip STM32F1 DMA 串口实验”后面添加0x0d和0x0a,也就是自动换行,这样在串口助手中接收到的数据就是ALIENTEK WarShip STM32F1 DMA 串口实验,然后自动换行,另外串口助手sscom程序有bug,不能自动换行,可以换其他串口助手观察。
资料分享便于后期的学习参考
(DMA专题讲解)
http://www.makeru.com.cn/live/1392_1048.html?s=45051
stm32 如何用DMA搬运数据
http://www.makeru.com.cn/live/detail/1484.html?s=45051
(stm32串口应用)
http://www.makeru.com.cn/live/1392_1164.html?s=45051
PWM脉宽调制技术
http://www.makeru.com.cn/live/4034_2146.html?s=45051
嵌入式单片机stm32之DMA实验的更多相关文章
- 嵌入式单片机STM32应用技术(课本)
目录SAIU R20 1 6 第1页第1 章. 初识STM32..................................................................... ...
- STM32之DMA+ADC
借用小甲鱼的经典:各位互联网的广大网友们.大家早上中午晚上好..(打下小广告,因为小甲鱼的视频真的很不错).每次看小甲鱼的视频自学都是比较轻松愉快的..我在想,如果小甲鱼出STM32的视频,我会一集不 ...
- STM32之DMA
一.DMA简介 1.DMA简介 DMA(Direct Memory Access:直接内存存取)是一种可以大大减轻CPU工作量的数据转移方式. CPU有转移数据.计算.控制程序转移等很多功能,但其实转 ...
- STM32使用DMA发送串口数据
1.概述 上一篇文章<STM32使用DMA接收串口数据>讲解了如何使用DMA接收数据,使用DMA外设和串口外设,使用的中断是串口空闲中断.本篇文章主要讲解使用DMA发送数据,不会讲解基础的 ...
- 嵌入式单片机之stm32串口你懂了多少!!
stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...
- 嵌入式02 STM32 实验10 定时器中断
优秀文章 https://blog.csdn.net/qq_38351824/article/details/82619734 一.STM32通用定时器(TIM2.TIM3.TIM4和TIM5共四个通 ...
- 嵌入式02 STM32 实验08 外部中断
一.中断 由于某个事件的发生,CPU暂停当前正在执行的程序,转而执行处理事件的一个程序.该程序执行完成后,CPU接着执行被暂停的程序.这个过程称为中断.(我正在捉泥鳅,但是我妈喊我回家吃饭,我必须回家 ...
- 嵌入式02 STM32 实验07 串口通信
STM32串口通信(F1系列包含3个USART和2个UART) 一.单片机与PC机串行通信研究目的和意义: 单片机自诞生以来以其性能稳定,价格低廉.功能强大.在智能仪器.工业装备以及日用电子消费产品中 ...
- 嵌入式02 STM32 实验01 端口复用和重映射
内设与外设: 端口复用和端口重映射都需要了解内设和外设,那么什么是内设?什么是外设? 内设:单片机内部集成的功能一般包括:串口模块.SPI模块(Serial Peripheral Interface ...
随机推荐
- 源码解读Dubbo分层设计思想
一.Dubbo分层整体设计概述 我们先从下图开始简单介绍Dubbo分层设计概念: (引用自Duboo开发指南-框架设计文档) 如图描述Dubbo实现的RPC整体分10层:service.config. ...
- clion结合vcpkg以及GTest的使用
目录 一.vcpkg简介.下载和使用 1. vcpkg是什么 2. vcpkg下载 3. 使用vcpkg下载第三方库 二.clion结合vcpkg 1. 方法一:使用环境变量 2. 方法二:添加cma ...
- 5-7接口测试工具之jmeter的使用
1.安装 免费的,安装jdk配好系统环境变量就能用了 2.jmeter测接口 获取用户信息,接口文档定义有2种请求方式 添加线程组-->添加http请求-->输入接口文档中说明的服务器名称 ...
- POJ1804——Brainman(水题)
解题思路: 一个乱序序列的 逆序数 = 在只允许相邻两个元素交换的条件下,得到有序序列的交换次数 直接求逆序数 把S[i]和s[i+1~n]的元素逐个比较,如果s[i] > s[k] (k∈[i ...
- scrum项目冲刺_day04总结
摘要:今日完成任务. 1.图像识别已优化 2.语音识别正在进行 3.搜索功能 正在进行 总任务: 一.appUI页面(已完成) 二.首页功能: 1.图像识别功能(已完成) 2.语音识别功能 3.垃圾搜 ...
- jquery获取一个元素符合条件的第一个父元素
closest jQuery 1.3新增.从元素本身开始,逐级向上级元素匹配,并返回最先匹配的元素.. closest会首先检查当前元素是否匹配,如果匹配则直接返回元素本身.如果不匹配则向上查找父元素 ...
- Dede后台广告管理模块增加图片上传功能插件
用户问题:网站广告后台管理非常方便,但是织梦后台的广告管理模块,发布广告时图片没有上传选项,只能用URL地址,很不方便,那么织梦帮就教大家一个方法实现广告图片后台直接上传,非常方便.先给大家看下修改后 ...
- python 语法规范
在python shell 中输入 import this 可以看到python之禅 The Zen of Python, by Tim Peters Beautiful is better than ...
- 启用 Spring-Cloud-OpenFeign 配置可刷新,项目无法启动,我 TM 人傻了(上)
本篇文章涉及底层设计以及原理,以及问题定位,比较深入,篇幅较长,所以拆分成上下两篇: 上:问题简单描述以及 Spring Cloud RefreshScope 的原理 下:当前 spring-clou ...
- android 使用SQLite的基本操作
Android操作数据库SQLite使用sql语句基本操作 1:自定义自己的SQLiteOpenHelper public class DBHelper extends SQLiteOpenHelpe ...