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

基于天空星GD32F407的MQ-4甲烷传感器ADC+DMA数据采集实战

基于天空星GD32F407的MQ-4甲烷传感器ADCDMA数据采集实战最近在做一个智能家居环境监测的小项目需要检测厨房的天然气泄漏于是就用上了MQ-4甲烷传感器。很多刚开始接触嵌入式开发的朋友一看到传感器、ADC、DMA这些词就有点发怵觉得配置起来很复杂。其实只要把流程理清楚一步步来你会发现并没有想象中那么难。今天我就以国产的天空星GD32F407开发板为例手把手带你完成MQ-4传感器的数据采集。咱们的目标很明确把传感器输出的模拟电压信号通过ADC转换成数字量再用DMA自动搬运到内存里最后换算成浓度百分比显示出来。我会把代码的每一部分都掰开揉碎了讲保证你跟着做一遍就能完全掌握。1. 认识你的“侦察兵”MQ-4传感器在写代码之前咱们得先了解要驱动的对象。MQ-4传感器就像是一个专门侦察甲烷气体的“电子鼻子”。它的核心是一层对气体敏感的材料——二氧化锡。在干净的空气里这层材料的导电性比较差。一旦周围有甲烷、天然气这类可燃气体材料的导电性就会随着气体浓度的增加而变强。传感器内部有个简单的电路能把这个导电性的变化转换成咱们单片机可以测量的电压信号。MQ-4模块通常有4个引脚工作电压3.3V到5V都行和咱们的开发板正好匹配。它有两条输出“战线”AO模拟输出直接输出一个连续的电压值气体浓度越高电压越高。这是我们获取精确浓度数据的关键。DO数字输出模块上有个比较器电路和一个可调电阻。当AO端的电压超过你设定的阈值通过拧动电阻调整DO就会从低电平跳变成高电平相当于一个简单的“超标报警”开关。所以我们的任务就是读取AO引脚的电压并通过计算得到浓度信息。DO引脚可以作为一个简单的报警指示灯来用。提示模块资料和驱动源码可以在提供的网盘链接提取码9966里找到里面有原理图、说明书等动手前可以先下载下来看看。2. 硬件连接与引脚规划硬件连接很简单就是给传感器供电并把信号线接到开发板上。供电将MQ-4模块的VCC和GND分别接到开发板的3.3V和GND。信号线连接AO引脚需要连接到具有ADC模数转换器功能的单片机引脚上。根据GD32F407的数据手册我们选择PC1引脚它对应着ADC0模块的第11号输入通道。DO引脚这是一个普通的数字信号接任意一个GPIO引脚都可以我们把它接到PA1。为什么选PC1因为不是所有引脚都能做ADC输入。你必须去查芯片的数据手册Datasheet在引脚定义表里找到标有ADCx_INy功能的引脚才行。这一步是硬件设计的基础千万不能搞错。为了方便后续编程我们先在代码里把这些硬件连接关系用宏定义确定下来后面就直接用这些宏不用老去记具体的引脚号了。// bsp_mq4.h 中部分宏定义 #define PORT_MQ4_AO GPIOC // AO引脚所在的端口 #define GPIO_MQ4_AO GPIO_PIN_1 // AO引脚是PC1 #define PORT_MQ4_DO GPIOA // DO引脚所在的端口 #define GPIO_MQ4_DO GPIO_PIN_1 // DO引脚是PA1 #define PORT_ADC ADC0 // 使用的ADC模块编号 #define CHANNEL_ADC ADC_CHANNEL_11 // 使用的ADC通道号对应PC13. 核心武器ADC与DMA的协同配置这是本次实战最核心的部分。如果让CPU一次次去ADC那里读取数据会占用大量时间。我们的策略是让ADC专心转换让DMA直接存储器访问这个“搬运工”自动把转换好的数据存到数组里CPU只需要偶尔去数组里取处理好的数据就行效率大大提升。3.1 初始化流程总览整个初始化过程就像启动一条自动化生产线打开各个部件的时钟GPIO、ADC、DMA。配置GPIO引脚的模式AO为模拟输入DO为数字输入。配置ADC的工作模式独立、连续转换、扫描等。配置DMA告诉它从哪里搬ADC数据寄存器搬到哪里去内存数组怎么搬。校准ADC然后启动DMA和ADC开始生产数据。下面我们来看具体的代码实现。3.2 代码逐行解析首先在bsp_mq4.c里我们定义一个数组作为DMA的“目的地”仓库。这里计划对1个通道采样30次所以定义了一个二维数组实际代码中数组维度需根据实际情况补全例如uint16_t gt_adc_val[1][30]。uint16_t gt_adc_val[][]; // DMA缓冲区用于存储ADC转换结果接下来是重头戏ADC_DMA_Init()函数。第一步开启时钟任何外设要工作必须先打开它的时钟。这就像给设备通电。rcu_periph_clock_enable(RCU_MQ4_GPIO_AO); // 打开GPIOC时钟 rcu_periph_clock_enable(RCU_MQ4_GPIO_DO); // 打开GPIOA时钟 rcu_periph_clock_enable(RCU_MQ4_ADC); // 打开ADC0时钟 rcu_periph_clock_enable(RCU_MQ4_DMA); // 打开DMA1时钟第二步配置GPIO引脚AO引脚用于测量模拟电压必须设置为模拟输入模式这样引脚内部电路才会连接到ADC模块。DO是数字输入就设为浮空输入模式。gpio_mode_set(PORT_MQ4_DO, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_MQ4_DO); gpio_mode_set(PORT_MQ4_AO, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_MQ4_AO); // PC1: 模拟输入模式第三步配置ADC核心参数这里配置ADC的工作方式是关键所在。adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT); // ADC独立模式 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); // 数据右对齐 adc_resolution_config(PORT_ADC, ADC_RESOLUTION_12B); // 12位分辨率连续转换模式ADC完成一次转换后立刻开始下一次转换源源不断。扫描模式如果使能了多个通道ADC会按顺序自动扫描这些通道。我们虽然只有一个通道但也按这个模式配置。12位分辨率意味着ADC输出的数字量范围是0-4095对应输入电压0-3.3V。然后告诉ADC规则组可以理解为一个待转换的通道列表里有多少个通道并把我们的PC1通道11加到这个列表的第0个位置。adc_channel_length_config(PORT_ADC, ADC_ROUTINE_CHANNEL, 1); // 规则组通道数为1 adc_routine_channel_config(PORT_ADC, 0, ADC_CHANNEL_11, ADC_SAMPLETIME_15); // 第0个顺序通道11采样时间15周期第四步配置DMA——自动化搬运的关键这是解放CPU的核心。我们配置DMA1的通道0来为ADC0服务。dma_single_data_parameter_struct dma_single_data_parameter; // 清除DMA通道旧配置 dma_deinit(DMA1, DMA_CH0); // 配置DMA参数 dma_single_data_parameter.periph_addr (uint32_t)(ADC_RDATA(ADC0)); // 源头ADC0数据寄存器地址 dma_single_data_parameter.periph_inc DMA_PERIPH_INCREASE_DISABLE; // 源头地址固定总是从同一个寄存器读 dma_single_data_parameter.memory0_addr (uint32_t)(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位ADC是12位用16位变量存 dma_single_data_parameter.direction DMA_PERIPH_TO_MEMORY; // 传输方向外设到内存 dma_single_data_parameter.number 30 * 1; // 传输数据量30个样本 * 1个通道 dma_single_data_parameter.priority DMA_PRIORITY_HIGH; // DMA优先级高 // 初始化DMA通道 dma_single_data_mode_init(DMA1, DMA_CH0, dma_single_data_parameter);配置好传输任务后还要选择这个DMA通道是为哪个外设服务的。查数据手册可知ADC0对应的是DMA_SUBPERI0。dma_channel_subperipheral_select(DMA1, DMA_CH0, DMA_SUBPERI0);第五步启动流水线所有配置完毕依次启动各个部件。特别注意顺序先使能DMA相关功能再校准和使能ADC最后开启ADC转换。// 使能DMA循环模式搬完指定数量后自动从头开始实现循环缓冲 dma_circulation_enable(DMA1, DMA_CH0); // 使能ADC的DMA请求每次转换完成就请求DMA来搬 adc_dma_request_after_last_enable(PORT_ADC); adc_dma_mode_enable(PORT_ADC); // 启动DMA通道 dma_channel_enable(DMA1, DMA_CH0); // 使能ADC等待稳定然后进行校准提高精度 adc_enable(ADC0); delay_ms(1); adc_calibration_enable(ADC0); // 最后用软件触发ADC开始转换。一旦开始由于是连续模式它将永不停歇。 adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);至此一个由ADC采样、DMA搬运的自动化数据流水线就开始运行了。gt_adc_val数组里会自动填充最新的ADC采样值。4. 数据处理与浓度计算数据自动存好了我们怎么用呢首先写一个函数去计算一段时间内采样的平均值这样可以过滤掉一些偶然的干扰。unsigned int Get_Adc_Dma_Value(char CHx) { unsigned char i 0; unsigned int AdcValue 0; // 假设我们采样了30次对它们求和 for(i0; i30; i) { AdcValue gt_adc_val[0][i]; // 从缓冲区取数据 } // 再求平均 AdcValue AdcValue / 30; return AdcValue; }拿到稳定的ADC值0-4095后就可以把它换算成百分比了。这个百分比代表当前电压值占ADC量程3.3V的比例。对于MQ-4传感器这个电压比例间接反映了气体浓度的相对大小。unsigned int Get_MQ4_Percentage_value(void) { int adc_max 4095; // 12位ADC最大值 int adc_new 0; int Percentage_value 0; adc_new Get_Adc_Dma_Value(0); // 获取ADC平均值 // 计算百分比(当前值 / 最大值) * 100% Percentage_value ((float)adc_new / adc_max) * 100; return Percentage_value; }注意这里计算的是电压百分比并非精确的甲烷浓度ppm值。要得到精确浓度需要根据传感器数据手册提供的灵敏度特性曲线通常是指数关系进行更复杂的换算并且需要进行校准。本例的百分比输出适用于对浓度进行相对比较或阈值报警的场景。另外数字输出DO的状态可以直接读取用于快速报警。char Get_MQ4_DO_value(void) { // 读取DO引脚电平RESET为低电平SET为高电平 if(gpio_input_bit_get(GPIOA, GPIO_PIN_1) RESET) { return 0; // 未检测到高浓度气体 } else { return 1; // 检测到气体浓度超过模块设定阈值 } }5. 实战验证让代码跑起来最后我们在主函数里把上面的功能整合起来进行验证。#include board.h #include bsp_mq4.h #include stdio.h // 为了使用printf int main(void) { board_init(); // 开发板基础初始化系统时钟、延时等 bsp_uart_init(); // 初始化串口用于打印数据 ADC_DMA_Init(); // 初始化ADC和DMA printf(MQ-4 ADC DMA Demo Start\r\n); while(1) { // 每秒读取并打印一次甲烷浓度的百分比值 printf(Methane Concentration: %d%%\r\n, Get_MQ4_Percentage_value()); // 也可以检查数字输出状态 // if(Get_MQ4_DO_value()) { // printf(Warning: High concentration detected!\r\n); // } delay_ms(1000); // 延时1秒 } }将代码编译下载到天空星GD32F407开发板连接好传感器打开串口助手。你应该能看到终端里每秒打印一个百分比数值。对着传感器吹口气含二氧化碳或者靠近打火机注意安全释放少量气体观察数值的变化。数字输出DO的状态也可以通过模块上的电位器调整灵敏度来测试。这个项目把ADC采样、DMA传输、传感器应用串了起来是一个很典型的嵌入式数据采集案例。掌握了这个流程你再遇到其他模拟传感器比如温湿度、光照强度等思路都是一样的只需要根据具体传感器调整计算方式即可。

相关文章:

基于天空星GD32F407的MQ-4甲烷传感器ADC+DMA数据采集实战

基于天空星GD32F407的MQ-4甲烷传感器ADCDMA数据采集实战 最近在做一个智能家居环境监测的小项目,需要检测厨房的天然气泄漏,于是就用上了MQ-4甲烷传感器。很多刚开始接触嵌入式开发的朋友,一看到传感器、ADC、DMA这些词就有点发怵&#xff0c…...

深入解析hutool的BeanUtil.copyProperties在多线程环境下的潜在陷阱

1. 为什么CopyOnWriteArrayList会变成ArrayList? 这个问题困扰了我整整两天。当时生产环境突然报出ArrayIndexOutOfBoundsException异常,查看日志发现是在ArrayList.add方法抛出的,但明明代码里用的是CopyOnWriteArrayList啊!这种…...

Sunshine 完全卸载与系统清理指南

Sunshine 完全卸载与系统清理指南 【免费下载链接】Sunshine Sunshine: Sunshine是一个自托管的游戏流媒体服务器,支持通过Moonlight在各种设备上进行低延迟的游戏串流。 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 引言 Sunshine作为一款…...

基于计算机网络原理优化LiuJuan模型分布式集群部署方案

基于计算机网络原理优化LiuJuan模型分布式集群部署方案 最近和几个做AI服务的同行聊天,大家普遍有个头疼的问题:模型单机部署,用户一多就卡死;想搞分布式集群,又怕架构太复杂,运维成本上天。这让我想起了之…...

手把手教程:用AI股票分析师daily_stock_analysis一键生成专业投资报告

手把手教程:用AI股票分析师daily_stock_analysis一键生成专业投资报告 你是不是也对那些动辄几十页、充满专业术语的股票分析报告感到头疼?自己研究吧,时间不够;找人分析吧,成本太高。现在,有个工具能让你…...

ADRC实战:用Python从零搭建一阶系统自抗扰控制器(附完整代码)

ADRC实战:用Python从零搭建一阶系统自抗扰控制器(附完整代码) 控制工程领域一直在追求更鲁棒、更智能的算法来应对复杂系统中的不确定性。自抗扰控制(Active Disturbance Rejection Control, ADRC)作为一种不依赖精确模…...

LibreELEC新手必看:用PVR IPTV Simple Client搞定电视直播(附免费m3u8源)

LibreELEC电视直播实战指南:从零搭建稳定流畅的IPTV系统 第一次在树莓派上打开央视高清频道时,那种用开源软件替代广电机顶盒的成就感至今难忘。LibreELEC作为专为Kodi优化的轻量级系统,配合PVR IPTV Simple Client插件,确实能打造…...

避坑指南:Unity触发器(Trigger)的5个典型误用场景与正确解决方案

Unity触发器(Trigger)实战避坑指南:5个高频误用场景与优化方案 在Unity物理交互开发中,触发器(Trigger)就像一把双刃剑——用得巧妙可以创造丝滑的游戏体验,用错地方则会导致诡异的bug和性能灾难。本文将揭示那些连资深开发者都可能踩中的陷阱…...

MedGemma医疗助手实战:从部署到问诊,小白也能用的AI医生

MedGemma医疗助手实战:从部署到问诊,小白也能用的AI医生 1. 引言:您的私人医疗AI助手 当深夜突然出现不明症状,或是阅读病历遇到难懂的医学术语时,您是否希望有个随时待命的专业医疗顾问?MedGemma医疗助手…...

douyin-downloader:突破平台限制的视频高效获取解决方案

douyin-downloader:突破平台限制的视频高效获取解决方案 【免费下载链接】douyin-downloader 项目地址: https://gitcode.com/GitHub_Trending/do/douyin-downloader 在数字内容快速迭代的时代,视频资源的高效获取面临平台访问限制、动态签名验证…...

VibeVoice模型推理加速:TensorRT优化实战

VibeVoice模型推理加速:TensorRT优化实战 1. 为什么VibeVoice需要TensorRT加速 VibeVoice作为微软推出的前沿语音合成模型,能生成长达90分钟的多角色自然对话,但它的计算复杂度也相当可观。我在实际部署时发现,直接用PyTorch运行…...

Meta-Llama-3-8B-Instruct零基础部署:5分钟用vLLM+Open WebUI搭建对话机器人

Meta-Llama-3-8B-Instruct零基础部署:5分钟用vLLMOpen WebUI搭建对话机器人 1. 准备工作:了解你的工具 Meta-Llama-3-8B-Instruct是Meta公司最新开源的80亿参数对话模型,相比前代产品,它在指令遵循、多轮对话和代码理解方面都有…...

MySQL连接查询实战:从头歌平台案例学多表联合查询技巧

MySQL连接查询实战:从头歌平台案例学多表联合查询技巧 在数据库应用开发中,多表联合查询是每个开发者必须掌握的核心技能。想象一下,当你需要从学生表中获取姓名,同时从成绩表中查询对应分数,再关联课程表获取课程名称…...

ComfyUI低显存模式避坑指南:如何正确使用--disable-cuda-malloc和--normalvram参数

ComfyUI低显存GPU优化实战:参数调优与性能平衡指南 当你在4GB显存的显卡上运行ComfyUI时,是否经常遇到RuntimeError: CUDA error: operation not supported的报错?这可能是显存管理策略与你的硬件不兼容导致的。本文将带你深入理解ComfyUI的显…...

3步解锁图像数据:让科研图表开口说话

3步解锁图像数据:让科研图表开口说话 【免费下载链接】WebPlotDigitizer Computer vision assisted tool to extract numerical data from plot images. 项目地址: https://gitcode.com/gh_mirrors/web/WebPlotDigitizer 在科研分析、工程计算和商业决策中&a…...

AI辅助开发:借助快马平台为你的网盘注入智能文件摘要与语义搜索能力

最近在捣鼓一个网盘项目,想着怎么让它更“聪明”一点。传统的网盘就是个文件仓库,找东西全靠文件名,有时候文件多了,或者名字起得随意,找起来真是费劲。正好看到大家都在玩AI,我就琢磨着,能不能…...

Qwen3-14b_int4_awq惊艳效果:输入‘画一个架构图:用户登录流程’生成PlantUML代码

Qwen3-14b_int4_awq惊艳效果:输入"画一个架构图:用户登录流程"生成PlantUML代码 1. 模型简介 Qwen3-14b_int4_awq是基于Qwen3-14b模型的int4量化版本,采用AngelSlim技术进行压缩优化,专门用于高效文本生成任务。这个量…...

Qwen3-14b_int4_awqvLLM部署详解:engine_args配置、tokenizer路径指定与量化权重加载

Qwen3-14b_int4_awq LLM部署详解:engine_args配置、tokenizer路径指定与量化权重加载 1. 模型简介 Qwen3-14b_int4_awq是基于Qwen3-14b模型的int4量化版本,采用AngelSlim技术进行压缩优化,专门用于高效文本生成任务。这个量化版本在保持模型…...

Matlab中如何灵活定制坐标轴标签:深入解析set(gca,xtick)与set(gca,xticklabel)

1. 为什么需要定制坐标轴标签? 在数据可视化过程中,默认的坐标轴标签往往不能满足我们的需求。比如绘制一个正弦函数时,Matlab会自动生成均匀分布的刻度值,但这些数值可能并不直观。想象一下,如果你要给非技术背景的同…...

SpringBoot+Vue3无人机AI巡检:从实时流处理到智能预警的闭环实践

1. 项目背景与技术选型 最近几年无人机巡检在安防、电力、农业等领域快速普及,但很多团队在落地时都会遇到视频延迟高、AI识别不准、预警响应慢等问题。去年我们团队用SpringBootVue3完整实现了一套无人机AI巡检系统,实测在2km范围内能做到500ms以内的端…...

3步激活旧Mac潜能:OpenCore Legacy Patcher让不支持的设备重获新生

3步激活旧Mac潜能:OpenCore Legacy Patcher让不支持的设备重获新生 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher(OCLP&…...

如何用动态深度学习提升锂电池故障检测准确率?清华团队最新研究实践

动态深度学习在锂电池故障检测中的突破性实践 电动汽车的普及让锂电池安全问题日益凸显。传统检测方法在面对复杂工况时,往往表现出高误报率或漏检率,而清华大学团队的最新研究为这一难题提供了创新解决方案——通过动态深度学习技术,实现了锂…...

Aria2配置避坑指南:从自启动到浏览器插件联调(附完整.conf文件)

Aria2配置避坑指南:从自启动到浏览器插件联调(附完整.conf文件) 在Windows环境下配置Aria2自启动并实现浏览器插件联调,看似简单却暗藏诸多细节陷阱。许多用户在完成基础配置后,常遇到服务静默崩溃、RPC连接失败或下载…...

手把手教你修复libgit2报错:从corrupted loose reference到完整恢复Git仓库

手把手教你修复libgit2报错:从corrupted loose reference到完整恢复Git仓库 当你正在专注地开发项目,突然遇到corrupted loose reference file: refs/heads/master这样的Git错误时,那种感觉就像是在高速公路上突然爆胎。这个错误不仅会中断你…...

百度网盘下载加速:突破限速的高效解决方案

百度网盘下载加速:突破限速的高效解决方案 【免费下载链接】pan-baidu-download 百度网盘下载脚本 项目地址: https://gitcode.com/gh_mirrors/pa/pan-baidu-download 面对百度网盘动辄几十KB的下载速度,你是否也曾经历过等待大文件传输完成的煎熬…...

基于立创逻辑派与高云FPGA的100MHz双通道数字示波器DIY全解析

基于立创逻辑派与高云FPGA的100MHz双通道数字示波器DIY全解析 最近有不少朋友问我,想深入学习FPGA和嵌入式系统,有没有什么能动手又有挑战性的项目?今天我就来分享一个自己刚做完的“大玩具”——一个基于立创逻辑派开发板和高云FPGA的100MH…...

得物sign签名逆向避坑指南:常见MD5加密错误及解决方案

得物sign签名逆向避坑指南:常见MD5加密错误及解决方案 在逆向分析领域,sign签名机制一直是开发者关注的焦点。得物作为国内领先的潮流电商平台,其sign签名算法采用了经典的MD5加密方式,但在实际逆向过程中,开发者常常会…...

Phi-3-vision-128k-instruct保姆级部署教程:开源多模态模型GPU算力优化实操

Phi-3-vision-128k-instruct保姆级部署教程:开源多模态模型GPU算力优化实操 1. 模型简介 Phi-3-Vision-128K-Instruct是一个轻量级的开源多模态模型,属于Phi-3模型家族的最新成员。这个模型特别适合处理需要同时理解文本和图像的复杂任务,比…...

Phi-3-vision-128k-instruct代码实例:自定义Chainlit UI实现多图批量问答

Phi-3-vision-128k-instruct代码实例:自定义Chainlit UI实现多图批量问答 1. 模型简介 Phi-3-Vision-128K-Instruct是微软推出的轻量级多模态模型,属于Phi-3系列的最新成员。这个模型特别擅长处理图文结合的复杂任务,支持长达128K的上下文理…...

XTDrone--解决roslaunch px4 indoor1.launch依赖问题的实战指南

1. XTDrone环境搭建与依赖问题概述 第一次在XTDrone环境中运行roslaunch px4 indoor1.launch时,十有八九会遇到各种依赖报错。这就像组装一台新电脑,明明所有硬件都插好了,开机却总是提示缺少驱动。我刚开始接触XTDrone时,光是解决…...