火灾报警(烟雾&火焰检测)-STM8L

最终实现效果

正常运行火灾检测

设计目标

  1. 火焰检测报警(4方向),指示灯红色,蜂鸣器一直鸣叫。
  2. 烟雾报警,指示灯蓝色,蜂鸣器周期性鸣叫。
  3. 正常状态,指示灯绿色,蜂鸣器不叫。

硬件设计

总电路图

总电路图

电源部分

电路供电可使用单个锂电池或外部5V供电,电路集成锂电池充电电路(TP4056),外部电源与锂电池供电自动切换,有外部供电时,使用外部电源,5V电源由SX1308经过升压得到,一个拨动开关控制系统电源(不控制锂电池充电,即系统未开,有外部供电也会对锂电池进行充电),3.3V由升压得到的5V经过稳压得到,火焰检测方向指示灯的电源可控,即可以控制指示灯是否显示。

四方向火焰检测

使用四个红外接收二极管作为火焰检测传感器,使用4路电压比较器LM339进行电压比较,检测到火焰输出低电平。可调整比较值VREF1,调整检测灵敏度。

烟雾与温度检测

烟雾检测使用MQ-2B烟雾传感器,温度使用NTC,分别设置比较阈值VREF2,VREF3,通过二路比较器LM393进行电压比较,输出端使用二极管来实现5V转3.3V。

软件设计

代码功能较为简单,有注释,就不多讲了。

#include "stm8l15x.h"//STM8L051/151公用库函数
#include "bsp_led.h"
#include "stdio.h"
void delay_us(u16 nCount);
void delay_ms(u16 nCount);
/**********************************************************************************************************
*   函 数 名: delay_us
*   功能说明: 微秒延时程序
*   形    参:nCount要延时的微秒数
*   返 回 值: 无
**********************************************************************************************************/
void delay_us(u16 nCount)
{
    nCount *= 3;
    while (--nCount);
}

/**********************************************************************************************************
*   函 数 名: delay_ms
*   功能说明: 毫秒延时程序
*   形    参:nCount要延时的毫米数
*   返 回 值: 无
**********************************************************************************************************/
void delay_ms(u16 nCount)
{
    while (nCount--)
    {
        delay_us(1000);
    }
}

void UART1_Send_byte(unsigned char byte)  //发送一个8位的数据
{
    USART_SendData8(USART1, byte);//将接收到的数据发送出去
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
void UART1_Send_str(unsigned char *str)   //发送字符串的数据
{
    while (*str)
    {
        UART1_Send_byte(*str);
        str++;
    }
}
//将有符合整数转换为字符串
char *itoa(int num, char *str, int radix)
{
    char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //索引表
    unsigned unum;//存放要转换的整数的绝对值,转换的整数可能是负数
    int i = 0, j, k; //i用来指示设置字符串相应位,转换之后i其实就是字符串的长度;转换后顺序是逆序的,有正负的情况,k用来指示调整顺序的开始位置;j用来指示调整顺序时的交换。

    //获取要转换的整数的绝对值
    if (radix == 10 && num < 0) //要转换成十进制数并且是负数
    {
        unum = (unsigned) - num; //将num的绝对值赋给unum
        str[i++] = '-'; //在字符串最前面设置为'-'号,并且索引加1
    }
    else unum = (unsigned)num; //若是num为正,直接赋值给unum

    //转换部分,注意转换后是逆序的
    do
    {
        str[i++] = index[unum % (unsigned)radix]; //取unum的最后一位,并设置为str对应位,指示索引加1
        unum /= radix; //unum去掉最后一位

    }
    while (unum);//直至unum为0退出循环

    str[i] = '\0'; //在字符串最后添加'\0'字符,c语言字符串以'\0'结束。

    //将顺序调整过来
    if (str[0] == '-') k = 1; //如果是负数,符号不用调整,从符号后面开始调整
    else k = 0; //不是负数,全部都要调整

    char temp;//临时变量,交换两个值时用到
    for (j = k; j <= (i - 1) / 2; j++) //头尾一一对称交换,i其实就是字符串的长度,索引最大值比长度少1
    {
        temp = str[j]; //头部赋值给临时变量
        str[j] = str[i - 1 + k - j]; //尾部赋值给头部
        str[i - 1 + k - j] = temp; //将临时变量的值(其实就是之前的头部值)赋给尾部
    }

    return str;//返回转换后的字符串
}
void Init_Timer4(void)
{
    /* Init TIMER 4 */
    CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);//将主时钟信号送给定时器4(L系列单片机必需)
    /* HSI div by 1 --> Auto-Reload value: 16M / 64 = 1/4M, 1/4M / 1k = 250*/
//  TIM4_DeInit();
    TIM4_TimeBaseInit(TIM4_Prescaler_64, 250); //T=1ms  64分频 X=16M/64    中断溢出=X/250 进中断一次1ms
    TIM4_SetCounter(250);
    TIM4_ClearFlag(TIM4_FLAG_Update);
    TIM4_ITConfig(TIM4_IT_Update, ENABLE);
    TIM4_Cmd(ENABLE);
}

/* Includes ------------------------------------------------------------------*/


/* Private defines -----------------------------------------------------------*/
uint8_t Scan_Flag = 0;
uint16_t Fire_Scan_Count = 0;
uint16_t Smoke_Scan_Count = 0;
//uint8_t Temp_Humi_GET = 0;
uint8_t Warning_Flag = 0;
uint8_t Sec_Flag = 0;
uint8_t Sec_Count = 0;
uint8_t BEEP_Flag = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
uint8_t showstr[20] = {0};
void main(void)
{
//    uint8_t i = 0;
//    int16_t Temp = 10;
//    uint16_t Humi = 20;
//    uint8_t data_temp = 0;
    uint8_t scan_temp = 0;
    /* Infinite loop */
    //使用内部HSI 16M 不分频
    CLK_HSICmd(ENABLE);//开始内部高频RC
    CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);//HSI为系统时钟
    CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);//不分频,16M

    CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);//开启USART时钟
//SYSCFG_REMAPPinConfig(REMAP_Pin_USART1TxRxPortA,ENABLE);//端口重映射,去掉注释之后USART1为PA2-TX、PA3-RX;注释之后USART1为TX-PC5、RX-PC6;复位之后USART会自动恢复至PC5、PC6
    USART_Init(USART1, (uint32_t)9600, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, (USART_Mode_TypeDef)(USART_Mode_Tx | USART_Mode_Rx)); //设置USART参数9600,8N1,接收/发送
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能接收中断
    USART_Cmd(USART1, ENABLE);//使能USART
    Init_Timer4();
    enableInterrupts(); //中断使能
    LED_Init();      //LED GPIO 管脚初始化
//    LED_POWER_ON();
    GPIO_Init(GPIOB, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4, GPIO_Mode_In_PU_No_IT); //输入上拉无中断
    GPIO_Init(GPIOC, GPIO_Pin_4, GPIO_Mode_In_PU_No_IT); //输入上拉无中断
    GPIO_Init(GPIOA, GPIO_Pin_2, GPIO_Mode_Out_PP_Low_Fast); //快速推挽输出默认低电平
    UART1_Send_str("\r\nHELLO,STM8L051!!!\r\n");
    while (1)
    {
        if (Sec_Flag)
        {
            if (++Sec_Count == 5)
            {
                if ((Fire_Scan_Count >= 20))
                {
                    Warning_Flag |= 0x80;//火灾警报
                }
                else
                {
                    Warning_Flag &= 0x7D;
                }
                if (Smoke_Scan_Count >= 20)
                {
                    Warning_Flag |= 0x40;//烟雾警报
                }
                else
                {
                    Warning_Flag &= 0xBF;
                }
                Fire_Scan_Count = 0;
                Smoke_Scan_Count = 0;
                Sec_Count = 0;
            }
            if ((Warning_Flag & 0x80) == 0x80)//火灾警报
            {
                LED2_L();
                LED_POWER_ON();
                LED1_H();
                BEEP_Flag = 1;
            }
            else
            {

                LED_POWER_OFF();
                LED1_L();
                if ((Warning_Flag & 0x40) == 0x40)//烟雾警报
                {
                    LED2_L();
                    LED3_H();
                    BEEP_Flag = 2;
                }
                else
                {
                    BEEP_Flag = 0;
                    LED3_L();
                    LED2_H();
                }
            }
            switch (BEEP_Flag)
            {
            case 0:
                GPIO_ResetBits(GPIOA, GPIO_Pin_2);
                break;
            case 1:
                GPIO_SetBits(GPIOA, GPIO_Pin_2);
                break;
            case 2:
                GPIO_ToggleBits(GPIOA, GPIO_Pin_2);
                break;
            }
            Sec_Flag = 0;
        }
        if (Scan_Flag)
        {

            scan_temp = GPIO_ReadInputData(GPIOB) & 0x1F;
            if (scan_temp != 0x1F)
            {
                if ((scan_temp >> 4) == 0)
                {
                    Smoke_Scan_Count++;
                }
                else
                {
                    Fire_Scan_Count++;
                }
            }
            scan_temp = GPIO_ReadInputData(GPIOC) & 0x10;//NTC检测
            if (scan_temp != 0x10)//温度过高
            {
              Fire_Scan_Count++;
            }
            Scan_Flag = 0;
        }
    }

}

#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */
void assert_failed(u8 *file, u32 line)
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}
#endif
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值