当前位置: 首页 > news >正文

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

文章目录

  • 需求
  • 一、MQ-2 气体传感器
    • 特点
    • 应用
    • 电路及引脚
  • 二、实现流程
    • 1.开时钟,分频,配IO
    • 2.配置ADC的工作模式
    • 3.配置通道
    • 4.复位,AD校准
    • 5.数值的获取
  • 需求实现
  • 总结


需求

使用ADC将MQ2模块检测到的烟雾浓度模拟量转化为数字量。
最后,将实时检测的结果显示在串口上。
在这里插入图片描述


一、MQ-2 气体传感器

特点

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

应用

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

电路及引脚

在这里插入图片描述
在这里插入图片描述

二、实现流程

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

1.开时钟,分频,配IO

该模块使用的引脚为PC1/ADC123_IN11,所以接下来我们要配置PC1。
烟雾检测模块是获得一个模拟量,所以接引脚模式配置为模拟输入。
代码如下:

	//开时钟ADC1和PCRCC_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;//MQ2GPIO_Init(GPIOC, &GPIO_InitStructure);

2.配置ADC的工作模式

和光照检测一样,直接改成库函数就行。
代码如下(示例):

	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 通道的采样时间值

ADC_RegularChannelConfig(ADC1, ADC_Channel_11,1, ADC_SampleTime_239Cycles5);

4.复位,AD校准

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

	ADC_ResetCalibration(ADC1);//复位while(ADC_GetResetCalibrationStatus(ADC1));ADC_StartCalibration(ADC1);//AD校准while(ADC_GetCalibrationStatus(ADC1));	

5.数值的获取

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

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

#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]){//过去500msledcnt[0]=0;Get_Smoke_Value();}}return 0;
}

adc.c

#include "ADC.h"
//库函数
void Adc_Config(void)
{//开时钟ADC1和PC,PARCC_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;//MQ2GPIO_Init(GPIOC, &GPIO_InitStructure);//配置ADC1ADC_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

#ifndef _ADC_H_
#define _ADC_H_
#include "stm32f10x.h"
#include "stdio.h"
void Get_Smoke_Value();
void Adc_Config(void);
#endif

总结

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

相关文章:

  • 4-数据提取方法2(xpath和lxml)(6节课学会爬虫)
  • 2024最全前端面试系列(计算机网络)(非科班出身最薄弱的环节)
  • 系统架构设计师教程(清华第2版)<第1章 绪论>解读
  • 一个启动脚本例子
  • git 常用语句
  • Windows环境使用SpringBoot整合Minio平替OSS
  • 点击notify里面的通知,实现路由跳转
  • 学习Symfony框架
  • react框架,使用vite和nextjs构建react项目
  • datawhale大模型应用开发夏令营学习笔记一
  • 下拉选择输入框(基于elment-ui)
  • 【JavaEE】多线程代码案例(2)
  • 8.ApplicationContext常见实现
  • 【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验15 网络故障导致的路由环路问题
  • CPU通过网络将IP camera的RTSP流(H.264编码或是H.265编码)拉回, 交给GPU解码并显示的处理流程
  • ES6指北【2】—— 箭头函数
  • “大数据应用场景”之隔壁老王(连载四)
  • 【5+】跨webview多页面 触发事件(二)
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • 07.Android之多媒体问题
  • es6
  • github指令
  • in typeof instanceof ===这些运算符有什么作用
  • input实现文字超出省略号功能
  • Java 网络编程(2):UDP 的使用
  • JavaScript DOM 10 - 滚动
  • Javascript Math对象和Date对象常用方法详解
  • Java精华积累:初学者都应该搞懂的问题
  • Linux链接文件
  • magento2项目上线注意事项
  • 理解在java “”i=i++;”所发生的事情
  • 码农张的Bug人生 - 见面之礼
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 整理一些计算机基础知识!
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • $Django python中使用redis, django中使用(封装了),redis开启事务(管道)
  • (1)常见O(n^2)排序算法解析
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (ZT)出版业改革:该死的死,该生的生
  • (安卓)跳转应用市场APP详情页的方式
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (一)Linux+Windows下安装ffmpeg
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)母版页和相对路径
  • .htaccess 强制https 单独排除某个目录
  • .java 9 找不到符号_java找不到符号
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • ??javascript里的变量问题
  • @ModelAttribute 注解
  • @SpringBootApplication 包含的三个注解及其含义
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042
  • [CDOJ 838]母仪天下 【线段树手速练习 15分钟内敲完算合格】
  • [codevs 2822] 爱在心中 【tarjan 算法】
  • [Firefly-Linux] RK3568 pca9555芯片驱动详解