STM32微项目10:使用DMA实现多通道ADC数据采集和转移

一、微项目实现目标:

由于ADC多通道采集在规则组中只有一个寄存器CR,实际上在多通道采集时刻,需要把每一个同都的数据及时传出,否则上一个通道的数据会被当前通道的数据给覆盖掉。

二、微项目硬件配置需求:

 stm32F103C8T6核心板一块

0.96寸OLED显示,用于显示计数

三、前置知识:

1,传输数据流:

外部GPIO采集—-ADC转化执行—–存放到CR寄存器中—–触发DMA转移信号—-DMA硬件触发开始转移数据—–从外设寄存器DR转移到SRAM的数组中

2,

四、代码逻辑分析:

① 启动GPIO时钟、启动DMA1时钟、启动ADC1时钟(由于ADC最大14MHZ,还需要进行一次分频处理);

②初始化GPIO模块,本实验采用4路,分别是PA0-PA3上;配置模拟输入模式

③配置ADC输入通道开启,使用ADC_Channel_0到ADC_Channel_3,分别放置在规则组1-3通道上;

④配置ADC模块,

需要注意:1)触发模式—硬件触发;2)开启循环模式,转化完成后,重新开下一轮转化;3)开启扫描模式,表示转化序列组中依次进行转化;4)转化通道数配置4

⑤DMA通道配置。

需要注意:1)数据源起始地址选择(uint32_t)&ADC1->DR;2)数据源采用16位的半字传输;3)不自增模式,即一直在这寄存器内取数据;

4)接受方地址选择(uint32_t)arr,存放到SRAM数组中;5)接收方采用16位半字接受;6)启动自增模式;

7)配置计数器值4位;8)传输模式,采用循环传输;其余正常配置

⑥开启ADC触发DMA通道,以完成一个通道后,产生DMA转移的硬件请求信号;

⑦开启ADC电源和DMA电源

⑧配置ADC校准

⑨软件触发启动ADC

五、代码示例:

① 启动GPIO时钟、启动DMA1时钟、启动ADC1时钟(由于ADC最大14MHZ,还需要进行一次分频处理);

//打开ADC1时钟 和GPIO时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//配置ADC1的分频,ADC最高支持14mhz
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	//打开DMA1时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);

②初始化GPIO模块,本实验采用4路,分别是PA0-PA3上;配置模拟输入模式

/初始化GPIO模块,模拟输入模式
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0 |GPIO_Pin_1 |GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOA,&GPIO_InitStruct);

③配置ADC输入通道开启,使用ADC_Channel_0到ADC_Channel_3,分别放置在规则组1-3通道上;

//配置ad输入通道
	ADC_RegularChannelConfig( ADC1, ADC_Channel_0 , 1, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig( ADC1, ADC_Channel_1 , 2, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig( ADC1, ADC_Channel_2 , 3, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig( ADC1, ADC_Channel_3 , 4, ADC_SampleTime_55Cycles5);

④配置ADC模块,

需要注意:1)触发模式—硬件触发;2)开启循环模式,转化完成后,重新开下一轮转化;3)开启扫描模式,表示转化序列组中依次进行转化;4)转化通道数配置4

//初始化AD模块
	ADC_InitTypeDef  ADC_InitStruct;
	ADC_InitStruct.ADC_ContinuousConvMode=ENABLE;//循环模式
	ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right ;//转化后在寄存器内右对齐
	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None ;//软件触发,不使用硬件触发转化
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;//独立模式
	ADC_InitStruct.ADC_NbrOfChannel=4;
	ADC_InitStruct.ADC_ScanConvMode=ENABLE;//扫描模式
	ADC_Init( ADC1, &ADC_InitStruct);

⑤DMA通道配置。

需要注意:1)数据源起始地址选择(uint32_t)&ADC1->DR;2)数据源采用16位的半字传输;3)不自增模式,即一直在这寄存器内取数据;

4)接受方地址选择(uint32_t)arr,存放到SRAM数组中;5)接收方采用16位半字接受;6)启动自增模式;

7)配置计数器值4位;8)传输模式,采用循环传输;其余正常配置

/DMA初始化
	DMA_InitTypeDef  DMA_InitStruct;
	DMA_InitStruct.DMA_PeripheralBaseAddr=(uint32_t)&ADC1->DR;
	DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
	DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	
	DMA_InitStruct.DMA_MemoryBaseAddr=(uint32_t)arr;
	DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord ;
	DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;
	
	DMA_InitStruct.DMA_BufferSize=4;//传输计数器的值
	DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC ;//方向
	DMA_InitStruct.DMA_M2M=DMA_M2M_Disable ;//存储器到存储器、存储器到外设

	DMA_InitStruct.DMA_Mode=DMA_Mode_Circular ; 
	//是否循环传输;在存储器到存储器模式下,不可循环传输
	
	DMA_InitStruct.DMA_Priority=DMA_Priority_Medium  ;
	DMA_Init( DMA1_Channel1, &DMA_InitStruct);

⑥开启ADC触发DMA通道,以完成一个通道后,产生DMA转移的硬件请求信号;

	//开启ADC-DMA硬件触发
	ADC_DMACmd( ADC1,ENABLE);

⑦开启ADC电源和DMA电源

	//开启adc电源
	ADC_Cmd(ADC1,ENABLE);
	//开启DMA电源
	DMA_Cmd(DMA1_Channel1, ENABLE);

⑧配置ADC校准

	//ADC校准
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1)==SET);//完成后会被硬件置为reset
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1)==SET);
	

⑨软件触发启动ADC

ADC_SoftwareStartConvCmd( ADC1, ENABLE);//软件触发ADC转换

物联沃分享整理
物联沃-IOTWORD物联网 » STM32微项目10:使用DMA实现多通道ADC数据采集和转移

发表评论