GD32F470_MQ-2烟雾检测传感器模块移植

2.5 MQ-2烟雾检测传感器
MQ-2型烟雾传感器属于二氧化锡半导体气敏材料,属于表面离子式N型半导体。处于200~3000摄氏度时,二氧化锡表面吸附空气中的氧,形成氧的负离子吸附,使半导体中的电子密度减少,从而使其电阻值增加。当与烟雾接触时,如果晶粒间界处的势垒收到烟雾的调至面变化,就会引起表面导电率的变化。利用这一点就可以获得这种烟雾存在的信息。烟雾浓度越大导电率越大,输出电阻越低,则输出的模拟信号就越大。
2.5.1 模块来源
采购链接:
MQ-2烟雾传感器模块 MQ2 气体传感器
资料下载链接:
https://pan.baidu.com/s/1ETxqg03p5fEjKS7AZ2kV6w
资料提取码:dfr1

2.5.2 规格参数
工作电压:5V
工作电流:150MA
输出方式: DO接口为数字量输出 AO接口为模拟量输出
读取方式:ADC
管脚数量:4 Pin(2.54mm间距排针)
工作电流:150MA
输出方式: DO接口为数字量输出 AO接口为模拟量输出
读取方式:ADC
管脚数量:4 Pin(2.54mm间距排针)

2.5.3 移植过程
我们的目标是在梁山派GD32F470上能够判断当前环境状况的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
2.5.3.1 查看资料
MQ-2烟雾传感器对液化气、天然气、城市煤气灵敏度较高。需要注意的是:在使用之前必须加热一段时间,否则其输出的电阻和电压不准确。其检测可燃气体与烟雾的范围是100~10000ppm(ppm为体积浓度。 1ppm=1立方厘米/1立方米)。带有双路信号输出(模拟量输出AO和数字量输出DO)。当气体浓度未超过设定阈值时,数字接口DO口输出低电平,模拟接口AO电压基本为0v左右;当气体影响超过设定阈值时,模块数字接口DO输出高电平,模拟接口AO输出的电压会随着气体的影响慢慢增大。阈值由模块上的可调电阻控制。
其对应的原理图见图2.2.3.1-2,AO输出为MQ-2传感器直接输出的电压,所以为模拟量;DO为经过LM393进行电压比较后,输出高低电平,所以为数字量。具体原理见光敏电阻光照传感器章节的2.3.3.1 查看资料。

图2.5.3.1-2  MQ-2烟雾传感器原理图
2.5.3.2 引脚选择
想要使用ADC,需要确定使用的引脚是否有ADC外设功能。可以通过数据手册【GD32F450xx_Datasheet_Rev2.2.pdf】进行查看。文件下载见文件2.3.3.2-1 数据手册(GD32F450与GD32F470在功能与寄存器地址上没有区分)(梁山派开发板资料可在官网获取www.lckfb.com)
图2.5.3.2-1 数据手册来源
在数据手册的第28页结尾,是关于GD32F450Zx系列芯片引脚的功能定义示意图。
图2.5.3.2-2 引脚功能定义起始页

当前只有AO引脚需要使用到ADC接口,所以DO引脚可以使用开发板上其他的GPIO。这里选择使用PC1的附加ADC功能。使用ADC0的第11道输入通道。
在这里插入图片描述

烟雾传感器立创·梁山派
VCC5V
GNDGND
DOPF10
AOPC1

在这里插入图片描述
2.5.3.3 移植至工程
移植步骤中的导入.c和.h文件与上一节相同,只是将.c和.h文件更改为bsp_mq2.c与bsp_mq2.h。见2.2.3.3 移植至工程。这里不再过多讲述。移植完成后面修改相关代码。
在文件bsp_mq2.c中,编写如下代码。

/********************************************************************************
  * 文 件 名: bsp_mq2.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月06日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/


#include "bsp_mq2.h"
#include "systick.h"


 //DMA缓冲区
uint16_t gt_adc_val[ SAMPLES ][ CHANNEL_NUM ]; 


/******************************************************************
 * 函 数 名 称:ADC_DMA_Init
 * 函 数 说 明:初始化ADC+DMA功能
 * 函 数 形 参:无
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:无
******************************************************************/
void ADC_DMA_Init(void)
{
    /* DMA初始化功能结构体定义 */
    dma_single_data_parameter_struct dma_single_data_parameter;
        
        /* 使能引脚时钟 */
    rcu_periph_clock_enable(RCU_MQ2_GPIO_AO);                    
        rcu_periph_clock_enable(RCU_MQ2_GPIO_DO); 
        /* 使能ADC时钟 */
    rcu_periph_clock_enable(RCU_MQ2_ADC);                
  
        /* 使能DMA时钟 */
        rcu_periph_clock_enable(RCU_MQ2_DMA);
 
        /*        配置ADC时钟        */ 
    adc_clock_config(ADC_ADCCK_PCLK2_DIV4);        
   /*        配置DO为输入模式        */
    gpio_mode_set(PORT_MQ2_DO, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_MQ2_DO); 
        /*        配置AO为浮空模拟输入模式        */
    gpio_mode_set(PORT_MQ2_AO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_MQ2_AO); // PC1 : ADC012_IN11 
 
        /*        配置ADC为独立模式        */
    adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
        
    /*        使能连续转换模式        */
    adc_special_function_config(PORT_ADC, ADC_CONTINUOUS_MODE, ENABLE);
         
    /*        使能扫描模式        */
    adc_special_function_config(PORT_ADC, ADC_SCAN_MODE, ENABLE);
   
        /*        数据右对齐        */        
    adc_data_alignment_config(PORT_ADC, ADC_DATAALIGN_RIGHT);
    
    /*        ADC0设置为规则组  一共使用 CHANNEL_NUM 个通道                */  
    adc_channel_length_config(PORT_ADC, ADC_REGULAR_CHANNEL, CHANNEL_NUM);
                
    /*        ADC规则通道配置:ADC0的通道11的扫描顺序为0;采样时间:15个周期                */  
        /*        DMA开启之后 gt_adc_val[x][0] = PC1的数据   */
    adc_regular_channel_config(PORT_ADC, 0, CHANNEL_ADC, ADC_SAMPLETIME_15);//PC1
 
        /*        ADC0设置为12位分辨率                */  
        adc_resolution_config(PORT_ADC, ADC_RESOLUTION_12B); 
        
        /*        ADC外部触发禁用, 即只能使用软件触发                */  
    adc_external_trigger_config(PORT_ADC, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
    
    /*        使能规则组通道每转换完成一个就发送一次DMA请求                */  
    adc_dma_request_after_last_enable(PORT_ADC);  
    
        /*        使能DMA请求                */  
        adc_dma_mode_enable(PORT_ADC);
    
        /*        使能DMA                */          
        adc_enable(PORT_ADC);
    
        /*        等待ADC稳定                */  
        delay_1ms(1);
    
        /*        开启ADC自校准                */
    adc_calibration_enable(PORT_ADC); 
 
    /*        清除 DMA通道0 之前配置         */
    dma_deinit(PORT_DMA, CHANNEL_DMA);
   
        /*        DMA初始化配置         */
        dma_single_data_parameter.periph_addr = (uint32_t)(&ADC_RDATA(PORT_ADC));         //设置DMA传输的外设地址为ADC0基地址
        dma_single_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;                         //关闭外设地址自增
        dma_single_data_parameter.memory0_addr = (uint32_t)(gt_adc_val);                         //设置DMA传输的内存地址为 gt_adc_val数组
        dma_single_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;                         //开启内存地址自增(因为不止一个通道)
        dma_single_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;             //传输的数据位 为 16位
        dma_single_data_parameter.direction = DMA_PERIPH_TO_MEMORY;                                         //DMA传输方向为 外设往内存
        dma_single_data_parameter.number = SAMPLES * CHANNEL_NUM;                                     //传输的数据长度为:每个通道采集30次 * 1个通道
        dma_single_data_parameter.priority = DMA_PRIORITY_HIGH;                                                 //设置高优先级
        dma_single_data_mode_init(PORT_DMA, CHANNEL_DMA, &dma_single_data_parameter);//将配置保存至DMA1的通道0
        
        /*        DMA通道外设选择                */
        /*        数据手册的195页根据PERIEN[2:0]值确定第三个参数,例是100 则为DMA_SUBPERI4          例是010 则为DMA_SUBPERI2         */
        /*        我们是ADC0功能,PERIEN[2:0]值为000,故为DMA_SUBPERI0                */
        dma_channel_subperipheral_select(PORT_DMA, CHANNEL_DMA, DMA_SUBPERI0);
 
        /*        使能DMA1通道0循环模式                */
        dma_circulation_enable(PORT_DMA, CHANNEL_DMA);
 
        /*        启动DMA1的通道0功能                */
        dma_channel_enable(PORT_DMA, CHANNEL_DMA); 
        
        /*        开启软件触发ADC转换                */
        adc_software_trigger_enable(PORT_ADC, ADC_REGULAR_CHANNEL); 
}
 

/******************************************************************
 * 函 数 名 称:Get_Adc_Dma_Value
 * 函 数 说 明:对DMA保存的数据进行平均值计算后输出
 * 函 数 形 参:CHx 第几个扫描的数据
 * 函 数 返 回:对应扫描的ADC值
 * 作       者:LC
 * 备       注:无
******************************************************************/
unsigned int Get_Adc_Dma_Value(char CHx)
{
        unsigned char i = 0;
        unsigned int AdcValue = 0;
    
    /* 因为采集 SAMPLES 次,故循环 SAMPLES 次 */
        for(i=0; i< SAMPLES; i++)
        {
        /*    累加    */
                AdcValue+=gt_adc_val[i][CHx];
        }
    /* 求平均值 */
        AdcValue=AdcValue / SAMPLES;
    
        return AdcValue;
}

/******************************************************************
 * 函 数 名 称:Get_MQ2_Percentage_value
 * 函 数 说 明:读取MQ2值,并且返回百分比
 * 函 数 形 参:无
 * 函 数 返 回:返回百分比
 * 作       者:LC
 * 备       注:无
******************************************************************/
unsigned int Get_MQ2_Percentage_value(void)
{
    int adc_max = 4095;
    int adc_new = 0;
    int Percentage_value = 0;
    
    adc_new = Get_Adc_Dma_Value(0);
    
    Percentage_value = ((float)adc_new/adc_max) * 100;
    return Percentage_value;
}

在文件bsp_mq2.h中,编写如下代码。

#ifndef _BSP_MQ2_H_
#define _BSP_MQ2_H_
 
#include "gd32f4xx.h"
 
 
#define RCU_MQ2_GPIO_AO    RCU_GPIOC
#define RCU_MQ2_GPIO_DO    RCU_GPIOF

#define RCU_MQ2_ADC     RCU_ADC0
#define RCU_MQ2_DMA     RCU_DMA1

#define PORT_DMA        DMA1
#define CHANNEL_DMA     DMA_CH0

#define PORT_ADC     ADC0
#define CHANNEL_ADC     ADC_CHANNEL_11

#define PORT_MQ2_AO     GPIOC
#define GPIO_MQ2_AO     GPIO_PIN_1

#define PORT_MQ2_DO     GPIOF
#define GPIO_MQ2_DO     GPIO_PIN_11

 //采样次数
#define SAMPLES         30
//采样通道数 
#define CHANNEL_NUM     1


extern uint16_t gt_adc_val[ SAMPLES ][ CHANNEL_NUM ];  //DMA缓冲区
 
/************************
 
//之前的单路采集
void ADC_Init(void);
unsigned int Get_ADC_Value(void);
 
**************************/
void ADC_DMA_Init(void);
unsigned int Get_Adc_Dma_Value(char CHx);
 unsigned int Get_MQ2_Percentage_value(void);
unsigned int Get_MQ2_Percentage_value(void);

#endif

2.5.4 移植验证
在自己工程中的main主函数中,编写如下。

/********************************************************************************
  * 文 件 名: main.c
  * 版 本 号: 初版
  * 修改作者: LC
  * 修改日期: 2023年04月06日
  * 功能介绍:          
  ******************************************************************************
  * 注意事项:
*********************************************************************************/


#include "gd32f4xx.h"
#include "systick.h"
#include "bsp_usart.h"
#include "bsp_mq2.h"
#include "stdio.h"

int main(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 优先级分组
        systick_config();                //滴答定时器初始化 1ms

    usart_gpio_config(115200U);
    ADC_DMA_Init();
    printf("ADC+DMA demo start\r\n");
    while(1)
    {
        
        printf("ADC-%d\r\n", Get_Adc_Dma_Value(0) );
        printf("MQ2-%d\r\n", Get_MQ2_Percentage_value() );
        delay_1ms(1000);
    }
}

移植现象:输出ADC值和换算后的烟雾浓度百分比。
在这里插入图片描述
移植成功示例,见文件2.5.4-1 。
文件2.5.4-1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/517414.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

模板匹配——基于模板与基于特征的两种模板匹配对比

概述 在人工智能&#xff08;AI&#xff09;的研究领域中&#xff0c;模板匹配不仅是一个重要的研究课题&#xff0c;也是解决图像处理中核心问题——定位兴趣区域的关键方法之一。通过模板匹配&#xff0c;可以准确地识别和定位给定图像中的特定对象。这项技术在对象检测、跟…

【Week-Y4】修改yolov5s中C3模块的结构,common.py文件解读

修改C3模块的结构 一、commom.py文件解析二、修改代码&#xff0c;运行train.py训练 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 &#x1f4d5;本次任务&#xff1a;将yolov5s网络模型…

Dynamo之雪花分形(衍生式设计)

你好&#xff0c;这里是BIM的乐趣&#xff0c;我是九哥~ 今天简单分享一些我收集的Dynamo的雪花分形案例吧&#xff0c;不过多讲解了&#xff0c;有兴趣的小伙伴&#xff0c;可以私信“雪花分形”获取案例文件&#xff0c;下面基本以分享为主&#xff1a; ******多图预警****…

第四百四十二回

文章目录 1. 概念介绍2. 使用方法2.1 获取思路2.2 获取方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取屏幕相关参数"相关的内容&#xff0c;本章回中将介绍如何获取AppBar的高度.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《含储能接入的三相配电网分布式可再生能源可调度域建模与计算》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

糟糕,Oracle归档满RMAN进不去,CPU98%了!

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

程序员延寿指南:科学延寿 20 年 | 开源日报 No.214

geekan/HowToLiveLonger Stars: 28.7k License: Unlicense HowToLiveLonger 是一个程序员延寿指南项目。 该项目旨在提供关于如何延长寿命的指南&#xff0c;特别是针对程序员群体。该项目包括术语、目标、关键结果、分析、行动和证据等内容&#xff0c;涵盖了各种与健康相关的…

C语言要点细细梳理——番外:运算符优先级

C语言中的运算符优先级决定了在没有括号的情况下&#xff0c;表达式中的各个部分应如何求值。这个优先级是固定的&#xff0c;并且遵循一定的规则。当运算符的优先级相同时&#xff0c;运算的方向&#xff08;从左到右或从右到左&#xff09;则称为运算符的结合性。 下面是一个…

JAVA基础03-scanner,输出,循环,if的使用以及eclipse的安装

目录 scanner的使用 if语句的使用 eclipse的使用 switch语句的使用 输出方法的使用 循环语句 scanner的使用 实现用户数据的交互&#xff0c;用户通过终端输入数据 注意&#xff1a;使用Scanner需要导包 在程序开头加上&#xff1a;import java.util.Scanner; //由于S…

2024免费Mac苹果解压压缩包软件BetterZip5

在2024年&#xff0c;对于Mac电脑用户来说&#xff0c;如果你想要无需解压就能快速查看压缩文档的内容&#xff0c;BetterZip是一个极佳的选择。这款软件不仅支持多种格式的压缩和解压&#xff0c;如zip、rar、7z、tar等&#xff0c;还具备丰富的功能和设置&#xff0c;包括预览…

异地组网怎么管理?

在当今信息化时代&#xff0c;随着企业的业务扩张和员工的分布&#xff0c;异地组网已经成为越来越多企业的需求。异地组网管理相对来说是一项复杂而繁琐的任务。本文将介绍一种名为【天联】的管理解决方案&#xff0c;帮助企业更好地管理异地组网。 【天联】组网的优势 【天联…

《pytorch深度学习实战》学习笔记第2章

第2章 预训练网络 讨论3种常用的预训练模型&#xff1a; 1、根据内容对图像进行标记&#xff08;识别&#xff09; 2、从真实图像中生成新图像&#xff08;GAN&#xff09; 3、使用正确的英语句子来描述图像内容&#xff08;自然语言&#xff09; 2.1 获取一个预训练好的网络…

c++宏有什么离谱操作?

Boost.Preprocessor确实是一个非常强大而复杂的C宏库&#xff0c;专门用于元编程&#xff0c;即在编译时进行代码生成和变换。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程不妨点个关注&#xff0c;给个评论222&…

WordPress建站教程:10步快速搭建个人网站

WordPress是一个广泛使用的内容管理系统&#xff08;CMS&#xff09;&#xff0c;凭借其用户友好的界面和大量可定制的主题和插件&#xff0c;为WordPress 提供了多功能性和灵活性&#xff0c;可用于创建各种类型的网站&#xff0c;包括个人博客、B2B企业网站、B2C外贸网站等&a…

骨架屏:提升用户体验的巧妙技巧

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

CleanMyMac2024拥有优化Mac电脑所需的所有工具,深层清理、恶意软件移除、用CleanMyMac X就够了!

CleanMyMac X 拥有优化 Mac 电脑所需的所有工具&#xff1a;深层清理、恶意软件移除、性能提升…… 优化 Mac 电脑&#xff0c;用 CleanMyMac X 就够了&#xff01; CleanMyMac作为一款专为Mac用户设计的系统清理和优化软件&#xff0c;通过其独特的功能和特性&#xff0c;帮助…

Linux集群(二)集群搭建与keeplived配置

目录 一、集群搭建 1.复制3份Tomcat 2.测试Tomcat 3. 配置nginx.conf配置文件 二、keeplived 1.什么是keeplived 2.keeplived特点 3.下载和安装 3.1下载 3.2安装 3.3配置keeplived.conf配置文件 3.4测试 一、集群搭建 集群的主要目的是解决并发的问题。 1.复制3…

【QT+QGIS跨平台编译】056:【pdal_lazperf+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、pdal_lazperf介绍二、pdal下载三、文件分析四、pro文件五、编译实践一、pdal_lazperf介绍 pdal_lazperf 是 PDAL(Point Data Abstraction Library)的一个插件,用于处理点云数据。PDAL 是一个开源的库,用于处理和分析地理空间数据,特别是点云…

详解TCP/IP五层模型

目录 一、什么是TCP五层模型&#xff1f; 二、TCP五层模型的详细内容 1. 应用层 2. 传输层 3. 网络层 4. 数据链路层 5. 物理层 三、网络设备所在分层 封装和分⽤ 三、Java示例 引言&#xff1a; 在网络通信中&#xff0c;TCP/IP协议是至关重要的。为了更好地理解TCP协议的工…

SD-WAN组网,协助企业业务需求灵活调整带宽和网络资源

随着企业网络需求的不断增长和变化&#xff0c;传统的网络架构已经不能满足企业灵活调整带宽和网络资源的需求。而SD-WAN&#xff08;软件定义广域网&#xff09;作为一种新型的网络架构&#xff0c;可以帮助企业实现灵活调整带宽和网络资源&#xff0c;满足不同业务需求。本文…