STM32F1xx 系列 多通道ADC DMA采集与非DMA采集

版权声明:本文为博主原创文章,未经博主允许要转就转吧。 https://blog.csdn.net/cleverhorse/article/details/84786131

ADC 多通道 DMA 采集

#include "ADcx.h"
#include <stdio.h>
#include "stm32f10x.h"
#include "stm32f10x_rcc.h" 
#include "stm32f10x_adc.h"
#include "stm32f10x_gpio.h"

void ADcDMA_Configuration(void);
u16 AD_Value[8][8]; //ADC数据缓存
//初始化
void ADcx_Init(){
	ADC_InitTypeDef ADC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);//使能ADC时钟和相关GPIO时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC时钟72M/6=12,最大不能超过14
	
	//GPIO配置
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_Init(GPIOC,&GPIO_InitStructure);

	ADC_DeInit(ADC1);//复位ADC
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//独立工作模式
	ADC_InitStructure.ADC_ScanConvMode=ENABLE;//启动多通道扫描(单通道不要打开)
	ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//启动连续转换
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//软件触发
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//右对齐
	ADC_InitStructure.ADC_NbrOfChannel=8;//扫描8个通道
	ADC_Init(ADC1,&ADC_InitStructure);//根据参数初始化ADC1

	//指定8个通道的扫描顺讯
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_10,5,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_11,6,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_12,7,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_13,8,ADC_SampleTime_239Cycles5);
	
	ADC_DMACmd(ADC1,ENABLE);
	ADC_Cmd(ADC1,ENABLE);//使能ADC
	ADC_ResetCalibration(ADC1);//使能复位校准
	while(ADC_GetResetCalibrationStatus(ADC1));//等待校准完成
	ADC_StartCalibration(ADC1);//使能ADC校准
	while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//启动一次ADC转换
	
	ADcDMA_Configuration();
	//测试
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA搬移
}
void ADcDMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel1); //复位DMA通道,ADC1专用DMA通道为DMA1-1
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&ADC1->DR; //DMA从ADC1的DR处搬移
DMA_InitStructure.DMA_MemoryBaseAddr =(u32)&AD_Value; //搬移到AD_Value处
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//目的地址为内存
DMA_InitStructure.DMA_BufferSize = 64; //单次搬移数目
DMA_InitStructure.DMA_PeripheralInc =DMA_PeripheralInc_Disable; //搬移地址不累计
DMA_InitStructure.DMA_MemoryInc =DMA_MemoryInc_Enable; //目的地址逐次加1
DMA_InitStructure.DMA_PeripheralDataSize =DMA_PeripheralDataSize_HalfWord; //外围数据大小为半个字节(16位)
DMA_InitStructure.DMA_MemoryDataSize =DMA_MemoryDataSize_HalfWord; //内存数据大小为半个字节(16位)
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //设置循环工作模式
DMA_InitStructure.DMA_Priority =DMA_Priority_High; //设置DMA1_Channel1高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
}

非DMA模式

#include "ADcx.h"
#include <stdio.h>
#include "stm32f10x.h"
#include "stm32f10x_rcc.h" 
#include "stm32f10x_adc.h"
#include "stm32f10x_gpio.h"

void ADcDMA_Configuration(void);
u16 AD_Value[8][8]; //ADC数据缓存
//初始化
void ADcx_Init(){
	ADC_InitTypeDef ADC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);//使能ADC时钟和相关GPIO时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC时钟72M/6=12,最大不能超过14
	
	//GPIO配置
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_Init(GPIOC,&GPIO_InitStructure);

	ADC_DeInit(ADC1);//复位ADC
	ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;//独立工作模式
	ADC_InitStructure.ADC_ScanConvMode=ENABLE;//启动多通道扫描(单通道不要打开)
	ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//启动连续转换
	ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//软件触发
	ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//右对齐
	ADC_InitStructure.ADC_NbrOfChannel=8;//扫描8个通道
	ADC_Init(ADC1,&ADC_InitStructure);//根据参数初始化ADC1

	//指定8个通道的扫描顺讯
	ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_10,5,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_11,6,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_12,7,ADC_SampleTime_239Cycles5);
	ADC_RegularChannelConfig(ADC1,ADC_Channel_13,8,ADC_SampleTime_239Cycles5);
	
	ADC_Cmd(ADC1,ENABLE);//使能ADC
	ADC_ResetCalibration(ADC1);//使能复位校准
	while(ADC_GetResetCalibrationStatus(ADC1));//等待校准完成
	ADC_StartCalibration(ADC1);//使能ADC校准
	while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);//启动一次ADC转换
}
//获取ADC通道的值
void  ADCValue(void)
{
	u16 tempADC[8];//ADC数据存放地
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[0]=ADC_GetConversionValue(ADC1);
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[1]=ADC_GetConversionValue(ADC1);

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[2]=ADC_GetConversionValue(ADC1);
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[3]=ADC_GetConversionValue(ADC1);
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[4]=ADC_GetConversionValue(ADC1);

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[5]=ADC_GetConversionValue(ADC1);

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[6]=ADC_GetConversionValue(ADC1);

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[7]=ADC_GetConversionValue(ADC1);

	ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能ADC转换
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//等待转换完成
	tempADC[8]=ADC_GetConversionValue(ADC1);
}
读取指定通道值
uint16_t read_adc_value(uint8_t ch)   
{
    uint16_t adc_val = 0;
    
    ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );    
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);        
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )){};
    
    adc_val = ADC_GetConversionValue(ADC1);    
    
    return adc_val;

}

关于间断模式采集介绍
ADC_DiscModeChannelCountConfig(ADC1, 1); //对 ADC 规则组通道配置间断模式
ADC_DiscModeCmd(ADC1, ENABLE); //使能指定的 ADC 规则组通道的间断模式

这两个库函数就是配置ADC为间断的模式,
配置为间断模式之后,每一次软件转换启动后,读取的就是相应转换的通道数据。

ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能或者失能指定的ADC的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); //等待转换完成
adc1 = ADC_GetConversionValue(ADC1); //返回最近一次 ADCx 规则组的转换结果

猜你喜欢

转载自blog.csdn.net/cleverhorse/article/details/84786131