MQ-5液化气传感器在TI MSPM0G3507开发板上的ADC与GPIO驱动移植实战最近有不少同学在准备电赛或者做智能家居项目问我怎么用单片机检测天然气、液化气这些可燃气体。正好手头有TI的MSPM0G3507开发板和常见的MQ-5传感器模块今天我就来手把手教大家怎么把它们连起来从硬件接线到软件驱动一步步实现气体浓度检测和报警功能。这个教程特别适合嵌入式初学者哪怕你刚接触单片机也没关系。我会把每个步骤都讲清楚包括怎么配置引脚、怎么用TI的SysConfig工具、怎么写ADC和GPIO的驱动代码。跟着做下来你不仅能学会MQ-5传感器的使用还能掌握MSPM0这款芯片的ADC和GPIO编程方法一举两得。1. 认识MQ-5气体传感器模块咱们先来看看今天的主角——MQ-5气体传感器模块。这个小模块在淘宝、立创商城都能买到价格很便宜十几块钱一个。1.1 传感器工作原理MQ-5的核心是一层二氧化锡SnO₂气敏材料。这东西在清洁空气里电阻很大电导率低不怎么导电。但是当它周围有可燃气体比如天然气、液化气、丙烷时气体分子会吸附在材料表面导致材料的电阻变小电导率增大。气体浓度越高电阻变得越小。模块内部有个简单的电路能把电阻的变化转换成电压信号输出。所以咱们单片机要做的就是读取这个电压值然后根据电压高低来判断气体浓度。MQ-5对好几种气体都敏感特别是丁烷、丙烷、甲烷。如果你主要想检测天然气主要成分是甲烷或者液化气主要成分是丙烷用这个模块正合适。1.2 模块引脚和参数拿到模块你会看到4个引脚2.54mm间距的排针分别是引脚标号功能说明VCC电源正极接3.3V或5V都行GND电源地线DO数字量输出输出高低电平AO模拟量输出输出0-VCC的电压关键参数工作电压3.3V ~ 5V咱们开发板有5V和3.3V输出都可以用工作电流约150mA电流不小最好单独供电或者确保电源能带动DO输出数字信号高电平表示气体浓度低于设定阈值低电平表示高于阈值AO输出模拟信号电压值随气体浓度变化浓度越高电压越高DO口那里有个蓝色的小电位器拧它可以调整报警阈值。顺时针拧灵敏度提高更容易报警逆时针拧灵敏度降低。注意模块需要预热刚上电时读数不准要等里面的气敏材料加热稳定一般需要1-2分钟。做实验时要有耐心。2. 硬件连接把传感器接到开发板上现在咱们要把MQ-5模块和MSPM0G3507开发板连起来。连接很简单就4根线。2.1 引脚分配方案我选择的引脚连接方案如下传感器模块引脚MSPM0G3507开发板引脚说明VCC5V05V电源输出模块支持5V供电这样驱动能力强GNDGND地线共地很重要不然ADC读数不准DOPA26普通GPIO输入引脚读取高低电平AOPA27这个引脚有ADC功能读取模拟电压为什么选PA27作为ADC输入因为查看MSPM0G3507的数据手册PA27引脚支持ADC功能正好用来接模拟输出。DO口就是个开关量随便找个GPIO都能用我选了PA26你换成其他空闲的GPIO也行。2.2 实际接线图接线的时候注意方向别接反了模块的VCC接开发板的5V输出找标着5V0的排针模块的GND接开发板的任意GND引脚模块的DO接开发板的PA26具体位置看开发板丝印模块的AO接开发板的PA27接好线后检查一遍确保没有接错、没有短路。然后就可以上电了你会看到模块上的红灯亮起表示开始预热。3. 软件配置使用SysConfig工具硬件接好了接下来配置软件。TI给MSPM0系列芯片做了个很好的工具叫SysConfig图形化配置不用自己手动写寄存器对新手特别友好。3.1 打开并配置工程首先确保你已经安装了Code Composer StudioCCS和MSPM0的SDK。然后打开你的工程找到empty.syscfg文件双击它。SysConfig界面打开后咱们要添加两个外设配置一个给GPIO读DO引脚一个给ADC读AO引脚。第一步添加GPIO配置点击左边的ADD按钮在搜索框输入GPIO选择GPIO并添加在右侧配置区域给这个GPIO实例起个名字比如GPIO_DO选择引脚点击Pin选择PA26方向选择Input输入模式初始状态保持默认第二步添加ADC配置再次点击ADD搜索ADC12选择ADC12并添加MSPM0G3507用的是ADC12模块在右侧配置区域实例名保持ADC12_0就行点击Channel Configuration在Channel 0那里启用打勾输入通道选择PA27对应的ADC通道系统会自动匹配采样时间可以先用默认值如果读数不稳再调大3.2 保存和生成代码配置完成后按CtrlS保存。这时候SysConfig可能会提示一些警告不用管它只要没报错就行。保存后点击编译按钮或者按F7SysConfig会自动生成配置文件。这个过程中它会在后台生成一个重要的头文件ti_msp_dl_config.h。这个文件里定义了所有我们刚才配置的引脚和功能。更棒的是我们的工程里已经有一个board.h文件它包含了ti_msp_dl_config.h。所以以后在代码里我们只需要包含board.h这一个头文件就能使用所有配置好的功能了。提示如果你找不到某个引脚的定义可以打开ti_msp_dl_config.h搜索一下里面宏定义的名字都很直观比如GPIO_DO_PIN对应DO引脚。4. 编写驱动代码BSP层实现配置工具帮我们生成了底层配置现在要写应用层的驱动代码了。好的习惯是把传感器驱动放在独立的BSP板级支持包文件里这样代码结构清晰也方便移植到其他项目。4.1 创建BSP文件在工程里找到或创建一个BSP文件夹在里面新建两个子文件夹inc放头文件和src放源文件。然后创建两个文件bsp_mq5.c- 驱动源文件bsp_mq5.h- 驱动头文件别忘了在CCS的工程属性里把BSP/inc路径添加到Include Options中这样编译器才能找到我们的头文件。4.2 头文件定义bsp_mq5.h先来看头文件这里定义了一些宏和函数声明#ifndef _BSP_MQ5_H_ #define _BSP_MQ5_H_ #include board.h // 读取DO引脚状态的宏 // 原理读取GPIO端口值与引脚掩码进行与操作然后判断是否为0 #define MQ_DO ( ( DL_GPIO_readPins( GPIO_PORT, GPIO_DO_PIN ) GPIO_DO_PIN ) ? 1 : 0 ) // ADC采样次数多次采样取平均可以减少噪声干扰 #define SAMPLES 30 // 函数声明 unsigned int Get_Adc_MQ5_Value(void); // 获取ADC原始值 unsigned int Get_MQ5_Percentage_value(void); // 获取浓度百分比 char Get_MQ5_DO(void); // 获取DO引脚状态 #endif这里有个关键点MQ_DO宏。它用TI的驱动库函数DL_GPIO_readPins读取引脚状态GPIO_PORT和GPIO_DO_PIN是SysConfig自动生成的宏分别代表端口和引脚号。这个宏展开后如果DO引脚是高电平MQ_DO的值就是1低电平就是0。4.3 ADC读取函数bsp_mq5.c现在来看核心的ADC读取代码。MSPM0的ADC是12位的最大数值是40952^12 - 1。#include bsp_mq5.h #include stdio.h /********************************************************** * 函数名称ADC_GET * 函数功能单次ADC转换 * 传入参数无 * 函数返回ADC转换结果0-4095 * 备注这是底层读取函数被Get_Adc_MQ5_Value调用 **********************************************************/ static uint32_t ADC_GET(void) { unsigned int gAdcResult 0; // 1. 使能ADC转换器 DL_ADC12_enableConversions(ADC12_0_INST); // 2. 软件触发开始转换 DL_ADC12_startConversion(ADC12_0_INST); // 3. 等待转换完成 // 如果ADC忙就循环等待直到它空闲 while (DL_ADC12_getStatus(ADC12_0_INST) ! DL_ADC12_STATUS_CONVERSION_IDLE); // 4. 停止转换并失能ADC省电 DL_ADC12_stopConversion(ADC12_0_INST); DL_ADC12_disableConversions(ADC12_0_INST); // 5. 从ADC结果存储器读取数据 // ADC12_0_ADCMEM_CH0对应我们配置的通道0 gAdcResult DL_ADC12_getMemResult(ADC12_0_INST, ADC12_0_ADCMEM_CH0); return gAdcResult; }这个函数完成一次完整的ADC转换。我解释一下关键步骤DL_ADC12_enableConversions打开ADC的转换功能就像打开水龙头开关DL_ADC12_startConversion告诉ADC开始采样这是软件触发方式等待循环ADC转换需要时间不能立即读取结果要等它忙完DL_ADC12_getMemResult从ADC的结果寄存器里读取数值注意实际项目中如果频繁读取ADC可以不用每次都使能/失能ADC那样效率更高。但咱们这个应用读取间隔长这样写更省电。单次ADC读数可能受噪声干扰所以我们要多次采样取平均/****************************************************************** * 函数名称Get_Adc_MQ5_Value * 函数说明获取MQ5的ADC值多次采样平均 * 函数形参无 * 函数返回ADC平均值0-4095 ******************************************************************/ unsigned int Get_Adc_MQ5_Value(void) { uint32_t Data 0; // 采样SAMPLES次30次然后求平均 for(int i 0; i SAMPLES; i) { Data ADC_GET(); // 累加每次的采样值 delay_ms(5); // 每次采样间隔5ms让ADC稳定 } Data Data / SAMPLES; // 计算平均值 return Data; }这里我采样30次每次间隔5ms。为什么要这么多次因为MQ-5传感器本身输出就有波动多次平均可以平滑曲线让读数更稳定。如果你发现读数跳变厉害可以增加SAMPLES的值或者增大采样间隔。4.4 计算浓度百分比ADC读出来的是0-4095的原始值但咱们更关心的是浓度百分比。这个转换很简单/****************************************************************** * 函数名称Get_MQ5_Percentage_value * 函数说明读取MQ5值并转换为百分比 * 函数形参无 * 函数返回气体浓度百分比0-100% ******************************************************************/ unsigned int Get_MQ5_Percentage_value(void) { int adc_max 4095; // 12位ADC最大值 int adc_new 0; int Percentage_value 0; adc_new Get_Adc_MQ5_Value(); // 获取ADC平均值 // 计算百分比(当前值 / 最大值) * 100 Percentage_value ((float)adc_new / (float)adc_max) * 100.f; return Percentage_value; }这里有个细节adc_new和adc_max要先转成float再做除法不然整数除法会丢失小数部分。比如adc_new2048如果不转float2048/40950整数除法转成float后2048.0/4095.0≈0.5再乘以100就是50%。4.5 读取DO引脚状态DO引脚更简单就是个数字输入/****************************************************************** * 函数名称Get_MQ5_DO * 函数说明获取MQ5 DO引脚的电平状态 * 函数形参无 * 函数返回0浓度低于阈值1浓度高于阈值 * 备注通过模块上的电位器可以调整报警阈值 ******************************************************************/ char Get_MQ5_DO(void) { // 使用头文件中定义的MQ_DO宏读取引脚状态 if( MQ_DO 0 ) { return 0; // DO输出低电平气体浓度超过设定阈值 } else { return 1; // DO输出高电平气体浓度未超过阈值 } }注意这里的逻辑当气体浓度超过模块上电位器设定的阈值时DO输出低电平(0)浓度低于阈值时DO输出高电平(1)。这个逻辑是模块上的比较器电路决定的不要搞反了。5. 主程序测试与验证驱动写好了现在写个简单的主程序测试一下。打开工程里的empty.c或者你的主文件添加以下代码#include ti_msp_dl_config.h #include board.h #include bsp_mq5.h int main(void) { // 初始化系统时钟、外设等 SYSCFG_DL_init(); // 初始化串口用于打印调试信息 lc_printf(MQ-5 Sensor Start...\r\n); lc_printf(Please wait 1-2 minutes for sensor preheating...\r\n); // 主循环 while (1) { // 打印空行分隔每次输出 lc_printf(\n); // 打印ADC原始值0-4095 lc_printf(MQ5 ADC Value %d\r\n, Get_Adc_MQ5_Value()); // 打印浓度百分比 lc_printf(MQ5 Percentage [%d%%]\r\n, Get_MQ5_Percentage_value()); // 打印DO引脚状态 char do_state Get_MQ5_DO(); lc_printf(MQ5 DO State %d, do_state); if(do_state 0) { lc_printf( (Gas detected!)\r\n); } else { lc_printf( (Normal)\r\n); } // 延时500ms再读下一次 delay_ms(500); } }编译下载到开发板打开串口调试助手波特率一般115200你会看到类似这样的输出MQ-5 Sensor Start... Please wait 1-2 minutes for sensor preheating... MQ5 ADC Value 1250 MQ5 Percentage [30%] MQ5 DO State 1 (Normal) MQ5 ADC Value 1280 MQ5 Percentage [31%] MQ5 DO State 1 (Normal)5.1 实际测试与校准上电后别急着看数据先等1-2分钟让传感器预热。你会观察到刚上电ADC值可能很低几十到几百然后慢慢上升预热稳定后在清洁空气中ADC值会稳定在一个基线值比如1200左右对应约30%靠近气体源用打火机不点火轻轻放气靠近传感器ADC值会迅速上升可能到3000以上DO引脚变化当ADC值超过某个阈值时DO引脚会从1变成0这个基线值很重要它是清洁空气下的参考值。实际应用中你可以简单判断当ADC值比基线值高很多时认为有气体泄漏设置阈值比如if(Get_MQ5_Percentage_value() 60) { 报警 }使用DO直接读取DO引脚通过电位器调整报警灵敏度5.2 调试技巧和常见问题问题1ADC读数跳变太大可能原因电源噪声、采样次数太少解决方法增加SAMPLES的值比如从30改成50或者在VCC和GND之间加个100uF的电容问题2DO引脚一直为0或一直为1检查接线确认DO引脚接到了正确的GPIO调整电位器用小螺丝刀轻轻旋转模块上的蓝色电位器检查代码确认GPIO_DO_PIN宏定义正确问题3响应速度慢原因MQ-5本身响应就慢特别是从高浓度回到清洁空气时注意这是气敏传感器的特性不是代码问题。如果需要快速检测要考虑其他类型的传感器。6. 项目扩展思路基本的读取功能实现了你可以在这个基础上做很多扩展1. 浓度标定和换算现在的百分比只是相对值。如果你想得到实际的气体浓度比如ppm单位需要在已知浓度的气体环境中测试用标准气体记录多个浓度点对应的ADC值建立ADC值与实际浓度的关系曲线通常是线性或对数关系2. 增加报警功能// 简单的软件报警 if(Get_MQ5_Percentage_value() 70) { // 点亮LED报警 // 或者控制蜂鸣器 // 甚至可以通过Wi模块发送报警信息到手机 }3. 数据记录和显示把ADC值保存到数组绘制浓度变化曲线连接OLED屏幕实时显示浓度和状态通过串口发送到电脑用上位机软件显示波形4. 多传感器融合同时接温湿度传感器如DHT11因为温湿度会影响气体检测接多个MQ系列传感器区分不同气体类型这个MQ-5驱动我已经在好几个项目里用过了稳定性不错。最需要注意的就是预热时间一定要够不然读数不准。还有传感器不要长时间暴露在高浓度气体中会影响寿命。代码里我加了详细的注释你直接复制就能用。如果遇到问题先检查接线再看SysConfig配置是否正确。嵌入式开发就是这样一点点调试成功了就很有成就感。
MQ-5液化气传感器在TI MSPM0G3507开发板上的ADC与GPIO驱动移植实战
MQ-5液化气传感器在TI MSPM0G3507开发板上的ADC与GPIO驱动移植实战最近有不少同学在准备电赛或者做智能家居项目问我怎么用单片机检测天然气、液化气这些可燃气体。正好手头有TI的MSPM0G3507开发板和常见的MQ-5传感器模块今天我就来手把手教大家怎么把它们连起来从硬件接线到软件驱动一步步实现气体浓度检测和报警功能。这个教程特别适合嵌入式初学者哪怕你刚接触单片机也没关系。我会把每个步骤都讲清楚包括怎么配置引脚、怎么用TI的SysConfig工具、怎么写ADC和GPIO的驱动代码。跟着做下来你不仅能学会MQ-5传感器的使用还能掌握MSPM0这款芯片的ADC和GPIO编程方法一举两得。1. 认识MQ-5气体传感器模块咱们先来看看今天的主角——MQ-5气体传感器模块。这个小模块在淘宝、立创商城都能买到价格很便宜十几块钱一个。1.1 传感器工作原理MQ-5的核心是一层二氧化锡SnO₂气敏材料。这东西在清洁空气里电阻很大电导率低不怎么导电。但是当它周围有可燃气体比如天然气、液化气、丙烷时气体分子会吸附在材料表面导致材料的电阻变小电导率增大。气体浓度越高电阻变得越小。模块内部有个简单的电路能把电阻的变化转换成电压信号输出。所以咱们单片机要做的就是读取这个电压值然后根据电压高低来判断气体浓度。MQ-5对好几种气体都敏感特别是丁烷、丙烷、甲烷。如果你主要想检测天然气主要成分是甲烷或者液化气主要成分是丙烷用这个模块正合适。1.2 模块引脚和参数拿到模块你会看到4个引脚2.54mm间距的排针分别是引脚标号功能说明VCC电源正极接3.3V或5V都行GND电源地线DO数字量输出输出高低电平AO模拟量输出输出0-VCC的电压关键参数工作电压3.3V ~ 5V咱们开发板有5V和3.3V输出都可以用工作电流约150mA电流不小最好单独供电或者确保电源能带动DO输出数字信号高电平表示气体浓度低于设定阈值低电平表示高于阈值AO输出模拟信号电压值随气体浓度变化浓度越高电压越高DO口那里有个蓝色的小电位器拧它可以调整报警阈值。顺时针拧灵敏度提高更容易报警逆时针拧灵敏度降低。注意模块需要预热刚上电时读数不准要等里面的气敏材料加热稳定一般需要1-2分钟。做实验时要有耐心。2. 硬件连接把传感器接到开发板上现在咱们要把MQ-5模块和MSPM0G3507开发板连起来。连接很简单就4根线。2.1 引脚分配方案我选择的引脚连接方案如下传感器模块引脚MSPM0G3507开发板引脚说明VCC5V05V电源输出模块支持5V供电这样驱动能力强GNDGND地线共地很重要不然ADC读数不准DOPA26普通GPIO输入引脚读取高低电平AOPA27这个引脚有ADC功能读取模拟电压为什么选PA27作为ADC输入因为查看MSPM0G3507的数据手册PA27引脚支持ADC功能正好用来接模拟输出。DO口就是个开关量随便找个GPIO都能用我选了PA26你换成其他空闲的GPIO也行。2.2 实际接线图接线的时候注意方向别接反了模块的VCC接开发板的5V输出找标着5V0的排针模块的GND接开发板的任意GND引脚模块的DO接开发板的PA26具体位置看开发板丝印模块的AO接开发板的PA27接好线后检查一遍确保没有接错、没有短路。然后就可以上电了你会看到模块上的红灯亮起表示开始预热。3. 软件配置使用SysConfig工具硬件接好了接下来配置软件。TI给MSPM0系列芯片做了个很好的工具叫SysConfig图形化配置不用自己手动写寄存器对新手特别友好。3.1 打开并配置工程首先确保你已经安装了Code Composer StudioCCS和MSPM0的SDK。然后打开你的工程找到empty.syscfg文件双击它。SysConfig界面打开后咱们要添加两个外设配置一个给GPIO读DO引脚一个给ADC读AO引脚。第一步添加GPIO配置点击左边的ADD按钮在搜索框输入GPIO选择GPIO并添加在右侧配置区域给这个GPIO实例起个名字比如GPIO_DO选择引脚点击Pin选择PA26方向选择Input输入模式初始状态保持默认第二步添加ADC配置再次点击ADD搜索ADC12选择ADC12并添加MSPM0G3507用的是ADC12模块在右侧配置区域实例名保持ADC12_0就行点击Channel Configuration在Channel 0那里启用打勾输入通道选择PA27对应的ADC通道系统会自动匹配采样时间可以先用默认值如果读数不稳再调大3.2 保存和生成代码配置完成后按CtrlS保存。这时候SysConfig可能会提示一些警告不用管它只要没报错就行。保存后点击编译按钮或者按F7SysConfig会自动生成配置文件。这个过程中它会在后台生成一个重要的头文件ti_msp_dl_config.h。这个文件里定义了所有我们刚才配置的引脚和功能。更棒的是我们的工程里已经有一个board.h文件它包含了ti_msp_dl_config.h。所以以后在代码里我们只需要包含board.h这一个头文件就能使用所有配置好的功能了。提示如果你找不到某个引脚的定义可以打开ti_msp_dl_config.h搜索一下里面宏定义的名字都很直观比如GPIO_DO_PIN对应DO引脚。4. 编写驱动代码BSP层实现配置工具帮我们生成了底层配置现在要写应用层的驱动代码了。好的习惯是把传感器驱动放在独立的BSP板级支持包文件里这样代码结构清晰也方便移植到其他项目。4.1 创建BSP文件在工程里找到或创建一个BSP文件夹在里面新建两个子文件夹inc放头文件和src放源文件。然后创建两个文件bsp_mq5.c- 驱动源文件bsp_mq5.h- 驱动头文件别忘了在CCS的工程属性里把BSP/inc路径添加到Include Options中这样编译器才能找到我们的头文件。4.2 头文件定义bsp_mq5.h先来看头文件这里定义了一些宏和函数声明#ifndef _BSP_MQ5_H_ #define _BSP_MQ5_H_ #include board.h // 读取DO引脚状态的宏 // 原理读取GPIO端口值与引脚掩码进行与操作然后判断是否为0 #define MQ_DO ( ( DL_GPIO_readPins( GPIO_PORT, GPIO_DO_PIN ) GPIO_DO_PIN ) ? 1 : 0 ) // ADC采样次数多次采样取平均可以减少噪声干扰 #define SAMPLES 30 // 函数声明 unsigned int Get_Adc_MQ5_Value(void); // 获取ADC原始值 unsigned int Get_MQ5_Percentage_value(void); // 获取浓度百分比 char Get_MQ5_DO(void); // 获取DO引脚状态 #endif这里有个关键点MQ_DO宏。它用TI的驱动库函数DL_GPIO_readPins读取引脚状态GPIO_PORT和GPIO_DO_PIN是SysConfig自动生成的宏分别代表端口和引脚号。这个宏展开后如果DO引脚是高电平MQ_DO的值就是1低电平就是0。4.3 ADC读取函数bsp_mq5.c现在来看核心的ADC读取代码。MSPM0的ADC是12位的最大数值是40952^12 - 1。#include bsp_mq5.h #include stdio.h /********************************************************** * 函数名称ADC_GET * 函数功能单次ADC转换 * 传入参数无 * 函数返回ADC转换结果0-4095 * 备注这是底层读取函数被Get_Adc_MQ5_Value调用 **********************************************************/ static uint32_t ADC_GET(void) { unsigned int gAdcResult 0; // 1. 使能ADC转换器 DL_ADC12_enableConversions(ADC12_0_INST); // 2. 软件触发开始转换 DL_ADC12_startConversion(ADC12_0_INST); // 3. 等待转换完成 // 如果ADC忙就循环等待直到它空闲 while (DL_ADC12_getStatus(ADC12_0_INST) ! DL_ADC12_STATUS_CONVERSION_IDLE); // 4. 停止转换并失能ADC省电 DL_ADC12_stopConversion(ADC12_0_INST); DL_ADC12_disableConversions(ADC12_0_INST); // 5. 从ADC结果存储器读取数据 // ADC12_0_ADCMEM_CH0对应我们配置的通道0 gAdcResult DL_ADC12_getMemResult(ADC12_0_INST, ADC12_0_ADCMEM_CH0); return gAdcResult; }这个函数完成一次完整的ADC转换。我解释一下关键步骤DL_ADC12_enableConversions打开ADC的转换功能就像打开水龙头开关DL_ADC12_startConversion告诉ADC开始采样这是软件触发方式等待循环ADC转换需要时间不能立即读取结果要等它忙完DL_ADC12_getMemResult从ADC的结果寄存器里读取数值注意实际项目中如果频繁读取ADC可以不用每次都使能/失能ADC那样效率更高。但咱们这个应用读取间隔长这样写更省电。单次ADC读数可能受噪声干扰所以我们要多次采样取平均/****************************************************************** * 函数名称Get_Adc_MQ5_Value * 函数说明获取MQ5的ADC值多次采样平均 * 函数形参无 * 函数返回ADC平均值0-4095 ******************************************************************/ unsigned int Get_Adc_MQ5_Value(void) { uint32_t Data 0; // 采样SAMPLES次30次然后求平均 for(int i 0; i SAMPLES; i) { Data ADC_GET(); // 累加每次的采样值 delay_ms(5); // 每次采样间隔5ms让ADC稳定 } Data Data / SAMPLES; // 计算平均值 return Data; }这里我采样30次每次间隔5ms。为什么要这么多次因为MQ-5传感器本身输出就有波动多次平均可以平滑曲线让读数更稳定。如果你发现读数跳变厉害可以增加SAMPLES的值或者增大采样间隔。4.4 计算浓度百分比ADC读出来的是0-4095的原始值但咱们更关心的是浓度百分比。这个转换很简单/****************************************************************** * 函数名称Get_MQ5_Percentage_value * 函数说明读取MQ5值并转换为百分比 * 函数形参无 * 函数返回气体浓度百分比0-100% ******************************************************************/ unsigned int Get_MQ5_Percentage_value(void) { int adc_max 4095; // 12位ADC最大值 int adc_new 0; int Percentage_value 0; adc_new Get_Adc_MQ5_Value(); // 获取ADC平均值 // 计算百分比(当前值 / 最大值) * 100 Percentage_value ((float)adc_new / (float)adc_max) * 100.f; return Percentage_value; }这里有个细节adc_new和adc_max要先转成float再做除法不然整数除法会丢失小数部分。比如adc_new2048如果不转float2048/40950整数除法转成float后2048.0/4095.0≈0.5再乘以100就是50%。4.5 读取DO引脚状态DO引脚更简单就是个数字输入/****************************************************************** * 函数名称Get_MQ5_DO * 函数说明获取MQ5 DO引脚的电平状态 * 函数形参无 * 函数返回0浓度低于阈值1浓度高于阈值 * 备注通过模块上的电位器可以调整报警阈值 ******************************************************************/ char Get_MQ5_DO(void) { // 使用头文件中定义的MQ_DO宏读取引脚状态 if( MQ_DO 0 ) { return 0; // DO输出低电平气体浓度超过设定阈值 } else { return 1; // DO输出高电平气体浓度未超过阈值 } }注意这里的逻辑当气体浓度超过模块上电位器设定的阈值时DO输出低电平(0)浓度低于阈值时DO输出高电平(1)。这个逻辑是模块上的比较器电路决定的不要搞反了。5. 主程序测试与验证驱动写好了现在写个简单的主程序测试一下。打开工程里的empty.c或者你的主文件添加以下代码#include ti_msp_dl_config.h #include board.h #include bsp_mq5.h int main(void) { // 初始化系统时钟、外设等 SYSCFG_DL_init(); // 初始化串口用于打印调试信息 lc_printf(MQ-5 Sensor Start...\r\n); lc_printf(Please wait 1-2 minutes for sensor preheating...\r\n); // 主循环 while (1) { // 打印空行分隔每次输出 lc_printf(\n); // 打印ADC原始值0-4095 lc_printf(MQ5 ADC Value %d\r\n, Get_Adc_MQ5_Value()); // 打印浓度百分比 lc_printf(MQ5 Percentage [%d%%]\r\n, Get_MQ5_Percentage_value()); // 打印DO引脚状态 char do_state Get_MQ5_DO(); lc_printf(MQ5 DO State %d, do_state); if(do_state 0) { lc_printf( (Gas detected!)\r\n); } else { lc_printf( (Normal)\r\n); } // 延时500ms再读下一次 delay_ms(500); } }编译下载到开发板打开串口调试助手波特率一般115200你会看到类似这样的输出MQ-5 Sensor Start... Please wait 1-2 minutes for sensor preheating... MQ5 ADC Value 1250 MQ5 Percentage [30%] MQ5 DO State 1 (Normal) MQ5 ADC Value 1280 MQ5 Percentage [31%] MQ5 DO State 1 (Normal)5.1 实际测试与校准上电后别急着看数据先等1-2分钟让传感器预热。你会观察到刚上电ADC值可能很低几十到几百然后慢慢上升预热稳定后在清洁空气中ADC值会稳定在一个基线值比如1200左右对应约30%靠近气体源用打火机不点火轻轻放气靠近传感器ADC值会迅速上升可能到3000以上DO引脚变化当ADC值超过某个阈值时DO引脚会从1变成0这个基线值很重要它是清洁空气下的参考值。实际应用中你可以简单判断当ADC值比基线值高很多时认为有气体泄漏设置阈值比如if(Get_MQ5_Percentage_value() 60) { 报警 }使用DO直接读取DO引脚通过电位器调整报警灵敏度5.2 调试技巧和常见问题问题1ADC读数跳变太大可能原因电源噪声、采样次数太少解决方法增加SAMPLES的值比如从30改成50或者在VCC和GND之间加个100uF的电容问题2DO引脚一直为0或一直为1检查接线确认DO引脚接到了正确的GPIO调整电位器用小螺丝刀轻轻旋转模块上的蓝色电位器检查代码确认GPIO_DO_PIN宏定义正确问题3响应速度慢原因MQ-5本身响应就慢特别是从高浓度回到清洁空气时注意这是气敏传感器的特性不是代码问题。如果需要快速检测要考虑其他类型的传感器。6. 项目扩展思路基本的读取功能实现了你可以在这个基础上做很多扩展1. 浓度标定和换算现在的百分比只是相对值。如果你想得到实际的气体浓度比如ppm单位需要在已知浓度的气体环境中测试用标准气体记录多个浓度点对应的ADC值建立ADC值与实际浓度的关系曲线通常是线性或对数关系2. 增加报警功能// 简单的软件报警 if(Get_MQ5_Percentage_value() 70) { // 点亮LED报警 // 或者控制蜂鸣器 // 甚至可以通过Wi模块发送报警信息到手机 }3. 数据记录和显示把ADC值保存到数组绘制浓度变化曲线连接OLED屏幕实时显示浓度和状态通过串口发送到电脑用上位机软件显示波形4. 多传感器融合同时接温湿度传感器如DHT11因为温湿度会影响气体检测接多个MQ系列传感器区分不同气体类型这个MQ-5驱动我已经在好几个项目里用过了稳定性不错。最需要注意的就是预热时间一定要够不然读数不准。还有传感器不要长时间暴露在高浓度气体中会影响寿命。代码里我加了详细的注释你直接复制就能用。如果遇到问题先检查接线再看SysConfig配置是否正确。嵌入式开发就是这样一点点调试成功了就很有成就感。