stm32f030采用轮询方法采集ADC多通道数据

参考链接:关于STM32F0系列多路ADC单独采样数据相同问题的处理
文中博主已经详细说明了采集ADC多通道数据的方法,但是代码有一处BUG,运行时容易造成死循环。

查看STM32F030参考手册

12.12.8章节ADC 通道选择寄存器 (ADC_CHSELR)

代码中涉及配置到CHSELR寄存器前,必须要确保ADC_CR寄存器的位2:ADSTART=0 时 ( 确定无进行中的转换 ) 才允许改写这些位。
在这里插入图片描述

12.12.3ADC 控制寄存器 (ADC_CR)

位 4 ADSTP: ADC 停止转换命令:该位写1停止ADC转换,使得ADSTART位为0,从而确保ADC通道能成功切换。
在这里插入图片描述

改正代码如下:


void adc_init(void){
    
    
	ADC_InitTypeDef     ADC_InitStructure;
	GPIO_InitTypeDef    GPIO_InitStructure;
	/* GPIOC Periph clock enable */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);   //打开GPIO时钟
	/* ADC1 Peripheral clock enable */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE); //打开ADC1时钟
	
	/*Initialize GPIO 对应ADC_Channel_10到ADC_Channel_13*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;       //模拟输入模式
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;  //悬空
	GPIO_Init(GPIOC, &GPIO_InitStructure);             //初始化IO
	
	/* ADCs DeInit */  
	ADC_DeInit(ADC1);                                  
	/* Initialize ADC structure */
	ADC_StructInit(&ADC_InitStructure);
	/* Configure the ADC1 in continuous mode withe a resolution equal to 12 bits  */
	ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;    //12位精度
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 			//单次转换 每次转换需要start
	ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;   //软件触发
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                        //右对齐
	ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;             //Backward
	ADC_Init(ADC1, &ADC_InitStructure); 
//	ADC_OverrunModeCmd(ADC1, ENABLE);     //使能数据覆盖模式
	ADC_ChannelConfig(ADC1, ADC_Channel_11 , ADC_SampleTime_239_5Cycles);         //通道选择
	/* ADC Calibration */
	ADC_GetCalibrationFactor(ADC1);                                               //ADC校准
	/* Enable the ADC peripheral */
	ADC_Cmd(ADC1, ENABLE);                                                        //打开ADC
	/* Wait the ADRDY flag */
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY));                              //等待ADC准备完成
	/* ADC1 regular Software Start Conv */ 
//	ADC_StartOfConversion(ADC1);   //单次转换需要每次启动
}

/**
  * @brief  Returns the last ADCx conversion result voltage data for ADC channel.  
* @param  ADC_Channel_x:ADC通道号
  * @retval The Data conversion average value(v).
  */
float get_ADC_AvrVoltageValue(uint32_t ADC_Channel_x,uint8_t times) {
    
    
	float ADC1ConvertedValue = 0.0;
	//停止转换 对应ADC_StopOfConversion(ADC_TypeDef* ADCx)
	ADC1->CR |= (uint32_t)ADC_CR_ADSTP;          
	ADC_ChannelConfig(ADC1, ADC_Channel_x , ADC_SampleTime_239_5Cycles);
	//只选择ADC_Channel_x这个通道有效
	ADC1->CHSELR =ADC_Channel_x;
	//等待准备完成
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY) == RESET);
	//ADC_StartOfConversion(ADC1);
	for(int i=0;i<times;i++){
    
    
		/* ADC1 regular Software Start Conv */ 
		ADC_StartOfConversion(ADC1);
		/* Wait EOC flag */
		while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
		/* Get ADC1 converted data */
		ADC1ConvertedValue += ADC_GetConversionValue(ADC1);
	}
	return (float)(ADC1ConvertedValue *3.3)/0xFFF/times;
}

猜你喜欢

转载自blog.csdn.net/weixin_42518229/article/details/106648637