多路ADC的采集——stm32

         在对实际应用过程中,ADC的采集大多是多个通道同时采集的,比如同时采集多个传感器的数据,就可能需要我们配置多个通道的ADC采集了,而多通道的ADC采集大多用到了DMA,笼统的讲通过DMA来传输数据不经过CPU,可以有效的为CPU减负,我们在使用时只需要通过CPU完成相应的初始化,而传输本身呢,是由DMA来进行的,而对于采集到的不同通道的数据我们只需要将其放入指定的数组便可以获得到不同通道具体的数据了。

DMA通道配置过程:
1、在DMA_CPARx寄存器中设置外设寄存起的地址,发生外设数据请求时,这个地址将是数据传输的源或目标。
2、在DMA_CMARx寄存器中设置数据存储寄存器的地址,发生外设数据请求时,传输的数据将从这个地址读出或写入这个地址。
3、在DMA_CNDTRx寄存器中设置要传输的数据量。在每个数据传输后,这个数值递减。
4、在DMA_CCRx寄存器的PL[1:0]位中设置优先级。
5、在DMA_CCRx寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外设和存储器的数据宽度、传输一半产生中断,或
     传输完成产生中断。
6、设置DMA_CCRx寄存器的ENABLE位,启动该通道。

具体的配置过程我们通过代码来 展示

首先定义一个数组以便我们存放数据,数组大小按照实际需求即可。

u16 ADC_convered[2]={0,0};

然后是io口的初始化(我这儿把ADC的时钟也直接使能了) 

static void ADC_GPIO_CONFIG(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1	, ENABLE );	//使能 
    ADC1通道时钟
	//PA1 作为模拟通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//初始化两个GPIO
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
}

再接下来便是重头戏了——DMA和ADC的初始化(有些部分是需要配置多个通道的)

static void ADC_MODE_CONFIG_(void)
{ 	
	
	DMA_InitTypeDef DMA_InitInstructure;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
	DMA_DeInit(DMA1_Channel1);//复位
	DMA_InitInstructure.DMA_PeripheralBaseAddr =(u32)(&(ADC1->DR));//配置外设的基址,取adc 
    数据寄存器的地址
	DMA_InitInstructure.DMA_MemoryBaseAddr = (u32)ADC_convered;//把DMA的数据存入数组
	DMA_InitInstructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设到DMA
	DMA_InitInstructure.DMA_BufferSize = 2;//2个通道
	DMA_InitInstructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//
	DMA_InitInstructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitInstructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitInstructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitInstructure.DMA_Mode = DMA_Mode_Circular;//不断地传输,有数据就传输
	DMA_InitInstructure.DMA_Priority = DMA_Priority_High;//DMA优先级
	DMA_InitInstructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel1,&DMA_InitInstructure);
	DMA_Cmd(DMA1_Channel1,ENABLE);//使能DMA请求
	
	
	
	
	
	ADC_InitTypeDef ADC_InitStructure; 
	ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立 
    模式
	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数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 2;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄 
    存器   




	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
		//设置指定ADC的规则组通道,一个序列,采样时间
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1,1, ADC_SampleTime_239Cycles5 );	 
      //ADC1,ADC1通道1,采样时间为239.5周期
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2,2, ADC_SampleTime_239Cycles5 );	 
     //ADC1,ADC1通道2,采样时间为239.5周期

    ADC_DMACmd(ADC1,ENABLE);	
    ADC_Cmd(ADC1,ENABLE);

	
	ADC_ResetCalibration(ADC1);	//使能复位校准  
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
 
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	
	 
	//while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束


}				  

然后把初始化的程序整到一块,方便调用

void Adc_Init()
{
   ADC_GPIO_CONFIG();
   ADC_MODE_CONFIG_();
}

接下来便是主函数部分了,主函数主要看要实现什么样的功能,初始化之后其实也就是把采集到的数据展示或设置阈值再进行相应的操作。

extern u16 ADC_convered[2];

int main(void)
{ 
   delay_init();
	//uart_init(9600);//串口初始化为9600,串口打印需要对其进行初始化
   float temp[2];
   delay_init();
   Oled_Init();
   Adc_Init();

	float value;
	float value1;
	char buf[5];
	char buf1[5];

	while(1)
	{
	    temp[0]=(float)ADC_convered[0]/4096*3.3;
		temp[1]=(float)ADC_convered[1]/4096*3.3;//结果-电压转换
		
		//printf("\r\n THE AD1 is = %f V \r\n",temp[0]);
		//printf("\r\n THE AD2 is = %f V \r\n",temp[1]);
	
        value = temp[0];
		sprintf(buf,"%f",value);
		Oled_Display_String(0,0,buf);//显示电压值
		
		value1 = temp[1];  
	    sprintf(buf1,"%f",value1);	
		Oled_Display_String(2,0,buf1);//显示电压值
		
		//Oled_Display_String(4,0,buf1);//	
		
		delay_ms(500);//延时了一小会儿,要不数据变化太快,看的心烦
        //我这儿是把电压值显示在了oled上
	}	  
}	

如有错误还请指出,谢谢

 

  • 27
    点赞
  • 188
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
STM32是一种基于ARM Cortex-M核心的32位微控制器系列,具有多个模拟到数字转换器(ADC)通道,可以同时采集多路信号。 STM32微控制器系列中的大多数型号都配备了多个ADC通道,可以同时采集不同的信号源。这些通道可以配置为单独使用或者以定时或事件触发的方式进行同步采集。 使用STM32多路ADC采集功能时,我们需要了解以下几个方面: 1. ADC通道配置:首先,我们需要确定采集的信号源数目,并选择合适的ADC通道进行配置。每个ADC通道都有自己的寄存器和控制位用于配置采样时间、分辨率和触发模式等参数。 2. 采样时间和时钟频率:采样时间指的是ADC模块在每次采样过程中对输入信号进行采样的持续时间。时钟频率则是ADC模块的工作频率,可以根据系统需求进行设置。 3. 触发模式:ADC可以通过定时器或外部事件触发进行采样。在多路ADC采集中,我们可以配置多个ADC通道使用同一个触发源进行同步采样。 4. 中断或DMA传输:采集到的数据可以通过中断或DMA传输到内存中,以便后续处理或分析。中断方式可以在每次采样结束后触发中断,而DMA传输可以在一次或多次采样结束后自动传输数据。 通过合理配置和使用STM32多路ADC采集功能,我们可以同时采集多个信号源,并根据实际需求进行相应的处理和分析。这在很多需要对多个信号同时进行监测和控制的应用中非常有用,例如工业自动化、仪器仪表和数据采集等领域。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值