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

基于立创开发板的红外火焰传感器模块驱动移植与实战应用

基于立创开发板的红外火焰传感器模块驱动移植与实战应用

最近在做一个智能小车的项目,需要让小车能“看见”火源,于是就用上了红外火焰传感器。网上买的通用模块,到手后第一件事就是把它驱动起来,集成到我的立创开发板(STM32F103)上。整个过程从原理理解、引脚连接到代码编写,踩过一些小坑,也总结了一些经验。今天我就把这个完整的驱动移植过程分享给大家,手把手教你如何让火焰传感器在立创开发板上跑起来,最终输出一个直观的“火源强度百分比”。

无论你是正在做灭火机器人、智能车,还是单纯想学习传感器应用,这篇教程都能帮你快速上手。

1. 火焰传感器模块:你的“电子眼”

在开始写代码之前,咱们得先搞清楚手里这个传感器是什么、能干什么。这就像打仗前得先了解自己的武器。

1.1 模块原理与特性

你手上这个红外火焰传感器,本质上是一个“红外光强度检测器”。它的核心是一个对特定红外光敏感的光电二极管。

  • 它能“看”到什么?它专门探测波长在700纳米到1000纳米范围内的红外光。火焰(尤其是明火)会发出大量的这种红外辐射,所以传感器就能“看见”火。它的探测角度大约是60度,就像一个视野不太宽的“眼睛”。
  • 它是怎么“看”的?当红外光照射到传感器内部的敏感元件上时,元件的电导率会发生变化,从而引起电流变化。这个电流变化经过模块上的电路处理,最终转换成我们可以读取的信号。
  • 它怎么告诉我们“看到了什么”?这个模块提供了两种“说话”方式:
    1. 模拟量输出 (AO):直接输出一个电压值(0-3.3V或0-5V)。红外光越强,输出电压越低;光越弱,输出电压越高。这个信号是连续的,能反映火焰的“强弱程度”。
    2. 数字量输出 (DO):模块上还有一个LM393电压比较器芯片。你可以通过板载的电位器设定一个阈值电压。当AO端的电压低于这个阈值(即红外光强到一定程度),DO引脚就会从高电平变成低电平,同时板载的指示灯会亮起。这是一个“有”或“无”的开关信号,适合做简单的火焰报警。

简单理解:AO告诉你“火有多大”,DO告诉你“有没有火”

1.2 模块规格与接线

先看看模块的基本参数,这对供电和编程很重要:

项目参数
工作电压3.3V - 5V (与立创开发板完美兼容)
探测距离约1米 (实际受火焰大小和环境光影响)
输出信号AO (模拟量), DO (数字量)
接口类型4 Pin 2.54mm间距排针

模块通常有4个引脚:VCC、GND、AO、DO。接线非常简单:

  1. VCC-> 接到开发板的3.3V引脚。
  2. GND-> 接到开发板的GND引脚。
  3. AO-> 接到开发板的某个ADC 输入引脚(我们后面选PA5)。
  4. DO-> 接到开发板的某个普通GPIO输入引脚(我们后面选PA6)。

注意:虽然模块支持5V,但为了与STM32的IO电平匹配,强烈建议使用3.3V供电,避免意外损坏MCU。

2. 驱动移植:让开发板与传感器“对话”

理解了传感器,接下来就是重头戏:编写驱动程序,让STM32能够读取传感器的数据。我们会创建两个文件:bsp_flame.cbsp_flame.h。“bsp”是“板级支持包”的意思,我们把针对这个传感器的底层操作都封装在这里。

2.1 硬件连接与引脚定义

根据立创开发板的资源,我们做如下引脚分配:

  • AO引脚:连接到PA5。PA5对应STM32的ADC1 通道5,正好用来做模拟量采集。
  • DO引脚:连接到PA6。我们将其配置为上拉输入,用来读取高低电平。

bsp_flame.h头文件里,我们把这些硬件相关的定义写清楚:

#ifndef _BSP_FLAME_H_ #define _BSP_FLAME_H_ #include "stm32f10x.h" // 时钟和ADC外设定义 #define RCC_FLAME_GPIO RCC_APB2Periph_GPIOA #define RCC_FLAME_ADC RCC_APB2Periph_ADC1 #define PORT_ADC ADC1 #define CHANNEL_ADC ADC_Channel_5 // 对应PA5 // AO引脚 (ADC输入) 定义 #define PORT_FLAME_AO GPIOA #define GPIO_FLAME_AO GPIO_Pin_5 // DO引脚 (数字输入) 定义 #define PORT_FLAME_DO GPIOA #define GPIO_FLAME_DO GPIO_Pin_6 // 采样次数,用于软件滤波,取平均值 #define SAMPLES 30 // 函数声明 void ADC_FLAME_Init(void); unsigned int Get_Adc_FLAME_Value(void); unsigned int Get_FLAME_Percentage_value(void); unsigned char Get_FLAME_Do_value(void); #endif

2.2 初始化ADC与GPIO

传感器要工作,首先得给它的“耳朵”(ADC)和“手脚”(GPIO)做好设置。这个工作我们在ADC_FLAME_Init函数里完成。

void ADC_FLAME_Init(void) { // 1. 开启时钟:就像给设备通电 RCC_APB2PeriphClockCmd (RCC_FLAME_GPIO, ENABLE); // 使能GPIOA时钟 RCC_APB2PeriphClockCmd (RCC_FLAME_ADC, ENABLE); // 使能ADC1时钟 GPIO_InitTypeDef GPIO_InitStructure; // 2. 配置AO引脚 (PA5) 为模拟输入模式 // 模拟输入模式是ADC采集的专用模式,引脚直接连接到ADC内部 GPIO_InitStructure.GPIO_Pin = GPIO_FLAME_AO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 关键!必须设为模拟输入 GPIO_Init(PORT_FLAME_AO, &GPIO_InitStructure); // 3. 配置DO引脚 (PA6) 为上拉输入模式 // 上拉输入意味着默认读到高电平,当传感器DO输出低电平时才能被拉低 GPIO_InitStructure.GPIO_Pin = GPIO_FLAME_DO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入 GPIO_Init(PORT_FLAME_DO, &GPIO_InitStructure); // 4. 复位并初始化ADC1 ADC_DeInit(PORT_ADC); // 先复位到默认状态 ADC_InitTypeDef ADC_InitStruct; ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; // 独立模式,单ADC工作 ADC_InitStruct.ADC_ScanConvMode = DISABLE; // 非扫描模式,只用一个通道 ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; // 开启连续转换,ADC会不停采样 ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发,不用外部信号 ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐,方便读取 ADC_InitStruct.ADC_NbrOfChannel = 1; // 转换通道数为1 ADC_Init(PORT_ADC, &ADC_InitStruct); // 5. 配置ADC时钟和采样通道 RCC_ADCCLKConfig(RCC_PCLK2_Div6); // ADC时钟设为PCLK2的6分频,通常为12MHz,保证精度 // 指定ADC1的通道5(PA5)作为采样通道,采样顺序为1,采样时间设为55.5个周期(稍长,更稳定) ADC_RegularChannelConfig(PORT_ADC, CHANNEL_ADC, 1, ADC_SampleTime_55Cycles5); // 6. 使能ADC并执行校准(非常重要!) ADC_Cmd(PORT_ADC, ENABLE); // 打开ADC电源 // ADC校准可以减小零点误差和增益误差,是保证采样准确性的关键步骤 ADC_ResetCalibration(PORT_ADC); while (ADC_GetResetCalibrationStatus(PORT_ADC)); // 等待复位完成 ADC_StartCalibration(PORT_ADC); while (ADC_GetCalibrationStatus(PORT_ADC)); // 等待校准完成 // 7. 启动连续转换 ADC_SoftwareStartConvCmd(PORT_ADC, ENABLE); }

提示:STM32的ADC校准步骤很容易被初学者忽略,如果不校准,采集的值可能会有固定的偏差。务必记得在使能ADC后、开始转换前执行校准。

2.3 编写数据读取函数

初始化完成后,我们就可以随时读取数据了。我们编写三个函数,分别用于读取原始ADC值、计算火焰强度百分比、读取数字开关量。

1. 读取原始ADC值这个函数最简单,就是直接从ADC数据寄存器里把转换好的数字值读出来。

unsigned int Get_Adc_FLAME_Value(void) { uint32_t data = ADC_GetConversionValue(PORT_ADC); // 读取ADC转换结果 delay_1ms(20); // 稍作延时,避免读取过于频繁 return data; // 返回0-4095之间的值 }

2. 读取并计算火焰强度百分比这是核心功能函数。直接读ADC值不够直观(值越小代表火越强),我们把它转换成0%-100%的百分比,100%代表检测到最强火焰。

unsigned int Get_FLAME_Percentage_value(void) { uint32_t i = 0; uint32_t adc_max = 4095; // STM32的12位ADC最大值 uint32_t adc_new = 0; uint32_t Percentage_value = 0; // 软件滤波:连续采样SAMPLES次(30次),然后取平均值 // 这样可以有效消除单次采样的偶然误差和噪声干扰 for(i = 0; i < SAMPLES; i++) { adc_new += Get_Adc_FLAME_Value(); // 累加采样值 delay_ms(5); // 每次采样间隔5ms } adc_new = adc_new / SAMPLES; // 计算平均值 // 核心转换公式: // 1. (float)adc_new / (float)adc_max : 得到当前ADC值占满量程的比例。 // 2. 用1.0减去这个比例:因为ADC值越小代表光越强,所以需要反过来。 // 3. 乘以100.0f:转换成百分比。 Percentage_value = ( 1.0f - ( (float)adc_new / (float)adc_max ) ) * 100.0f; return Percentage_value; }

注意这个公式百分比 = (1 - ADC采样值/4095) * 100。这是理解传感器特性的关键。当传感器前方无火源(红外光最弱)时,ADC值接近4095,计算结果接近0%。当用火苗靠近(红外光最强)时,ADC值会变小,计算结果趋近100%。

3. 读取数字开关量这个函数就非常直接了,就是读取我们之前配置的PA6引脚的电平状态。

unsigned char Get_FLAME_Do_value(void) { // 读取PA6引脚的电平,返回0(低电平,检测到火焰)或1(高电平,未检测到火焰) return GPIO_ReadInputDataBit(PORT_FLAME_DO, GPIO_FLAME_DO); }

数字输出的阈值可以通过模块上的蓝色电位器调节。顺时针旋转,灵敏度降低(需要更强的火才能触发);逆时针旋转,灵敏度增高。

3. 实战应用:在主程序中测试

驱动写好了,最后一步就是在主函数里调用它,看看效果。我们让开发板每隔半秒通过串口打印出当前的火焰强度百分比。

#include "stm32f10x.h" #include "board.h" #include "bsp_uart.h" #include "stdio.h" #include "bsp_flame.h" // 包含我们刚写的驱动头文件 int main(void) { board_init(); // 立创开发板基础初始化(系统时钟、滴答定时器等) uart1_init(115200); // 初始化串口1,用于打印数据到电脑 ADC_FLAME_Init(); // 初始化火焰传感器ADC和GPIO printf("火焰传感器测试程序启动...\r\n"); while(1) { // 读取并打印火焰强度百分比 printf("火焰强度 = %d%%\r\n", Get_FLAME_Percentage_value()); // 也可以同时读取数字输出状态 // if(Get_FLAME_Do_value() == 0) { // printf("警告:检测到火焰!\r\n"); // } delay_ms(500); // 延时500毫秒 } }

将程序编译下载到立创开发板,打开串口调试助手(如XCOM,波特率115200),你就能看到不断输出的百分比数据了。

动手验证: 拿一个打火机(小心烫伤!)或者点燃一小片纸巾,在传感器前方约20-50厘米处晃动。你应该能看到输出的百分比数值显著上升。远离火源后,百分比会下降。这就是你的STM32在“感知”火焰!

通过这个实战项目,你不仅学会了如何驱动一个具体的传感器,更重要的是掌握了将通用模块移植到特定平台的标准流程:理解原理 -> 定义硬件 -> 编写初始化 -> 实现数据读取 -> 主程序验证。这个思路可以应用到绝大多数传感器和外围器件上。

http://www.cnnetsun.cn/news/1310123.html

相关文章:

  • Ncorr数字图像相关技术全攻略:从原理到工程实践
  • 热电阻接线方式全解析:两线、三线、四线制到底怎么选?
  • 从Skia到GPU:OpenGL与Mesa在图形栈中的协同与定位
  • 向日葵远程控制安全事件真相:官方辟谣与行业影响分析
  • 造相Z-Image与Stable Diffusion对比:轻量、高效、中文友好的新选择
  • FireRed-OCR Studio惊艳效果:无框线表格+LaTeX公式Markdown输出实测
  • AD9361寄存器配置全解析:从ENSM状态机到滤波器设计的实战指南
  • 静息态fMRI数据分析实战:从BOLD信号到功能连接的全流程解析(附避坑指南)
  • Windows用户必看:PaddleOCR PDF转Word完整避坑指南(附Shapely安装解决方案)
  • Johnson算法实战:如何用Python优化流水线作业调度(附完整代码)
  • RK3576、RK3588、RK3568:三款主流AIoT芯片的精准选型与场景适配指南
  • 泰凌微TLSR825X定时器实战:从硬件配置到软件轮询的完整指南
  • PyTorch进阶(15)-- torch.flatten()方法的深度解析与实战应用
  • GPT-3提示工程实战:从零开始构建高效prompt的5个技巧(附Playground示例)
  • 【VS Code】Windows10下VS Code搭建Java开发环境全攻略
  • 提升效率:用快马AI一键生成模块化计算机组成原理模拟器框架
  • ChatGLM3-6B功能体验:智能缓存技术,刷新页面无需重载模型
  • Phi-3-mini-128k-instruct助力软件测试:自动生成测试用例与缺陷报告
  • Vue3+ElementPlus避坑指南:el-pagination的total必须用Number类型?
  • 利用ABAP BAPI与OLE自动化,构建SE11对象批量生成与模板管理工具
  • PCIe 流量控制机制:信用管理的艺术
  • Realistic Vision V5.1写实模型效果对比:V5.0 vs V5.1在手部结构与发丝表现差异
  • 反射体系实战
  • CLIP-GmP-ViT-L-14算法精讲:深入理解对比学习与图文预训练核心技术
  • 第 178 场双周赛Q1:101014. 找到第一个唯一偶数
  • 基于RA - AF的高斯混合聚类裂纹模式识别:MATLAB实现
  • java8案例对list[过滤、分组,转换,查找等]清洗逻辑
  • Csimplecleaner:C盘维护与空间管理的最佳实践
  • 智能科学与技术毕业设计2026开题指导
  • LeetCode热题100 括号生成