单片机清零程序DMA传输完成后会把目标地址清零吗?急!!

单片机里的DMA是什么意思啊,有款单片机说具有DMA控制器,中的DMA是什么意思啊?_百度知道
单片机里的DMA是什么意思啊,有款单片机说具有DMA控制器,中的DMA是什么意思啊?
我有更好的答案
DMA就是直接存储器访问的首字母缩写(Direct Memory Access)。CPU的总线上同时会挂着多几个存储器,如果想要将存储器1的内容复制到存储器2,如果不用DMA的话,就得靠CPU直接去操作了,操作过程大致是:CPU准备好存储器1的地址和控制信号,读取存储器1的内容,存放到CPU内部寄存器中,再准备好存储器2的地址和控制信号,将寄存器中的内容写入到存储器2。如果是单个数据的操作,这个过程都是必须的,效率问题也不明显,但如果一次要复制大量数据(比如一帧图像数据、一批语音数据等),那么靠CPU这样循环一个数据一个数据地操作,不仅速度慢(由于架构设计的原因,一般CPU访问外部总线的速度都不是很高),还会导致CPU和总线一直被占用,效率就非常低了。如果在CPU内部做一个硬件控制器,专门负责这种数据搬移操作(自动产生存储器的地址和控制信号,自动实现读写时序),不仅速度可以提高很多,CPU还可以在此期间做其它的事情,这样效率就会高很多了。DMA就是这么个意思,硬件上必须有一个DMA控制器来实现这一功能。现在DMA的概念和作用已经大大延伸了,很多复杂CPU里面甚至会包含很多个DMA控制器,DMA操作也不再仅限于外部存储器了,内部存储器之间、内部和外部存储器之间、各种标准外设和存储器之间,都有DMA控制器来实现数据交换,这样CPU的功能越来越强,数据处理也越来越快。。
采纳率:43%
DMA: Direct Memory Access,直接内存存取的意思。它是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依于 CPU 的大量 中断 负载。 在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU
本回答被网友采纳
为您推荐:
其他类似问题
您可能关注的内容
dma的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。单片机与IBM PC机的DMA数据传输--《电子技术》1992年07期
单片机与IBM PC机的DMA数据传输
【摘要】:正 一、引言单片机已广泛地应用于工业自动化过程的实时控制和数据处理。但是,由于单片机的计算功能有限,难以进行复杂的数据处理。所以,对复杂的数据处理常借助于IBM PC机来完成,而单片机主要完成一些较直接的数据处理和控制功能。为了保证控制和数据处理的实时性,单片机与IBM PC机的快速数据通信就成为一个首先必须解决的问题。本文就是针对这一情况,介绍了一种单片机与IBM PC机的DMA数据传输方法。该方法利用IBM PC主机板上已有的DMA资源,具有接口电路简单、编程容易、数据传输快和可靠性高等优点。
【作者单位】:
欢迎:、、)
支持CAJ、PDF文件格式,仅支持PDF格式
【相似文献】
中国期刊全文数据库
宋宜明;廖启征;郭磊;;[J];仪表技术;2007年01期
林盛鑫;;[J];东莞理工学院学报;2009年03期
于再兴;陈江;;[J];微计算机信息;2008年11期
庄建清;徐玮;;[J];电子制作;2008年09期
尚怡君;葛明涛;;[J];光盘技术;2009年08期
张文强;周斌;罗鹏;;[J];电子制作;2010年02期
汤华庚,李森生;[J];单片机与嵌入式系统应用;2004年10期
崔军辉;张培仁;王津津;杜洪亮;许波;;[J];自动化与仪表;2008年09期
高怀举;李楠;宋雪平;宋瑞莉;;[J];计算机与网络;2008年24期
龚步尺;翁惠辉;;[J];石油仪器;2007年03期
中国重要会议论文全文数据库
张从力;赵光;王述勇;;[A];计算机技术与应用进展·2007——全国第18届计算机技术与应用(CACIS)学术会议论文集[C];2007年
唐卫红;曹金荣;李汉军;郑晓慧;杨士亮;;[A];第六届全国信息获取与处理学术会议论文集(2)[C];2008年
杨剑平;刘淳;任广林;;[A];江苏省通信学会2004年学术年会论文集[C];2004年
周栋;马刚;闫广;;[A];第十三届全国煤矿自动化学术年会、中国煤炭学会自动化专业委员会学术会议论文集[C];2003年
黄贤超;宓方玮;;[A];四川省电子学会传感技术第九届学术年会论文集[C];2005年
徐志远;凌志浩;;[A];第七届工业仪表与自动化学术会议论文集[C];2006年
赵明忠;;[A];全面建设小康社会:中国科技工作者的历史责任——中国科协2003年学术年会论文集(下)[C];2003年
张艳;崔建召;文环明;;[A];2007年河北省电子学会、河北省计算机学会、河北省自动化学会、河北省人工智能学会、河北省计算机辅助设计研究会、河北省软件行业协会联合学术年会论文集[C];2007年
范小兰;;[A];第七届全国信息获取与处理学术会议论文集[C];2009年
汪科;秦正;罗辑;;[A];第六届全国信息获取与处理学术会议论文集(2)[C];2008年
中国重要报纸全文数据库
;[N];北京电子报;2001年
广东 张则;[N];电子报;2010年
郭学提;[N];电子报;2008年
广东 张则;[N];电子报;2010年
牛余朋;[N];电子报;2004年
刘少龙;[N];电子报;2005年
广东 陈城岗;[N];电子报;2011年
广东 陈城岗;[N];电子报;2011年
广东 陈城岗;[N];电子报;2011年
广东 陈城岗;[N];电子报;2011年
中国博士学位论文全文数据库
曹家鑫;[D];中国科学技术大学;2013年
谢旻;[D];国防科学技术大学;2007年
林进;[D];中国科学院研究生院(计算技术研究所);1998年
刘彩霞;[D];北京理工大学;2010年
李洁琼;[D];华中科技大学;2011年
中国硕士学位论文全文数据库
曹卫芳;[D];山东科技大学;2005年
吕春峰;[D];昆明理工大学;2006年
黄凤娟;[D];安徽大学;2006年
陶志东;[D];华中科技大学;2006年
尹林子;[D];电子科技大学;2005年
陈锐;[D];浙江大学;2006年
曹彩萍;[D];合肥工业大学;2006年
朱宇翔;[D];南京工业大学;2006年
周巧玲;[D];浙江工业大学;2007年
张俊武;[D];重庆大学;2007年
&快捷付款方式
&订购知网充值卡
400-819-9993DMA多知识学习应用实例
闲来无事,学习了下DMA的相关知识和使用。平时看到的DMA都是简单的存储器到寄存器或者寄存器到存储器这样单类的传输。学习完DMA后,我想写个比较综合点的DMA学习实例,不仅能增加自己对DMA的深入应用,也同时发表于此给网友提供参考。
之所以说多知识,实例涉及到存储器到寄存器和寄存器到存储器,以及DMA中断使用等相关知识。
实例内容:单片机采集AD值通过DMA传输给RAM存储器(就是定义的变量),同时又将存储器数据传输给串口输出,实现AD采集与串口输出的转换。
下面赋上一些主要的代码进行分析:
主函数部分
int main(void)
delay_init();
//延时初始化
RCCInit();//时钟初始化
USARTInit(USART2 ,115200);//串口初始化
ADCInit(ADC1 , 1); //AD初始化PA1
Get_ADCValue(ADC1 ,ADC_Channel_1 ,1);//对ADC通道配置
DMAx_ADCx_Init(DMA1_Channel1 ,DMA_DIR_PeripheralSRC,(u32)(&adcValue), (u32)&(ADC1-&DR),1);//ADC1--&存储器(adcValue)(注传入地址位要32位)
DMAx_USARTx_Init(DMA1_Channel7 ,DMA_DIR_PeripheralDST,(u32)usart_BUFF, (u32)&(USART2-&DR),bufferSize);//存储器(adcValue)--&UASART1
NVIC_Config();//注意,实测过,DMA中断配置必须放在DMA配置后面才能用
DMAx_Enable(DMA1_Channel1 , 1);
ADC_DMACmd(ADC1, ENABLE);
DMAx_Enable(DMA1_Channel7 , bufferSize);//先启动,使满标志不为0
USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
printf(&下面是DMA测试,AD值为:\r\n&);
delay_ms(100);
DMAx_Enable(DMA1_Channel1 , 1);
DMA1_CH1中断函数
void DMA1_Channel1_IRQHandler()
if(DMA_GetITStatus(DMA1_IT_TC1) == SET)//获取DMA1_CH1的传输完成标志位
DMA_ClearITPendingBit(DMA1_IT_TC1);//清除满标志(注意清除后,不能去等待判满)
sprintf(usart_BUFF,&%d &,adcValue);//16位整型转化为字符串型(每个字符8位,1字节)(转换中加了个空格,方便显示)
while(!DMA_GetFlagStatus( DMA1_FLAG_TC7));//等待传输完成(注意 等待判满前,不能清除标志)
DMA_ClearFlag(DMA1_FLAG_TC7); //完成后清除
DMAx_Enable(DMA1_Channel7 , bufferSize);//开始串口的DMA传输
ADC初始化:
void ADCInit(ADC_TypeDef* ADCx , u8 Channel_num)
//=============对ADC1的配置并校准====================//
ADC_InitTypeDef ADC_I
ADC_DeInit(ADCx);//复位ADC1
ADC_Inittrue.ADC_ContinuousConvMode = ENABLE;//连续转换
ADC_Inittrue.ADC_DataAlign = ADC_DataAlign_R//右对齐。(ADC为12位精度,其数字信号存于16位的寄存器)
ADC_Inittrue.ADC_ExternalTrigConv = ADC_ExternalTrigConv_N//触发方式,无外部触发=软件触发
ADC_Inittrue.ADC_Mode = ADC_Mode_I//独立模式
ADC_Inittrue.ADC_NbrOfChannel = Channel_//顺序进行规则转换的 ADC 通道的数目(1--16)
ADC_Inittrue.ADC_ScanConvMode = DISABLE;//无扫描模式,即工作在单通道下
ADC_Init(ADCx, &ADC_Inittrue);//初始化配置模块ADC1
ADC_Cmd(ADCx, ENABLE);//使能ADC1
ADC_ResetCalibration(ADCx);
//复位校准
while(ADC_GetResetCalibrationStatus(ADCx));
ADC_StartCalibration(ADCx);//开启adc校准
while(ADC_GetCalibrationStatus(ADCx));
ADC通道配置,并获取相应模块下通道的ADC值(这里只用到通道配置就够了)
u16 Get_ADCValue(ADC_TypeDef* ADCx ,u8 ADC_Channel_x ,u8 rank)
//========对ADC的规则通道的配置(选通道x)=========//
ADC_RegularChannelConfig(ADCx,ADC_Channel_x, rank , ADC_SampleTime_28Cycles5);//ADC1的通道4,排在第1个被转换,并且采集时间为28.5个ADC1时钟周期
ADC_SoftwareStartConvCmd(ADCx ,ENABLE);//开启软件转换
//========对ADC转换部分=========//
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADCx)&0x00000//换回ADC1转换后的值
DMA ADC初始化
//名称:DMA ADC初始化
//传入参数:通道 传输方向 存储器基地址
外设基地址 数据量
//注:传入地址位数32位
//说明:默认非循环,存储器地址不自加,外设不自加,数据宽度都为16位
void DMAx_ADCx_Init(DMA_Channel_TypeDef* DMAx_Channelx ,u32 DMA_DIR_Peripheralxxx , u32 MemoryBaseAddr, u32 PeripheralBaseAddr,u16 DMA_BufferSize)
DMA_InitTypeDef DMA_InitS
if(DMA1_Channel1 &= DMAx_Channelx && DMA1_Channel7 &= DMAx_Channelx)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA位于AHB时钟上
if(DMA2_Channel1 &= DMAx_Channelx && DMA2_Channel5 &= DMAx_Channelx)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);//DMA位于AHB时钟上
DMA_DeInit(DMAx_Channelx);//
DMA_InitStruct.DMA_BufferSize = DMA_BufferS//DMA传输的数据量
DMA_InitStruct.DMA_DIR = DMA_DIR_P//传输方向:外设为目标地址(存储器到外设)
DMA_InitStruct.DMA_M2M = DMA_M2M_D //存储器到存储器传输失能
DMA_InitStruct.DMA_MemoryBaseAddr = MemoryBaseA//存储器基地址(可为sram或flash,程序变量一般位于sram)
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfW//存储器传输数据宽度16(可选8,16,32位)
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_D//存储器地址不递增
DMA_InitStruct.DMA_Mode = DMA_Mode_N// 不循环传输模式(循环:地址递增满后,又重载从基地址开始传输)(不循环:递增满后不重载且暂停)
DMA_InitStruct.DMA_PeripheralBaseAddr = PeripheralBaseA//外设寄存器的基地址(多是数据寄存器)
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfW//外设寄存器传输数据宽度16(8,16,32位)
DMA_InitStruct.DMA_PeripheralInc =
DMA_PeripheralInc_D//外设地址不进行递增
DMA_InitStruct.DMA_Priority = DMA_Priority_H//传输优先级:高(四种:最高,高,中,低)
DMA_Init(DMAx_Channelx, &DMA_InitStruct);
DMA USART初始化。
注意此初始化和ADC 的DMA初始化是不一样的,具体不一样处见函数说明, 和调用的实参。
//名称:DMA USART初始化
//传入参数:通道 传输方向 存储器基地址
外设基地址 数据量
//注;传入地址位数32位
//说明:默认非循环,存储器地址自加,外设不自加,数据宽度都为8位
void DMAx_USARTx_Init(DMA_Channel_TypeDef* DMAx_Channelx ,u32 DMA_DIR_Peripheralxxx , u32 MemoryBaseAddr, u32 PeripheralBaseAddr,u16 DMA_BufferSize)
DMA_InitTypeDef DMA_InitS
if(DMA1_Channel1 &= DMAx_Channelx && DMA1_Channel7 &= DMAx_Channelx)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);//DMA位于AHB时钟上
if(DMA2_Channel1 &= DMAx_Channelx && DMA2_Channel5 &= DMAx_Channelx)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);//DMA位于AHB时钟上
DMA_DeInit(DMAx_Channelx);
DMA_InitStruct.DMA_BufferSize = DMA_BufferS//DMA传输的数据量
DMA_InitStruct.DMA_DIR = DMA_DIR_P//传输方向:外设为目标地址(存储器到外设)
DMA_InitStruct.DMA_M2M = DMA_M2M_D //存储器到存储器传输失能
DMA_InitStruct.DMA_MemoryBaseAddr = MemoryBaseA//存储器基地址(可为sram或flash,程序变量一般位于sram)
DMA_InitStruct.DMA_MemoryDataSize =DMA_MemoryDataSize_B存储器传输数据宽度8位(8,16,32位)
DMA_InitStruct.DMA_MemoryInc =DMA_MemoryInc_E//存储器地址随传输而递增(加多少与数据宽度有关,可见芯片参考手册,这里是地址自加1)
DMA_InitStruct.DMA_Mode = DMA_Mode_N//不循环传输模式(循环:地址递增满后,又重载从基地址开始传输)(不循环:递增满后不重载且暂停)
DMA_InitStruct.DMA_PeripheralBaseAddr = PeripheralBaseA//外设寄存器的基地址(多是数据寄存器)
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B// DMA_PeripheralDataSize_HalfW//外设寄存器传输数据宽度8位(8,16,32位)
DMA_InitStruct.DMA_PeripheralInc =
DMA_PeripheralInc_D//外设地址不进行递增
DMA_InitStruct.DMA_Priority = DMA_Priority_H//传输优先级:高(四种:最高,高,中,低)
DMA_Init(DMAx_Channelx, &DMA_InitStruct);
DMA启动传输(用于每次传输开启)
//DMA启动传输
//传入参数:通道
void DMAx_Enable(DMA_Channel_TypeDef* DMAx_Channelx ,u16 DMA_BufferSize)
DMA_Cmd(DMAx_Channelx, DISABLE);//失能
DMA_SetCurrDataCounter( DMAx_Channelx , DMA_BufferSize); //重新设置传输数据长度
DMA_Cmd(DMAx_Channelx, ENABLE);//使能
中断配置函数
void NVIC_Config()
NVICInit(NVIC_PriorityGroup_2, DMA1_Channel1_IRQn , 0, 1); //组别2 抢占0 从占1
DMA_ClearFlag(DMA1_FLAG_TC1);//清满标志
DMA_ClearITPendingBit(DMA1_IT_TC1);
DMA_ITConfig(DMA1_Channel1,
DMA_IT_TC, ENABLE);//开启全部传输完成中断
RCC时钟配置
void RCCInit()
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1 , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC时钟周期 6分频
下面是上位机显示传输的数据:
以上就是涉及的主要相关函数,在本次调试中,总结了几个注意要点:
对于串口,一次只能输出8位(一字节数),即使传进去16位数,也被截取前半段 ADC采集为10为精度,数据存储宽度要大于8位 所以:DMA的ADC传输需要16位,而USART传输只能8位传输 该例程的ADC为连续转换模式,若是单次需要每次对通道重新配置一次 *DMA为循环模式只需要使能一次,否则非循环下需要重新使能 来启动传输 每个DMA通道对应不同外设见手册 DMA中断配置必须放在DMA参数配置后面才能用 注意:等待判满前,不能清除标志;注意:清除后,不能去等待判满,否则死循环& & & & &本文主要介绍的是DMA相关的知识,首先:
1)在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题。即DMA传输前,CPU要把&总线控制权交给DMA控制器,而在结束DMA传输后,DMA控制器应立即把总线控制权再交回给CPU。一个完整的DMA传输过&程必须经过DMA请求、DMA响应、DMA传输、DMA结束4个步骤。
2)DMA技术的出现,使得外围设备可以通过DMA控制器直接访问内存,与此同时,CPU可以继续执行程序.那么DMA控制器与CPU怎样分时使用内存呢?通常采用以下三种方法:(1)停止CPU访内存;(2)周期挪用;(3)DMA与CPU交替访问内存
1.DMA有什么用?
直接存储器存取用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。
2.有多少个DMA资源?
有两个DMA控制器,DMA1有7个通道,DMA2有5个通道。
3.数据从什么地方送到什么地方?
外设到SRAM(I2C/UART等获取数据并送入SRAM);
SRAM的两个区域之间;
外设到外设(ADC读取数据后送到TIM1控制其产生不同的PWM占空比);
SRAM到外设(SRAM中预先保存的数据送入DAC产生各种波形);
……还有一些目前还搞不清楚的。
4.DMA可以传递多少数据?
传统的DMA的概念是用于大批量数据的传输,但是我理解,在STM32中,它的概念被扩展了,也许更多的时候快速是其应用的重点。数据可以从1~65535个。
直接存储器存取(Direct Memory Access,DMA)是计算机科学中的一种内存访问技术。它允许某些电脑内部的硬体子系统(电脑外设),可以独立地直接读写系统存储器,而不需绕道 CPU。在同等程度的CPU负担下,DMA是一种快速的数据传送方式。它允许不同速度的硬件装置来沟通,而不需要依于 CPU的大量中断请求。【摘自Wikipedia】
现在越来越多的单片机采用DMA技术,提供外设和存储器之间或者存储器之间的高速数据传输。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器
来实行和完成。STM32就有一个DMA控制器,它有7个通道,每个通道专门用来管理一个或多个外设对存储器访问的请求,还有一个仲裁器来协调各个DMA请求的优先权。
DMA 控制器和Cortex-M3核共享系统数据总线执行直接存储器数据传输。当CPU和DMA同时访问相同的目标(RAM或外设)时,DMA请求可能会停止 CPU访问系统总线达若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线(存储器或外设)带宽。
在发生一个事件后,外设发送一个请求信号到DMA控制器。DMA控制器根据通道的优先权处理请求。当DMA控制器开始访问外设的时候,DMA控制器立即发送给外设一个应答信号。当从DMA控制器得到应答信号时,外设立即释放它的请求。一旦外设释放了这个请求,DMA控制器同时撤销应答信号。如果发生更多的请求时,外设可以启动下次处理。
总之,每个DMA传送由3个操作组成:
1). 从外设数据寄存器或者从DMA_CMARx寄存器指定地址的存储器单元执行加载操作。
2). 存数据到外设数据寄存器或者存数据到DMA_CMARx寄存器指定地址的存储器单元。
3). 执行一次DMA_CNDTRx寄存器的递减操作。该寄存器包含未完成的操作数目。
仲裁器根据通道请求的优先级来启动外设/存储器的访问。优先级分为两个等级:软件(4个等级:最高、高、中等、低)、硬件(有较低编号的通道比拥有较高编号的通道有较高的优先权)。
可以在DMA传输过半、传输完成和传输错误时产生中断。
STM32中DMA的不同中断(传输完成、半传输、传输完成)通过“线或”方式连接至NVIC,需要在中断例程中进行判断。
进行DMA配置前,不要忘了在RCC设置中使能DMA时钟。STM32的DMA控制器挂在AHB总线上。
DMA总共有7个通道,各个通道的DMA映射关系如下:
外设的事件连接至相应DMA通道,每个通道均可以通过软件触发实现存储器内部的DMA数据传输(M2M模式)
Tips:库2.0中函数RCC_AHBPeriphClockCmd的参数由“RCC_AHBPeriph_DMA”改成“RCC_AHBPeriph_DMA1”(如果是DMA1控制器的话)。
DMA的传输标志位(CHTIFx、CTCIFx、CGIFx)由硬件设置为“1”,但需要软件清零,在中断服务程序中清除。当CGIFx(全局中断标志位)清零后,CHTIFx 和 CTCIFx均清零。
5.过程:怎样启用DMA?首先,众所周知的是初始化,任何设备启用前都要对其进行初始化,要对模块初始化,还要先了解该模块相应的结构及其函数,以便正确的设置;由于DMA较为复杂,我就只谈谈DMA的基本结构和和常用函数,这些都是ST公司提供在库函数中的。
1)、 下面代码是一个标准DMA设置,当然实际应用中可根据实际情况进行裁减:
DMA_DeInit(DMA_Channel1);
上面这句是给DMA配置通道,根据ST提供的资料,STM3210Fx中DMA包含7个通道(CH1~CH7),也就是说可以为外设或memory提供7座“桥梁”(请允许我使用桥梁一词,我觉得更容易理解,哈哈,别“拍砖”呀!);
DMA_InitStructure.DMA_PeripheralBaseAddr =
上面语句中的DMA_InitStructure是一个DMA结构体,在库中有声明了,当然使用时就要先定义
了;DMA_PeripheralBaseAddr是该结构体中一个数据成员,给DMA一个起始地址,好比是一个buffer起始地址,数据流程是:外设
寄存器à DMA_PeripheralBaseAddàmemory中变量空间(或flash中数据空间等),ADC1_DR_Address是我定义的一个地址
DMA_InitStructure.DMA_MemoryBaseAddr =
(u32)ADC_ConvertedV
上面这句很显然是DMA要连接在Memory中变量的地址,ADC_ConvertedValue是我自己在memory中定义的一个变量;
DMA_InitStructure.DMA_DIR =
DMA_DIR_PeripheralSRC;
上面的这句是设置DMA的传输方向,就如前面我所说的,DMA可以双向传输,也可以单向传输,这里设置的是单向传输,如果需要双向传输:把DMA_DIR_PeripheralSRC改成DMA_DIR_PeripheralDST即可。
DMA_InitStructure.DMA_BufferSize = 2;
上面的这句是设置DMA在传输时缓冲区的长度,前面有定义过了buffer的起始地址:ADC1_DR_Address ,为了安全性和可靠性,一般需要给buffer定义一个储存片区,这个参数的单位有三种类型:Byte、HalfWord、word,我设置的2个 half-word(见下面的设置);32位的MCU中1个half-word占16 bits。
DMA_InitStructure.DMA_PeripheralInc =
DMA_PeripheralInc_D
上面的这句是设置DMA的外设递增模式,如果DMA选用的通道(CHx)有多个外设连接,需要使用外设递增模式:DMA_PeripheralInc_E我的例子里DMA只与ADC1建立了联系,所以选用DMA_PeripheralInc_Disable
DMA_InitStructure.DMA_MemoryInc =
DMA_MemoryInc_E
上面的这句是设置DMA的内存递增模式,DMA访问多个内存参数时,需要使用DMA_MemoryInc_Enable,当DMA只访问一个内存参数时,可设置成:DMA_MemoryInc_Disable。
DMA_InitStructure.DMA_PeripheralDataSize =
DMA_PeripheralDataSize_HalfW
上面的这句是设置DMA在访问时每次操作的数据长度。有三种数据长度类型,前面已经讲过了,这里不在叙述。
DMA_InitStructure.DMA_MemoryDataSize =
DMA_MemoryDataSize_HalfW
与上面雷同。在此不再说明。
DMA_InitStructure.DMA_Mode =
DMA_Mode_C
上面的这句是设置DMA的传输模式:连续不断的循环模式,若只想访问一次后就不要访问了(或按指令操作来反问,也就是想要它访问的时候就访问,不要它访问的时候就停止),可以设置成通用模式:DMA_Mode_Normal
DMA_InitStructure.DMA_Priority =
DMA_Priority_H
上面的这句是设置DMA的优先级别:可以分为4级:VeryHigh,High,Medium,Low.
DMA_InitStructure.DMA_M2M =
上面的这句是设置DMA的2个memory中的变量互相访问的
DMA_Init(DMA_Channel1,&DMA_InitStructure);
前面那些都是对DMA结构体成员的设置,在次再统一对DMA整个模块做一次初始化,使得DMA各成员与上面的参数一致。
DMA_Cmd(DMA_Channel1,ENABLE);
哈哈哈!这一句我想我就不罗嗦了,大家一看就明白。
至此,整个DMA总算设置好了,但是,DMA通道又是怎样与外设联系在一起的呢?哈哈,这也是我当初最想知道的一个事情,别急!容我想喝口茶~~~~~~哈哈哈!
要使DMA与外设建立有效连接,这不是DMA自身的事情,是各个外设的事情,每个外设都有
一个xxx_DMACmd(XXXx,Enable )函数,如果使DMA与ADC建立有效联系,就使用ADC_DMACmd(ADC1,Enable);
(这里我启用了ADC中的ADC1模块)。
一个简单的例子 transfer& a word data buffer
from FLASH memory to embedded SRAM memory.
在V3.1.2库的位置
STM32F10x_StdPeriph_Lib_V3.1.2\Project\STM32F10x_StdPeriph_Examples\DMA\FLASH_RAM
DMA_DeInit(DMA1_Channel6);
//peripheral base address
DMA_InitStructure.DMA_PeripheralBaseAddr =
(uint32_t)SRC_Const_B
//memory base address&&
DMA_InitStructure.DMA_MemoryBaseAddr =
(uint32_t)DST_B
& //数据传输方向&&& Peripheral is source&&&&&&&&&&&&&&
DMA_InitStructure.DMA_DIR =
DMA_DIR_PeripheralSRC;
//缓冲区大小 Number of data
to be transferred (0 up to 65535).数据传输数目&&&&
DMA_InitStructure.DMA_BufferSize =
the Peripheral address register is incremented&&&&&&
DMA_InitStructure.DMA_PeripheralInc =
DMA_PeripheralInc_E
//the memory address register is incremented
DMA_InitStructure.DMA_MemoryInc =
DMA_MemoryInc_E
//the Peripheral data width&&&&&&
DMA_InitStructure.DMA_PeripheralDataSize =
DMA_PeripheralDataSize_W
DMA_InitStructure.DMA_MemoryDataSize =
DMA_MemoryDataSize_W
DMA_InitStructure.DMA_Mode =
DMA_Mode_N
DMA_InitStructure.DMA_Priority =
DMA_Priority_H
//the DMAy Channelx will be used in
memory-to-memory transfer
//DMA通道的操作可以在没有外设请求的情况下进行,这种操作就是存储器到存储器模式。
DMA_InitStructure.DMA_M2M =
DMA_M2M_E&&
DMA_Init(DMA1_Channel6,
&DMA_InitStructure);
DMA_ITConfig(DMA1_Channel6, DMA_IT_TC,
DMA_Cmd(DMA1_Channel6, ENABLE);
=======================================================================
3)外设的DMA请求映像
要使DMA与外设建立有效连接,这不是DMA自身的事情,是各个外设的事情,每个外设都有
xxx_DMACmd(XXXx,Enable )函数,如果使DMA与ADC建立有效联系,就使用
ADC_DMACmd
(ADC1,Enable); (这里我启用了ADC中的ADC1模块)。
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr =
DMA_InitStructure.DMA_MemoryBaseAddr =
(uint32_t)&AD_V&&
AD_Value[2];&& 不加&应该也可以& 数组名 代表地址
DMA_InitStructure.DMA_DIR =
DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 2;&&&&& //############## 改了
DMA_InitStructure.DMA_PeripheralInc =
DMA_PeripheralInc_D
DMA_InitStructure.DMA_MemoryInc =
DMA_MemoryInc_E& //############## &&改了
DMA_InitStructure.DMA_PeripheralDataSize =
DMA_PeripheralDataSize_HalfW
DMA_InitStructure.DMA_MemoryDataSize =
DMA_MemoryDataSize_HalfW
DMA_InitStructure.DMA_Mode =
DMA_Mode_C
DMA_InitStructure.DMA_Priority =
DMA_Priority_H
DMA_InitStructure.DMA_M2M =
DMA_Init(DMA1_Channel1,
&DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_InitStructure.ADC_Mode =
ADC_Mode_I
ADC_InitStructure.ADC_ScanConvMode =
ADC_InitStructure.ADC_ContinuousConvMode =
ADC_InitStructure.ADC_ExternalTrigConv =
ADC_ExternalTrigConv_N
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_R
ADC_InitStructure.ADC_NbrOfChannel =
2;&&&&& //##############&&&& 改了
ADC_Init(ADC1, &ADC_InitStructure);
//内部温度传感器& 添加这一句
ADC_TempSensorVrefintCmd(ENABLE);
//##############&&&& 改了
//################ Channel 10(电位器)
ADC_RegularChannelConfig(ADC1,
ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);
//###### 内部温度传感器& Channel 16 ###################
ADC_RegularChannelConfig(ADC1,
ADC_Channel_16, 2, ADC_SampleTime_55Cycles5);
& 使能ADC1的DMA请求映像
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
&& //使用之前一定要校准
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
最后附笔记:
阅读(...) 评论()

我要回帖

更多关于 正在检查目标单片机 的文章

 

随机推荐