基于STM32单片机的智能火灾报警系统毕业论文
摘要
随着现代科技的飞速发展,智能家居系统已经成为人们生活中不可或缺的一部分。特别是在家庭安全方面,智能火灾报警系统的重要性日益凸显。本文设计了一种基于STM32F103C8T6单片机的智能火灾报警系统,该系统能够实时监测家居环境中的温度、积水、烟雾、可燃气以及火焰情况,并通过OLED液晶显示屏展示监测数据。一旦检测到异常情况,系统能够自动启动相应的报警和防护措施,如发送GSM短信报警、启动水泵抽水、启动LED和报警器以及风扇通风等,从而有效保障家庭安全。
关键词:STM32单片机;智能火灾报警系统;传感器模块;GSM模块;家庭安全
Abstract
With the rapid development of modern technology, smart home systems have become an indispensable part of people's lives. Especially in terms of home security, the importance of intelligent fire alarm systems is increasingly prominent. This paper designs an intelligent fire alarm system based on the STM32F103C8T6 microcontroller. The system can monitor the temperature, water accumulation, smoke, combustible gas, and flame conditions in the home environment in real time and display the monitoring data on an OLED LCD screen. Once an abnormal situation is detected, the system can automatically activate corresponding alarm and protective measures, such as sending GSM SMS alerts, starting water pump drainage, activating LEDs and alarms, and enabling fan ventilation, thereby effectively ensuring home security.
Keywords: STM32 microcontroller; intelligent fire alarm system; sensor module; GSM module; home security
第一章 绪论
1.1 研究背景与意义
随着城市化进程的加快,人们越来越关注家庭安全问题。火灾作为一种常见的灾害,给人们的生命财产安全带来了严重威胁。传统的火灾报警系统往往存在报警不及时、准确性不高、功能单一等问题,难以满足现代家庭对安全性的高要求。因此,开发一种具有多功能、高准确性、智能化的火灾报警系统显得尤为重要。
基于STM32单片机的智能火灾报警系统,通过集成多种传感器模块,能够实时监测家居环境中的各种潜在火灾隐患,如温度异常、烟雾浓度过高、可燃气体泄漏以及火焰等。同时,系统还能够通过GSM模块实现远程报警,及时将异常情况通知用户,从而有效缩短响应时间,提高火灾防控的效率和准确性。此外,该系统还具有设置灵活、操作简便等特点,适用于各种家庭环境,具有较高的实用价值和社会效益。
1.2 国内外研究现状
目前,国内外在智能火灾报警系统领域已经取得了显著的研究成果。国外一些先进的火灾报警系统已经实现了高度的智能化和自动化,能够实时监测多种火灾隐患,并通过网络将报警信息传输到远程监控中心。然而,这些系统往往价格昂贵,难以普及到普通家庭。
国内在智能火灾报警系统方面也取得了不少进展,但大多数系统仍然存在着功能单一、准确性不高、稳定性差等问题。因此,开发一种具有高性价比、多功能、高准确性的智能火灾报警系统仍然是当前研究的热点和难点。
1.3 研究内容与目标
本文旨在设计一种基于STM32单片机的智能火灾报警系统,该系统能够实现以下功能:
(1)实时监测家居环境中的温度、积水、烟雾、可燃气体以及火焰情况;
(2)通过OLED液晶显示屏展示监测数据;
(3)在检测到异常情况时,自动启动相应的报警和防护措施,如发送GSM短信报警、启动水泵抽水、启动LED和报警器以及风扇通风等;
(4)允许用户通过按键模块设置相关参数,提高系统的灵活性和适用性。
本文的研究目标是开发出一种功能完善、准确性高、稳定性好的智能火灾报警系统,为家庭安全提供有力保障。
第二章 系统总体设计
2.1 系统组成
基于STM32单片机的智能火灾报警系统主要由STM32F103C8T6单片机、OLED液晶显示屏、温度传感器模块、水位传感器模块、烟雾传感器模块、可燃气体传感器模块、火焰传感器模块、水泵模块、LED灯模块、风扇模块、GSM模块、报警器模块、显示屏模块以及按键模块等组成。
2.2 系统架构
系统的整体架构如图2.1所示。其中,STM32F103C8T6单片机作为系统的核心控制器,负责接收各传感器模块的数据,并进行处理和分析。OLED液晶显示屏用于显示监测数据,方便用户实时查看家居环境的状态。各传感器模块负责实时监测家居环境中的温度、积水、烟雾、可燃气体以及火焰等参数。水泵模块、LED灯模块、风扇模块以及报警器模块则用于在检测到异常情况时执行相应的防护措施。GSM模块用于实现远程报警功能,将异常情况及时通知用户。按键模块则允许用户设置相关参数,提高系统的灵活性和适用性。
图2.1 系统架构图
2.3 系统工作流程
系统的工作流程如图2.2所示。首先,系统初始化,包括STM32单片机的初始化、各传感器模块的初始化以及OLED液晶显示屏的初始化等。然后,系统进入实时监测状态,不断接收各传感器模块的数据,并进行处理和分析。如果检测到异常情况,如温度异常、烟雾浓度过高、可燃气体泄漏或火焰等,系统将自动启动相应的报警和防护措施,如发送GSM短信报警、启动水泵抽水、启动LED和报警器以及风扇通风等。同时,系统还会将异常情况显示在OLED液晶显示屏上,方便用户查看。如果未检测到异常情况,则系统继续实时监测家居环境的状态。
图2.2 系统工作流程图
第三章 系统硬件设计
3.1 STM32F103C8T6单片机
STM32F103C8T6是一款基于ARM Cortex-M3内核的32位微控制器,具有丰富的外设资源和强大的处理能力。该单片机具有低功耗、高性能、易于编程等特点,非常适合用于智能火灾报警系统的核心控制器。
3.2 OLED液晶显示屏
OLED液晶显示屏具有亮度高、对比度高、色彩鲜艳等特点,非常适合用于显示监测数据。本系统采用了一款0.96英寸的OLED液晶显示屏,能够清晰地显示温度、积水、烟雾、可燃气体以及火焰等参数的值。
3.3 传感器模块
(1)温度传感器模块:本系统采用了一款DS18B20数字温度传感器,具有测量精度高、抗干扰能力强等特点。通过该传感器,系统能够实时监测家居环境中的温度值。
(2)水位传感器模块:本系统采用了一款基于浮球原理的水位传感器,能够准确检测家居环境中的积水情况。当积水超过设定阈值时,传感器将输出高电平信号,触发系统报警。
(3)烟雾传感器模块:本系统采用了一款MQ-2烟雾传感器,能够检测空气中的烟雾浓度。当烟雾浓度超过设定阈值时,传感器将输出高电平信号,触发系统报警。
(4)可燃气体传感器模块:本系统采用了一款MQ-5可燃气体传感器,能够检测空气中的可燃气体浓度。当可燃气体浓度超过设定阈值时,传感器将输出高电平信号,触发系统报警。
(5)火焰传感器模块:本系统采用了一款基于红外原理的火焰传感器,能够检测火焰的存在。当检测到火焰时,传感器将输出高电平信号,触发系统报警。
3.4 执行模块
(1)水泵模块:本系统采用了一款小型直流水泵,能够在检测到积水过多时启动抽水功能,将积水排出家居环境。
(2)LED灯模块:本系统采用了一款高亮LED灯,能够在检测到异常情况时启动报警功能,发出醒目的光信号。
(3)风扇模块:本系统采用了一款小型直流风扇,能够在检测到烟雾、火焰或可燃气体异常时启动通风功能,降低环境中的有害物质浓度。
(4)报警器模块:本系统采用了一款蜂鸣器作为报警器,能够在检测到异常情况时发出响亮的报警声,提醒用户注意安全。
3.5 GSM模块
GSM模块采用了一款SIM900A模块,能够实现短信发送功能。当系统检测到异常情况时,将通过GSM模块将报警信息发送到用户的手机上,实现远程报警功能。
3.6 按键模块
按键模块用于设置系统的相关参数,如温度报警阈值、烟雾报警阈值、可燃气体报警阈值以及火焰报警阈值等。通过按键模块,用户可以方便地调整这些参数,提高系统的灵活性和适用性。
第四章 系统软件设计
4.1 系统初始化
系统初始化包括STM32单片机的初始化、各传感器模块的初始化以及OLED液晶显示屏的初始化等。在STM32单片机的初始化过程中,需要配置时钟系统、GPIO端口、中断系统等。在各传感器模块的初始化过程中,需要配置传感器的通信协议、测量范围等参数。在OLED液晶显示屏的初始化过程中,需要配置显示屏的分辨率、对比度等参数。
4.2 数据采集与处理
系统通过各传感器模块实时采集家居环境中的温度、积水、烟雾、可燃气体以及火焰等参数的值。采集到的数据将被送到STM32单片机进行处理和分析。单片机将判断这些数据是否超过设定的报警阈值,如果超过,则触发相应的报警和防护措施。
4.3 报警与防护
当系统检测到异常情况时,将自动启动相应的报警和防护措施。具体实现方式如下:
(1)温度异常报警:当温度超过设定的报警阈值时,系统将启动LED和报警器进行报警,并通过GSM模块发送短信到用户手机上。
(2)积水报警与抽水:当检测到积水过多时,系统将启动水泵进行抽水,并通过GSM模块发送短信到用户手机上进行报警。
(3)烟雾、火焰、可燃气异常报警与通风:当检测到烟雾、火焰或可燃气体浓度超过设定的报警阈值时,系统将启动LED和报警器进行报警,同时启动风扇进行通风,以降低环境中的有害物质浓度,并通过GSM模块发送短信到用户手机上进行报警。
4.4 数据显示与按键设置
系统通过OLED液晶显示屏实时显示家居环境中的温度、积水、烟雾、可燃气体以及火焰等参数的值,方便用户随时查看家居环境的状态。同时,系统还提供了按键设置功能,允许用户通过按键模块设置相关参数,如温度报警阈值、烟雾报警阈值、可燃气体报警阈值以及火焰报警阈值等,以提高系统的灵活性和适用性。
4.5 软件流程图
系统的软件流程图如图4.1所示。首先,系统进行初始化,包括STM32单片机的初始化、各传感器模块的初始化、OLED液晶显示屏的初始化以及GSM模块的初始化等。然后,系统进入主循环,不断采集各传感器模块的数据,并进行处理和分析。如果检测到异常情况,系统将根据异常类型启动相应的报警和防护措施,如发送GSM短信报警、启动水泵抽水、启动LED和报警器以及风扇通风等。同时,系统还会将异常情况显示在OLED液晶显示屏上。如果未检测到异常情况,则系统继续采集数据并进行分析。在软件流程中,还包含了按键中断处理部分,用于响应用户的按键操作,实现参数设置功能。
图4.1 系统软件流程图
第五章 系统测试与验证
5.1 测试环境与方法
为了验证系统的性能和功能,我们进行了系统的测试与验证。测试环境为一个模拟的家居环境,包括温度、积水、烟雾、可燃气体以及火焰等参数的模拟。测试方法包括功能测试、性能测试以及稳定性测试等。
5.2 功能测试
功能测试主要验证系统是否能够实现预期的功能。我们分别测试了系统的温度监测与报警功能、积水监测与抽水功能、烟雾监测与报警及通风功能、可燃气体监测与报警及通风功能以及火焰监测与报警功能。测试结果表明,系统能够准确地监测各参数的值,并在检测到异常情况时及时启动相应的报警和防护措施。
5.3 性能测试
性能测试主要验证系统的响应时间和准确性。我们分别测试了系统在各种异常情况下的响应时间以及测量参数的准确性。测试结果表明,系统的响应时间较短,能够在几秒钟内启动报警和防护措施;同时,系统测量参数的准确性也较高,能够满足实际应用的需求。
5.4 稳定性测试
稳定性测试主要验证系统在不同环境下的运行稳定性和可靠性。我们分别测试了系统在高温、低温、潮湿等环境下的运行情况。测试结果表明,系统在不同环境下均能够稳定运行,且未出现异常情况。
第六章 结论与展望
6.1 结论
本文设计了一种基于STM32单片机的智能火灾报警系统,该系统能够实时监测家居环境中的温度、积水、烟雾、可燃气体以及火焰等参数的值,并在检测到异常情况时及时启动相应的报警和防护措施。通过系统的测试与验证,我们得出以下结论:
(1)系统能够实现预期的功能,包括温度监测与报警、积水监测与抽水、烟雾监测与报警及通风、可燃气体监测与报警及通风以及火焰监测与报警等功能。
(2)系统的响应时间和准确性较高,能够满足实际应用的需求。
(3)系统在不同环境下均能够稳定运行,具有较高的稳定性和可靠性。
6.2 展望
虽然本系统已经实现了基本的火灾报警功能,但在实际应用中仍存在一些不足和需要改进的地方。例如,系统的报警阈值设置较为简单,可以根据用户需求进行更细致的调整;系统的通信方式较为单一,可以考虑增加其他通信方式以提高系统的灵活性和可扩展性;此外,还可以考虑将系统与智能家居系统相结合,实现更加智能化的家庭安全监控和管理。在未来的研究中,我们将继续完善系统的功能和性能,提高系统的实用性和应用价值。
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "rtc.h"
#include "usart.h"
#include "oled.h"
//
//All rights reserved
//
RTC_HandleTypeDef RTC_Handler; //RTC句柄
_calendar_obj calendar;//时钟结构体
//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回0:正常
//其他:错误代码
u8 RTC_Init(void)
{
RTC_Handler.Instance=RTC;
RTC_Handler.Init.AsynchPrediv=32767; //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767
if(HAL_RTC_Init(&RTC_Handler)!=HAL_OK) return 1;
if(HAL_RTCEx_BKUPRead(&RTC_Handler,RTC_BKP_DR1)!=0X5050)//是否第一次配置
{
RTC_Set(2024,2,26,13,48,0); //设置日期和时间,2017年5月27日,17点07分0秒
HAL_RTCEx_BKUPWrite(&RTC_Handler,RTC_BKP_DR1,0X5050);//标记已经初始化过了
printf("FIRST TIME\n");
}
__HAL_RTC_ALARM_ENABLE_IT(&RTC_Handler,RTC_IT_SEC); //允许秒中断
__HAL_RTC_ALARM_ENABLE_IT(&RTC_Handler,RTC_IT_ALRA); //允许闹钟中断
HAL_NVIC_SetPriority(RTC_IRQn,0x01,0x02); //抢占优先级1,子优先级2
HAL_NVIC_EnableIRQ(RTC_IRQn);
RTC_Get();//更新时间
return 0; //ok
}
//RTC底层驱动,时钟配置
//此函数会被HAL_RTC_Init()调用
//hrtc:RTC句柄
void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE(); //使能电源时钟PWR
HAL_PWR_EnableBkUpAccess(); //取消备份区域写保护
__HAL_RCC_BKP_CLK_ENABLE(); //使能BSP时钟
RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSE;//LSE配置
RCC_OscInitStruct.PLL.PLLState=RCC_PLL_NONE;
RCC_OscInitStruct.LSEState=RCC_LSE_ON; //RTC使用LSE
HAL_RCC_OscConfig(&RCC_OscInitStruct);
PeriphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_RTC;//外设为RTC
PeriphClkInitStruct.RTCClockSelection=RCC_RTCCLKSOURCE_LSE;//RTC时钟源为LSE
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
__HAL_RCC_RTC_ENABLE();//RTC时钟使能
}
int val;
//RTC时钟中断
void RTC_IRQHandler(void)
{
if(__HAL_RTC_ALARM_GET_FLAG(&RTC_Handler,RTC_FLAG_SEC)!=RESET) //闹钟中断
{
//__HAL_RTC_ALARM_CLEAR_FLAG(&RTC_Handler,RTC_FLAG_ALRAF); //清除闹钟中断
//printf("%d 年,%d 月,%d 日,%d 时,%d 分,%d 秒\r\n ",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);
RTC_Get(); //更新时间
__HAL_RTC_ALARM_CLEAR_FLAG(&RTC_Handler,RTC_FLAG_SEC); //清除秒中断
//LED=!LED;
//
// OLED_Clear();
// OLED_Refresh();
// if(calendar.sec<5){
// RTC_Alarm_Set(2023,2,20,11,26,15);
// HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
//
// }
// if(calendar.sec>10)
// {
// HAL_PWR_DisableSleepOnExit();
// LED_Init();
// LED=1;
// }
}
if(__HAL_RTC_ALARM_GET_FLAG(&RTC_Handler,RTC_FLAG_ALRAF)!=RESET) //闹钟中断
{
__HAL_RTC_ALARM_CLEAR_FLAG(&RTC_Handler,RTC_FLAG_ALRAF); //清除闹钟中断
RTC_Get(); //更新时间
printf("ALARM A!\r\n");
printf("%d 年,%d 月,%d 日,%d 时,%d 分,%d 秒\r\n ",calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);
// RTC_Alarm_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec+20);
__HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟
__HAL_RTC_ALARM_CLEAR_FLAG(&RTC_Handler,RTC_FLAG_OW); //清除溢出
// OLED_Clear();
// HAL_PWR_EnterSTANDBYMode();
}
}
//判断是否是闰年函数
//月份 1 2 3 4 5 6 7 8 9 10 11 12
//闰年 31 29 31 30 31 30 31 31 30 31 30 31
//非闰年 31 28 31 30 31 30 31 31 30 31 30 31
//year:年份
//返回值:该年份是不是闰年.1,是.0,不是
u8 Is_Leap_Year(u16 year)
{
if(year%4==0) //必须能被4整除
{
if(year%100==0)
{
if(year%400==0)return 1;//如果以00结尾,还要能被400整除
else return 0;
}else return 1;
}else return 0;
}
//设置时钟
//把输入的时钟转换为秒钟
//以1970年1月1日为基准
//1970~2099年为合法年份
//返回值:0,成功;其他:错误代码.
//月份数据表
u8 const table_week[12]={0,3,3,6,1,4,6,2,5,0,3,5}; //月修正数据表
//平年的月份日期表
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
//syear,smon,sday,hour,min,sec:年月日时分秒
//返回值:设置结果。0,成功;1,失败。
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{
u16 t;
u32 seccount=0;
// RTC_DateTypeDef RTC_DateStructure;
// RTC_TimeTypeDef RTC_TimeStructure;
if(syear<1970||syear>2099)return 1;
for(t=1970;t<syear;t++) //把所有年份的秒钟相加
{
if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数
else seccount+=31536000; //平年的秒钟数
}
smon-=1;
for(t=0;t<smon;t++) //把前面月份的秒钟数相加
{
seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数
}
seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加
seccount+=(u32)hour*3600;//小时秒钟数
seccount+=(u32)min*60; //分钟秒钟数
seccount+=sec;//最后的秒钟加上去
// RTC_DateStructure.Year=syear;
// RTC_DateStructure.Month=smon;
// RTC_DateStructure.Date=sday;
// HAL_RTC_SetDate(&RTC_Handler,&RTC_DateStructure,RTC_FORMAT_BIN);
//
// RTC_TimeStructure.Hours=hour;
// RTC_TimeStructure.Minutes=min;
// RTC_TimeStructure.Seconds=sec;
// HAL_RTC_SetTime(&RTC_Handler,&RTC_TimeStructure,RTC_FORMAT_BIN);
//设置时钟
RCC->APB1ENR|=1<<28;//使能电源时钟
RCC->APB1ENR|=1<<27;//使能备份时钟
PWR->CR|=1<<8; //取消备份区写保护
//上面三步是必须的!
RTC->CRL|=1<<4; //允许配置
RTC->CNTL=seccount&0xffff;
RTC->CNTH=seccount>>16;
RTC->CRL&=~(1<<4);//配置更新
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
RTC_Get();//设置完之后更新一下数据
return 0;
}
//初始化闹钟
//以1970年1月1日为基准
//1970~2099年为合法年份
//syear,smon,sday,hour,min,sec:闹钟的年月日时分秒
//返回值:0,成功;其他:错误代码.
u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec)
{
u16 t;
u32 seccount=0;
if(syear<1970||syear>2099)return 1;
for(t=1970;t<syear;t++) //把所有年份的秒钟相加
{
if(Is_Leap_Year(t))seccount+=31622400;//闰年的秒钟数
else seccount+=31536000; //平年的秒钟数
}
smon-=1;
for(t=0;t<smon;t++) //把前面月份的秒钟数相加
{
seccount+=(u32)mon_table[t]*86400;//月份秒钟数相加
if(Is_Leap_Year(syear)&&t==1)seccount+=86400;//闰年2月份增加一天的秒钟数
}
seccount+=(u32)(sday-1)*86400;//把前面日期的秒钟数相加
seccount+=(u32)hour*3600;//小时秒钟数
seccount+=(u32)min*60; //分钟秒钟数
seccount+=sec;//最后的秒钟加上去
//设置时钟
RCC->APB1ENR|=1<<28;//使能电源时钟
RCC->APB1ENR|=1<<27;//使能备份时钟
PWR->CR|=1<<8; //取消备份区写保护
//上面三步是必须的!
RTC->CRL|=1<<4; //允许配置
RTC->ALRL=seccount&0xffff;
RTC->ALRH=seccount>>16;
RTC->CRL&=~(1<<4);//配置更新
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
return 0;
}
//得到当前的时间,结果保存在calendar结构体里面
//返回值:0,成功;其他:错误代码.
u8 RTC_Get(void)
{
static u16 daycnt=0;
u32 timecount=0;
u32 temp=0;
u16 temp1=0;
timecount=RTC->CNTH;//得到计数器中的值(秒钟数)
timecount<<=16;
timecount+=RTC->CNTL;
temp=timecount/86400; //得到天数(秒钟数对应的)
if(daycnt!=temp)//超过一天了
{
daycnt=temp;
temp1=1970; //从1970年开始
while(temp>=365)
{
if(Is_Leap_Year(temp1))//是闰年
{
if(temp>=366)temp-=366;//闰年的秒钟数
else break;
}
else temp-=365; //平年
temp1++;
}
calendar.w_year=temp1;//得到年份
temp1=0;
while(temp>=28)//超过了一个月
{
if(Is_Leap_Year(calendar.w_year)&&temp1==1)//当年是不是闰年/2月份
{
if(temp>=29)temp-=29;//闰年的秒钟数
else break;
}
else
{
if(temp>=mon_table[temp1])temp-=mon_table[temp1];//平年
else break;
}
temp1++;
}
calendar.w_month=temp1+1; //得到月份
calendar.w_date=temp+1; //得到日期
}
temp=timecount%86400; //得到秒钟数
calendar.hour=temp/3600; //小时
calendar.min=(temp%3600)/60; //分钟
calendar.sec=(temp%3600)%60; //秒钟
calendar.week=RTC_Get_Week(calendar.w_year,calendar.w_month,calendar.w_date);//获取星期
return 0;
}
//获得现在是星期几
//功能描述:输入公历日期得到星期(只允许1901-2099年)
//year,month,day:公历年月日
//返回值:星期号
u8 RTC_Get_Week(u16 year,u8 month,u8 day)
{
u16 temp2;
u8 yearH,yearL;
yearH=year/100; yearL=year%100;
// 如果为21世纪,年份数加100
if (yearH>19)yearL+=100;
// 所过闰年数只算1900年之后的
temp2=yearL+yearL/4;
temp2=temp2%7;
temp2=temp2+day+table_week[month-1];
if (yearL%4==0&&month<3)temp2--;
return(temp2%7);
}