STM32第十二课:ADC检测烟雾浓度(MQ2)

文章目录


需求

使用ADC将MQ2模块检测到的烟雾浓度模拟量转化为数字量。

最后,将实时检测的结果显示在串口上。


一、MQ-2 气体传感器

特点

广泛的探测范围,高灵敏度,快速响应恢复,优异的稳定性,寿命长以及简单的驱动电路。

应用

可用于家庭和工厂的气体泄漏监测装置, 适宜于液化气、丁烷、丙烷、甲烷、酒精、氢气、烟雾等的探测。

电路及引脚


二、实现流程

由于该模块的实现流程和ADC光照采集几乎一样,下面使用库函数的方式来编写。

1.开时钟,分频,配IO

该模块使用的引脚为PC1/ADC123_IN11,所以接下来我们要配置PC1。

烟雾检测模块是获得一个模拟量,所以接引脚模式配置为模拟输入。

代码如下:

c 复制代码
	//开时钟ADC1和PC
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6); 
	//配置GPIO口
	GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//MQ2
    GPIO_Init(GPIOC, &GPIO_InitStructure);

2.配置ADC的工作模式

和光照检测一样,直接改成库函数就行。

代码如下(示例):

c 复制代码
	ADC_InitTypeDef ADC_InitStruct={0};  //
	ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC独立模式
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//选择软件SWSTART位触发
	ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//连续还是单次模式
	ADC_InitStruct.ADC_ScanConvMode = DISABLE;//关闭扫描
	ADC_InitStruct.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1,&ADC_InitStruct);
	ADC_Cmd(ADC1, ENABLE);

3.配置通道

这里使用库函数编写就很简单了,直接一个函数就解决了。

输入参数 1 ADCx:x 可以是 1 或者 2 来选择 ADC 外设 ADC1 或 ADC2

输入参数 2 ADC_Channel:被设置的 ADC 通道

输入参数 3 Rank:规则组采样顺序。取值范围 1 到 16。

输入参数 4 ADC_SampleTime:指定 ADC 通道的采样时间值

c 复制代码
ADC_RegularChannelConfig(ADC1, ADC_Channel_11,1, ADC_SampleTime_239Cycles5);

4.复位,AD校准

没什么好说的,该部分可有可无,想严谨点的话就加上。

c 复制代码
	ADC_ResetCalibration(ADC1);//复位
	  while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);//AD校准
	  while(ADC_GetCalibrationStatus(ADC1));	

5.数值的获取

依旧是先转换一次,再while等待转换完成,最后读取打印。

c 复制代码
void Get_Smoke_Value()
{
	uint16_t Smoke=0;
	//让规则通道转换一次
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	//ADC1->CR2 |= 0x01<<22;
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == 0)//判断寄存器的位2是不是等于1,是0就等待转换完成
	{}
	Smoke = ADC_GetConversionValue(ADC1); //读规则组通道数据寄存器
	printf("烟雾浓度参数 = %d \r\n",Smoke);		
	return; 
}

需求实现

关键代码如下:

main.c

c 复制代码
#include "stm32f10x.h"
#include "usart.h"
#include "stdio.h"
#include "delay.h"
#include "string.h"
#include "pwm.h"
#include "adc.h"

int main()
{
	  NVIC_SetPriorityGrouping(5);//两位抢占两位次级
      Usart1_Config(); 
	  SysTick_Config(72000);
	  RGBpwm_Config();
	  uint8_t cai_count=0;
	  uint16_t cont=0;
	  Adc_Config();
    while(1)
    {	
			if(ledcnt[0]>=ledcnt[1]){//过去500ms
			ledcnt[0]=0;
					Get_Smoke_Value();
			}
    }
		
		return 0;
}

adc.c

c 复制代码
#include "ADC.h"
//库函数
void Adc_Config(void)
{
	//开时钟ADC1和PC,PA
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6); 
	//配置GPIO口
	GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//MQ2
    GPIO_Init(GPIOC, &GPIO_InitStructure);
	//配置ADC1
	ADC_InitTypeDef ADC_InitStruct={0};  //
	ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC独立模式
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//选择软件SWSTART位触发
	ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;//连续还是单次模式
	ADC_InitStruct.ADC_ScanConvMode = DISABLE;//关闭扫描
	ADC_InitStruct.ADC_NbrOfChannel = 1;
	ADC_Init(ADC1,&ADC_InitStruct);
	ADC_Cmd(ADC1, ENABLE);
	//配置通道
	ADC_RegularChannelConfig(ADC1, ADC_Channel_11,1,  ADC_SampleTime_239Cycles5);
	//校准
	ADC_ResetCalibration(ADC1);
	  while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
		while(ADC_GetCalibrationStatus(ADC1));	

}

void Get_Smoke_Value()
{
	uint16_t Smoke=0;
	//让规则通道转换一次
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	//ADC1->CR2 |= 0x01<<22;
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == 0)//判断寄存器的位2是不是等于1,是0就等待转换完成
	{}
	Smoke = ADC_GetConversionValue(ADC1); //读规则组通道数据寄存器
	printf("烟雾浓度参数 = %d \r\n",Smoke);
		
	return; 
}

adc.h

c 复制代码
#ifndef _ADC_H_
#define _ADC_H_
#include "stm32f10x.h"
#include "stdio.h"
void Get_Smoke_Value();
void Adc_Config(void);
#endif
		

总结

大致流程和ADC光照采集差别不大,照着一步一步做就能实现。

相关推荐
女神下凡4 小时前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
软件交付观察室5 小时前
旧设备要换平台,找谁开发?2026上海物联网软件服务方式比较
物联网·软件开发·系统集成
microrain5 小时前
SagooIoT 的数据接入层只有四张表,却能接住三种外部数据
物联网·golang·数据建模·sagooiot
sun153690275725 小时前
基坑边坡监测:振弦式土压力计选型、安装埋设与数据采集方案
大数据·物联网·自动化
Zw-awa5 小时前
从 CH340 到 HC-05 和 HC-06:让小车脱离电脑
stm32
硅基手札6 小时前
【Linux 内核专栏 19】20 · 嵌入式子系统 — GPIO·pinctrl·clock·regulator
linux·运维·单片机·linux内核·嵌入式开发·调试定位
TDengine (老段)8 小时前
TDengine IDMP 十大实用功能(7)
数据库·物联网·时序数据库·tdengine·涛思数据·工业数据·idmp
yusur8 小时前
万物智联 中科驭数受邀参加2026世界物联网博览会
物联网
何粥学8 小时前
Vivado 2024.2 开发记录(AC820 Zynq-7020)——软件使用,点亮led灯
单片机·嵌入式硬件·zynq
Sakura_j_h_9 小时前
51 单片机驱动四位数码管:动态扫描、限流电阻与消影的取舍
单片机·嵌入式硬件·51单片机·嵌入式·数码管·动态扫描·限流电阻