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

一、项目需求

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值