## STM32F103的光照、烟雾MQ2、有毒气体MQ135的ADC配置(寄存器版与库函数版

STM32F103的光照、烟雾MQ2、有毒气体MQ135的ADC配置(寄存器版与库函数版

//#include "adc.h"

#if 0  //寄存器编程
/*******************************************************
*函数名:void ADC1_Init(void)
*功  能:ADC1初始化
*参  数:无
*返  回:无
*备  注:
传感器         引脚    ADC1通道号
 光照          PA3     通道3 
 MQ2烟雾       PA2     通道2
 MQ135有害     PA1     通道1
********************************************************/
void ADC1_Init(void)  
{
	/* 1.时钟配置 */
	RCC->APB2ENR |=1<<2;  //开启PA口的时钟
    RCC->APB2ENR |=1<<9;  //开启ADC1的时钟
	RCC->CFGR &=~(3<<14); //清零
	RCC->CFGR |= (2<<14); //ADC时钟设置为6分频 72/6=12M .ADC时钟不能大于14M
    RCC->APB2RSTR  |=  1<<9;  //开启复位ADC1的接口
    RCC->APB2RSTR  &=~(1<<9); //关闭ADC1复位
	/* 2.GPIO配置 */
    GPIOA->CRL &= 0xffff000f; //PA1、PA2、PA3设置为模拟输入
	/* 3.ADC配置 */
	ADC1->CR1 &= ~(1<<23);  //禁用规则通道的模拟看门狗  
	ADC1->CR1 &= ~(1<<22);  //禁用注入通道的模拟看门狗 
	ADC1->CR1 &= ~(0XF<<16);//独立模式
	ADC1->CR1 &= ~(0X7<<13);//选1个通道
	ADC1->CR1 &= ~(1<<8);   //不用扫描模式
	ADC1->CR1 &= ~(1<<5);   //不使用ADC的任何中断 
	
	ADC1->CR2 |= 1<<20; 		//规则通道启用外部触发事件 
	ADC1->CR2 |= 7<<17; 		//规则通道启用软件触发 
	ADC1->CR2 &=~(1<<15);  //不启用注入通道
	ADC1->CR2 &=~(1<<11);  //得到的AD值采用右对齐方式 
	ADC1->CR2 &=~(1<<8);   //不启用DMA
   
	ADC1->SMPR2 &=~(7<<3);  //设置通道1的采样时间。
	ADC1->SMPR2 |= (7<<3);  //采样周期设置为239.5个周期 +12.5

	ADC1->SQR1 &= ~(0XF<<20); //设置为只有一个转换
	ADC1->SQR1 |=  ( 0 <<20);

	ADC1->CR2 |= 1<<0; //ADC从掉电模式,变为上电模式

	ADC1->CR2 |= 1<<3; // 初始化校准寄存器
	while (ADC1->CR2 & (1<<3)); //等待校准寄存器初始化完成

	ADC1->CR2 |= 1<<2; //开始校准        
	while (ADC1->CR2 & (1<<2)); //等待校准完成
}


/*******************************************************
*函数名:u16 ADC1_Get(u8 ch)  
*功  能:按通道号获取AD值
*参  数:通道号
*返  回:AD值
*备  注:
传感器        引脚    ADC1通道号
光照          PA3     通道3 
MQ2烟雾       PA2     通道2
MQ135有害     PA1     通道1
********************************************************/
u16 ADC1_ReadData(u8 ch)     
{  	
	ADC1->SQR3 &= ~(0X1F<<0); //设置通道3为第一个转换
    ADC1->SQR3 |= ch; // 通道号
	ADC1->CR2|= 1<<22;  //开启规则转换通道,这时才开始转换				
    while (!(ADC1->SR & (1<<1))); //等待AD转换完成
    return ADC1->DR; //返回AD值.
}  


#else  //库函数编程

/*******************************************************
*函数名:void ADC1_Init(void)
*功  能:ADC1初始化
*参  数:无
*返  回:无
*备  注:
传感器         引脚    ADC1通道号
 光照          PA3     通道3 
 MQ2烟雾       PA2     通道2
 MQ135有害     PA1     通道1
********************************************************/
void ADC1_Init(void)  
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef  ADC_InitStructure;
	/* 1.时钟配置 */	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启PA口的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//开启ADC1的时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div6); //ADC1时钟6分频(小于等于14MHz)
	/* 2.GPIO配置 */	
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN; // 模拟输入                  
	GPIO_Init(GPIOA, &GPIO_InitStructure);                           
	/* 3.ADC配置 */
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE; //非扫描模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//每次转换通道数目
	ADC_Init(ADC1,&ADC_InitStructure); //初始化ADC1
	ADC_Cmd(ADC1,ENABLE); //使能ADC
	ADC_ResetCalibration(ADC1);	//使能复位校准
	while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准结束
	ADC_StartCalibration(ADC1);	//开启AD校准
	while(ADC_GetCalibrationStatus(ADC1));//等待校准结束
	
	//ADC_SoftwareStartConvCmd(ADC1,ENABLE);	
}

/*******************************************************
*函数名:u16 ADC1_Get(u8 ch)  
*功  能:按通道号获取AD值
*参  数:通道号
*返  回:AD值
*备  注:
传感器        引脚    ADC1通道号
光照          PA3     通道3 
MQ2烟雾       PA2     通道2
MQ135有害     PA1     通道1
********************************************************/
u16 ADC1_ReadData(u8 ch)     
{  	
	ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_1Cycles5);            
    ADC_SoftwareStartConvCmd(ADC1,ENABLE);	
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));
	return ADC_GetConversionValue(ADC1);
}  

#endif


//中值平均滤波
#define N 10 //采样个数

u16 ADC1_ReadAvgData(u8 ch)
{
	u16 sum=0;
	u16 ADC1_ValueBuf[N];
	for(u8 i=0;i<N;i++)
	{
		ADC1_ValueBuf[i] = ADC1_ReadData(ch);
	}
	//从小到大排列(冒泡法)
	for(u8 j=0;j<N-1;j++) // 趟数 
	{
		for(u8 i=0;i<N-1-j;i++) // 一趟比较的次数 
		{
			if(ADC1_ValueBuf[i]>ADC1_ValueBuf[i+1]) // 把最大值往后放 
			{
				//交换 
				u16 temp;
				temp = ADC1_ValueBuf[i];
				ADC1_ValueBuf[i] = ADC1_ValueBuf[i+1];
				ADC1_ValueBuf[i+1] = temp;
			}
		}
	}
	for(u8 i=2;i<N-2;i++) // 去掉最低两位与最高两位
	{
		sum+=ADC1_ValueBuf[i];
	}
	return sum/(N-4); // 求平均值
}

u16 Light_Data(void)//光照  
{
	u16 ad;
	ad=ADC1_ReadAvgData(3); 		
	ad=(4095-ad)*1000/4095;
	return ad;
}


u16 MQ2_Data(void)//烟雾 
{
	u16 ad;
	ad=ADC1_ReadAvgData(2); 		
	ad=ad*100/4095;
	return ad;
}



u16 MQ135_Data(void)//有害气体
{
	u16 ad;
	ad=ADC1_ReadAvgData(1); 		
	ad=ad*100/4095;
	return ad;
}

  • 10
    点赞
  • 102
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,而MQ2是一种常见的烟雾传感器模块。MQ2烟雾传感器可以检测到可燃气体、烟雾和一些有毒气体的浓度。它通过测量气体中的电阻来判断气体浓度,输出模拟电压信号。在使用STM32F103C8T6与MQ2传感器进行烟雾浓度检测时,你可以按照以下步骤进行: 1. 连接硬件:将MQ2传感器模块与STM32F103C8T6微控制器连接。通常,MQ2传感器模块包含VCC(供电)、GND(地)、DO(数字输出)和AO(模拟输出)四个引脚。你需要将VCC引脚连接到STM32F103C8T6的3.3V电源引脚,GND引脚连接到STM32F103C8T6的地引脚,DO引脚连接到STM32F103C8T6的任意数字输入引脚(例如PA0或PB0),AO引脚连接到STM32F103C8T6的任意模拟输入引脚(例如PA1或PB1)。 2. 配置GPIO:在STM32F103C8T6上配置相应的GPIO引脚作为输入。你可以使用STM32的开发工具(如Keil或STM32CubeIDE)来进行配置。 3. 读取模拟值:通过配置ADC(模数转换器)模块,将模拟输入引脚连接到相应的ADC通道。然后,你可以使用ADC模块来读取MQ2传感器的模拟输出值。 4. 转换浓度:根据MQ2传感器的数据手册,使用合适的算法将模拟输出值转换为对应的烟雾浓度。这个转换过程可能因传感器型号和供应商而有所不同,所以建议参考MQ2传感器的相关文档来获取准确的转换公式。 5. 处理数据:你可以使用STM32F103C8T6上的其他功能(如串口通信或显示屏)来处理和展示烟雾浓度数据,例如将数据发送到计算机上进行进一步分析或在液晶屏上显示。 请注意,以上步骤只是一个大致的指导,并不具体到每个细节。具体的实现细节还取决于你所使用的开发工具和库。你可能需要参考STM32F103C8T6和MQ2传感器的相关文档和示例代码来完成整个系统的搭建和编程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值