STM32-笔记37-吸烟室管控系统项目

news2025/3/12 6:37:51

一、项目需求

1. 使用 mq-2 获取环境烟雾值,并显示在 LCD1602 上;

2. 按键修改阈值,并显示在 LCD1602 上;

3. 烟雾值超过阈值时,蜂鸣器长响,风扇打开;烟雾值小于阈值时,蜂鸣器不响,风扇关闭;

二、项目框图

三、介绍烟雾传感器(MQ-2)

四、项目实现

复制项目文件夹19-串口打印功能

重命名为46-烟雾报警系统项目

打开项目工程,加载文件

main.c

#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "adc.h"
#include "key.h"
#include "LCD1602.h"
#include "fan.h"
#include "beep.h"


uint16_t adc_result = 0;

int main(void)
{
    float smoke_value = 0;
    float limit_value = 1.0;
    uint8_t key_num = 0;
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    led_init();//初始化led灯
    uart1_init(115200);
    //adc
    adc_dma_init();
    key_init();
    lcd1602_init();
    beep_init();
    fan_init();
    printf("hello world!\r\n");
    
    lcd1602_show_line(1,1,"Smoke:   0.0 V");
    lcd1602_show_line(2,1,"Limit: - 1.0 +");
    
    while(1)
    { 
        key_num = key_scan();
        if(key_num == 1)
            limit_value +=0.1;
        else if(key_num == 2)
            limit_value -=0.1;
        //通过按键更改阈值
        lcd1602_display_limit(limit_value);
        
        smoke_value = adc_get_smoke();
        lcd1602_display_smoke(smoke_value);
        //判断smoke_value的值是不是大于limit_value
        //判断烟雾的值是不是大于我们限定的值
        if(smoke_value > limit_value)
        {
            beep_ON();
            fan_ON();
        }
        else
        {
            beep_OFF();
            fan_OFF();
        }
    }
}

LCD1602.c

adc.c

#include "adc.h"

DMA_HandleTypeDef dma_handle = {0};//DMA的句柄
ADC_HandleTypeDef adc_handle = {0};//ADC的句柄

uint16_t adc_value = 0;

//初始化ADC函数
void adc_config(void)
{
    adc_handle.Instance = ADC1;//基地址
    adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;//数据右对齐
    adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;//要不要扫描?不需要扫描
    adc_handle.Init.ContinuousConvMode = ENABLE;//连续模式?连续转换模式
    adc_handle.Init.NbrOfConversion = 1;//转换个数?1个
    adc_handle.Init.DiscontinuousConvMode = DISABLE;//间断模式?不间断模式
    adc_handle.Init.NbrOfDiscConversion = 0;//间断个数0
    adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;//触发方式:软件触发
    HAL_ADC_Init(&adc_handle);
    
    HAL_ADCEx_Calibration_Start(&adc_handle);//ADC校准
}
//初始化msp函数
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1)//判断是不是ADC1
    {
        RCC_PeriphCLKInitTypeDef adc_clk_init = {0};//ADC时钟句柄
        GPIO_InitTypeDef gpio_init_struct = {0};//GPIO的句柄
        
        __HAL_RCC_ADC1_CLK_ENABLE();//打开ADC1的时钟
        __HAL_RCC_GPIOB_CLK_ENABLE();//打开GPIO口的时钟
        
        gpio_init_struct.Pin = GPIO_PIN_0;//引脚
        gpio_init_struct.Mode = GPIO_MODE_ANALOG;//模式:虚拟量的输入
        HAL_GPIO_Init(GPIOB, &gpio_init_struct);
        
        adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;//外设的时钟选择:ADC
        adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;//分频?6分频
        HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);//ADC时钟初始化函数
    }
}
void dma_config(void)
{
    __HAL_RCC_DMA1_CLK_ENABLE();
    dma_handle.Instance = DMA1_Channel1;//通道1
    dma_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;//外设到内存
    
    //内存相关配置
    dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;//半字对齐
    dma_handle.Init.MemInc = DMA_MINC_ENABLE;//内存增量失能模式
    
    //外设相关配置
    dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;//半字对其
    dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;//内存增量失能模式
    
    dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM;//DMA优先级
    dma_handle.Init.Mode = DMA_CIRCULAR;//模式:循环搬运模式
    HAL_DMA_Init(&dma_handle);
    //这行代码的作用是将ADC的句柄(adc_handle)与DMA的句柄(dma_handle)关联起来
    __HAL_LINKDMA(&adc_handle, DMA_Handle, dma_handle);//当ADC完成数据采集时,数据可以直接通过DMA传输到指定的内存地址,而不需要CPU的干预。
}
//通道配置的函数
void adc_channel_config(ADC_HandleTypeDef* hadc, uint32_t ch, uint32_t rank, uint32_t stime)
{
    //
    ADC_ChannelConfTypeDef adc_ch_config = {0};
    
    adc_ch_config.Channel = ch;//指定通道-外界传进来
    adc_ch_config.Rank = rank;//序列-外界传进来
    adc_ch_config.SamplingTime = stime;//取样时间-外界传进来
    HAL_ADC_ConfigChannel(hadc, &adc_ch_config);//通道配置
}
//adc dma 初始化函数
void adc_dma_init(void)
{
    adc_config();
    //adc句柄,通道,序列号,ADC采样的时间
    adc_channel_config(&adc_handle, ADC_CHANNEL_8, ADC_REGULAR_RANK_1, ADC_SAMPLETIME_239CYCLES_5);
    dma_config();
    //启动adc,ADC转化完的数据通过DMA搬运出来,从ADC外设传输到存储器的长度
    HAL_ADC_Start_DMA(&adc_handle, (uint32_t *)&adc_value, 1);//mar是目标缓冲区的地址
}
//定义一个函数:把获取电压的值给返回出来
float adc_get_smoke(void)
{
    return (float)adc_value / 4096 * 3.3;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VUE3配置后端地址,实现前后端分离及开发、正式环境分离

新建.env.development及.env.production .env.development 指定开发环境地址.env.production 指定生产环境地址 格式如下 VITE_APP_BASE_APIhttp://localhost:8070只需要在对应文件写入对应的后端地址即可 修改env.d.ts /// <reference types"vite/client" /…

win32汇编环境,在窗口程序中画五边形与六边形

;运行效果 ;win32汇编环境,在窗口程序中画五边形与六边形 ;展示五边形与六边形的画法 ;将代码复制进radasm软件里,直接编译可运行.重要部分加备注。 ;下面为asm文件 ;>>>>>>>>>>>>>>>>>>>>>>>>>…

Java Web开发进阶——Spring Boot基础

Spring Boot是基于Spring框架的新一代开发框架&#xff0c;旨在通过自动化配置和简化的开发方式提升生产效率。它将复杂的配置抽象化&#xff0c;让开发者专注于业务逻辑实现&#xff0c;而无需关注繁琐的基础配置。 1. Spring Boot简介与优势 Spring Boot 是 Spring 家族中的…

【Linux】文件系统命令

目录 文件系统命令 Linux文件系统 文件操作相关命令 文件系统命令 磁盘文件系统&#xff1a;指本地主机中实际可以访问到的文件系统&#xff0c;包括硬盘、CD-ROM、DVD、USB存储器、磁盘阵列等。常见文件系统格式有&#xff1a;autofs、coda、Ext&#xff08;Extended File…

关于变电站及线路接线情况展示的一些想法

以前总项目的时候总习惯于给变电站画个轮廓和接线点&#xff0c;要不就是给变电站3D建模。费时、费力效果还不一定好!其实&#xff0c;像上图一样线路搭配高清影像效果是不是会更好&#xff1f;尤其变电站区域可以使用航飞0.2米左右的数据&#xff0c;基本上站内设备都能看清了…

【OceanBase】使用 Superset 连接 OceanBase 数据库并进行数据可视化分析

文章目录 前言一、前提条件二、操作步骤2.1 准备云主机实例2.2 安装docker-compose2.3 使用docker-compose安装Superset2.3.1 克隆 Superset 的 GitHub 存储库2.3.2 通过 Docker Compose 启动 Superset 2.4 开通 OB Cloud 云数据库2.5 获取连接串2.6 使用 Superset 连接 OceanB…

开源平台Kubernetes的优势是什么?

Kubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;方便进行声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统&#xff0c;其服务、支持和工具的使用范围广泛。 Kubernetes 这个名字源于希腊语&#xff0c;意…

“大数据+职业本科”:VR虚拟仿真实训室的发展前景

在新时代背景下&#xff0c;随着科技的飞速进步和产业结构的不断升级&#xff0c;职业教育正迎来前所未有的变革。“大数据职业本科”的新型教育模式&#xff0c;结合VR&#xff08;虚拟现实&#xff09;技术的广泛应用&#xff0c;为实训教学开辟了崭新的道路&#xff0c;尤其…

flask实现国外大学生志愿者管理服务系统【英文】

完整源码项目包获取→点击文章末尾名片&#xff01;

lambda用法及其原理

目录 lambda形式lambda用法1.sort降序2.swap3.捕捉列表 习题解题 lambda形式 [capture-list](parameters)->return type{function boby}[capture-list]&#xff1a;[捕捉列表]用于捕捉函数外的参数&#xff0c;可以为空&#xff0c;但不能省略&#xff1b;(parameters) &am…

Street Surf 的学习

数据结构和组织 定义了一个 scenebank 的 数据结构。 这篇文章定义了两种 采样 方式&#xff1a; JointFramePixelDataset 【任意帧中选择任意的 Pixel】PixelDataset [从固定的帧中选择任意的Pixel]ImagePatchDataset [基于image patch 的采样方式&#xff0c;可以用于 mono…

IP查询于访问控制保护你我安全

IP地址查询 查询方法&#xff1a; 命令行工具&#xff1a; ①在Windows系统中&#xff0c;我们可以使用命令提示符&#xff08;WINR&#xff09;查询IP地址&#xff0c;在弹窗中输入“ipconfig”命令查看本地网络适配器的IP地址等配置信息&#xff1b; ②在Linux系统中&…

大模型 LangChain-LangGraph 初探

大模型 LangChain-LangGraph 初探 一、LangGraph 简介 LangGraph&#xff08;https://langchain-ai.github.io/langgraph/&#xff09;是一个用于构建有状态、多参与者应用程序的库&#xff0c;在创建代理和多代理工作流方面发挥着重要作用。与其他大语言模型&#xff08;LLM…

yolov5核查数据标注漏报和误报

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、误报二、漏报三、源码总结 前言 本文主要用于记录数据标注和模型预测之间的漏报和误报思想及其源码 提示&#xff1a;以下是本篇文章正文内容&#xff0c;…

【Linux】进程间通信(一)

目录 一、进程间通信1.1 进程间通信目的1.2 理解进程间通信1.3 进程间通信发展1.4 进程间通信分类 二、管道2.1 什么是管道2.2 管道的原理2.3 匿名管道2.3.1 pipe函数2.3.2 匿名管道的实现2.3.3 匿名管道小结2.3.3.1 匿名管道的四种情况2.3.3.2 匿名管道的五种特性 2.3.4 匿名管…

【QT-QTableView实现鼠标悬浮(hover)行高亮显示+并设置表格样式】

1、自定义委托类 HoverDelegate hoverdelegate.h #ifndef HOVERDELEGATE_H #define HOVERDELEGATE_H#include <QObject> #include <QStyledItemDelegate>class hoverdelegate : public QStyledItemDelegate {Q_OBJECT // 添加 Q_OBJECT 宏public:explicit hoverde…

Elasticsearch:基础概念

这里写目录标题 一、什么是Elasticsearch1、基础介绍2、什么是全文检索3、倒排索引4、索引&#xff08;1&#xff09;创建索引a 创建索引基本语法b 只定义索引名&#xff0c;setting、mapping取默认值c 创建一个名为student_index的索引&#xff0c;并设置一些自定义字段 &…

RAG Logger:RAG日志记录工具

您听说过 RAG Logger 吗&#xff1f; 它是一款专为检索增强生成 (RAG) 应用程序设计的开源日志记录工具&#xff01; 据说它可以作为 LangSmith 的轻量级替代方案&#xff0c;满足 RAG 特定的日志记录需求。 查询、搜索结果、LLM 交互和性能指标可以以 JSON 格式记录。 特点 …

Spark-Streaming有状态计算

一、上下文 《Spark-Streaming初识》中的NetworkWordCount示例只能统计每个微批下的单词的数量&#xff0c;那么如何才能统计从开始加载数据到当下的所有数量呢&#xff1f;下面我们就来通过官方例子学习下Spark-Streaming有状态计算。 二、官方例子 所属包&#xff1a;org.…

gesp(C++四级)(4)洛谷:B3851:[GESP202306 四级] 图像压缩

gesp(C四级)&#xff08;4&#xff09;洛谷&#xff1a;B3851&#xff1a;[GESP202306 四级] 图像压缩 题目描述 图像是由很多的像素点组成的。如果用 0 0 0 表示黑&#xff0c; 255 255 255 表示白&#xff0c; 0 0 0 和 255 255 255 之间的值代表不同程度的灰色&#xff0…