基于STM32F407的DMA解析-ADC单通道DMA读取数据

目录

一:什么是DMA? 

1.DMA简介:

2.DMA数据流与通道:

3.工作原理 :

二:实验代码及实验效果

2.1  ADC基本配置:

2.2 DMA基本配置:

2.3 主函数:

2.4 实验结果——串口接收数据

 三:DMA代码详细解及注意事项

 3.1 ADC代码段:

3.2DMA代码段:


 

一:什么是DMA? 

1.DMA简介:

       DMA,全称为:Direct Memory Access,即直接存储器访问。DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。

      STM32F407ZGT6 有 2 个 DMA 控制器(DMA1 和 DMA2),共 16 个数据流(每个控制器 8 个),每一个 DMA 控制器都用于管理一个或多个外设的存储器访问请求。每个数据流有 8个通道(或称请求)。每个数据流通道都有一个仲裁器,用于处理 DMA 请求间的优先级。

2.DMA数据流与通道:

      每个DMA有八个数据流,而8个数据流中的每一个都连接到专用硬件 DMA 通道(请求),DMA 数据流请求之间的优先级可用软件编程(4 个级别:非常高、高、中、低),在软件优先级相同的情况下可以通过硬件决定优先级(例如,请求 0 的优先级高于请求 1),每个数据流也支持通过软件触发存储器到存储器的传输(仅限 DMA2 控制器),可供每个数据流选择的通道请求多达 8 个。此选择可由软件配置,允许几个外设启动 DMA请求。

      在设置DMA数据流与通道的时候要按照数据手册当中的对应关系进行配置。

3.工作原理 :

       在产生事件后,外设会向 DMA 控制器发送请求信号。DMA 控制器根据通道优先级处理该请求。只要 DMA 控制器访问外设,DMA 控制器就会向外设发送确认信号。外设获得 DMA 控制器的确认信号后,便会立即释放其请求。一旦外设使请求失效,DMA 控制器就会释放确认信号。如果有更多请求,外设可以启动下一个事务。 

二:实验代码及实验效果

2.1  ADC基本配置:

#include "adc.h"
#include "delay.h"		 


//初始化ADC															   
void  Adc_Init(void)
{    
    GPIO_InitTypeDef  GPIO_InitStructure;
	ADC_CommonInitTypeDef ADC_CommonInitStructure;
	ADC_InitTypeDef       ADC_InitStructure;
	
    /*使能 GPIOA ADC1 时钟*/
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 

    /*先初始化ADC1通道5 IO口*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);	  
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);	 
 
	/*ADC基本配置*/
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;//预分频4分频
    ADC_CommonInit(&ADC_CommonInitStructure);//初始化
	
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式	
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//关闭连续转换
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐	
    ADC_InitStructure.ADC_NbrOfConversion = 1;//1个转换在规则序列中 也就是只转换规则序列1 
    ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化
	ADC_Cmd(ADC1, ENABLE);//开启AD转换器	


    /*ADC1,ADC通道,480个周期,提高采样时间可以提高精确度*/
	ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_480Cycles );
    ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
    ADC_DMACmd(ADC1, ENABLE);
    /*使能指定的ADC1的软件转换启动功能	*/
	ADC_SoftwareStartConv(ADC1);	

}				  

2.2 DMA基本配置:

u32 ADC_ConvertedValue;

void Dma_Init(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); 
	/*外设基址为:ADC 数据寄存器地址*/
	DMA_InitStructure.DMA_PeripheralBaseAddr = ((u32)ADC1+0x4c);	
    /*存储器地址,实际上就是一个内部SRAM的变量*/
	DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&ADC_ConvertedValue;  
    / 数据传输方向为外设到存储器*/
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;	
	/* 缓冲区大小为,指一次传输的数据量*/
	DMA_InitStructure.DMA_BufferSize = 1;	
	/*外设寄存器只有一个,地址不用递增*/
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    /*存储器地址固定*/
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 
    /*外设数据大小为半字,即两个字节*/
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
    /*存储器数据大小也为半字,跟外设数据大小相同*/
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;	
	/*循环传输模式*/
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    /*DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响*/
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    /*禁止DMA FIFO,使用直连模式*/
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;  
    /*FIFO 大小,FIFO模式禁止时,这个不用配置*/	
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  
	/* 选择 DMA 通道,通道存在于流中*/
    DMA_InitStructure.DMA_Channel = DMA_Channel_0; 
    /*初始化DMA流,流相当于一个大的管道,管道里面有很多通道*/
	DMA_Init(DMA2_Stream0, &DMA_InitStructure);
	/*使能DMA流*/
    DMA_Cmd(DMA2_Stream0, ENABLE);

}

2.3 主函数:

int main(void)
{ 
	extern u32 ADC_ConvertedValue;
	float temp;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);    //初始化延时函数
	uart_init(115200);	//初始化串口波特率为115200
	Adc_Init();         //初始化ADC
    Dma_Init();   
	while(1)
	{ 
    printf ("V:%d\r\n",ADC_ConvertedValue);
		delay_ms(500);	
	}
}

2.4 实验结果——串口接收数据

分别对应引脚悬空、连接GND、连接3v3时的输出数据

 

 三:DMA代码详细解及注意事项

 3.1 ADC代码段:

相比无DMA的ADC配置代码,这里要多配置以下代码:

/*开启ADC DMA 请求*/
ADC_DMACmd(ADC1, ENABLE);
/*启用或禁用上次传输后的ADC DMA请求*/
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

3.2DMA代码段:

       首先要关注传输方向,这里我们需要将ADC转换完成的数据传递到cpu内部寄存器,所以为外设到寄存器。

/*数据传输方向为外设到存储器*/	
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;	

       其次要关注寄存器地址与外设地址,寄存器地址在这里为变量,所以取地址。

/*存储器地址,实际上就是一个内部SRAM的变量	*/
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&ADC_ConvertedValue;  

       外设在这里有对应的寄存器,地址为基地址+偏移地址,如果要更改ADC通道,要修改相应的寄存器地址,可以在中文参考手册里查找。

/*外设基址为:ADC 数据寄存器地址*/
DMA_InitStructure.DMA_PeripheralBaseAddr = ((u32)ADC1+0x4c);	

       寄存器地址与外设地址,在这里我们只传递了ADC1的数据,单对单,所以两个地址都不需要递增

/*外设寄存器只有一个,地址不用递增*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/*存储器地址固定*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 

  • 8
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
### 回答1: STM32F407ADC DMA FFT是一种基于STM32F407芯片的数字信号处理技术,主要用于实现高速数据采集、处理和分析。其中,ADC代表模拟数字转换器,DMA代表直接存储器访问,FFT代表快速傅里叶变换。通过将这些技术结合起来,可以实现高效的数据采集和处理,从而满足各种应用场景的需求。 ### 回答2: STM32F407ADCDMA模块是这一系列微控制器中最先进的部分之一。ADC是用于从模拟输入信号中读取数据的模块,而DMA则是一种用于高速数据传输的技术。对于实现实时信号处理的应用程序来说,有一个FFT(快速傅里叶变换)模块非常有用。FFT可以将模拟信号转换为其在频域内的表示,这是许多应用程序所必需的。 在STM32F407中,ADCDMA可以结合使用,以实现高速的数据读取和传输。通过使用DMA,可以让CPU完成其他任务,而ADCDMA模块则将数据直接传输到内存中,从而免去了CPU的干预。这可以极大地提高系统的效率。 当然,FFT模块也可以与ADCDMA结合使用。使用FFT算法可以对模拟信号进行处理,以提取其在不同频率上的成分。但是,FFT的计算需要大量的计算能力和内存空间。因此,对于STM32F407这样的嵌入式系统来说,需要使用高效的FFT库和优化的算法。 总之,STM32F407ADCDMA和FFT模块可以协同工作,以实现高速数据采集、传输和处理。这使得这种微控制器非常适合于实现实时信号处理的应用程序。同时,需要注意的是,这一系列模块的使用需要仔细的设计和实现,以保证系统的稳定性和可靠性。 ### 回答3: STM32F407是一款基于ARM Cortex-M4内核的微控制器,具有丰富的外设和高性能。其中包括ADC(模拟-数字转换器)和DMA(直接存储器访问)模块。 ADC模块可以将模拟信号转换为数字信号,用于数据采集。DMA模块可以直接将采集到的数据存储到内存中,减少了CPU的负担。FFT(快速傅立叶变换)是一种数字信号处理算法,用于将时域信号转换为频域信号,常用于音频处理、图像处理、通信等领域。 在STM32F407上,通过ADCDMA和FFT模块结合使用,可以实现实时的数据采集和处理。首先,ADC模块将模拟信号转换为数字信号,DMA模块将采集到的数据存储到内存中,FFT模块对存储的数据进行处理,获得频域信息。这些信息可以用于进行频谱分析、滤波、信噪比评估等。 在具体的应用中,可以使用不同的采样率、精度、采样通道数等参数进行调节,以满足不同的需求。此外,STM32F407的灵活性和可编程性,使得开发者可以自定义算法、优化代码,进一步提高系统的性能和效率。 总之,STM32F407ADC DMA FFT的组合,为实时信号采集和处理提供了高效、可靠的解决方案。通过合理地配置参数和算法,可以应用于各种领域,为我们的生产和生活带来便利和效益。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值