文章目录
- 设计要求
- 实物
- 人脸识别模块的调试
- 传感器采集与显示
- 模块设计
- 温湿度模块
- 烟雾浓度MQ2
- GSM模块
- 人脸识别模块
- 语音报警模块
- 资源占用
- 源程序
- 主程序
- 处理逻辑
- AD/DA转换检测烟雾浓度
- GSM-A6模块驱动
- HLK210人脸识别模块驱动
- DHT11模块驱动
- JQ8400语音模块驱动
- 串口驱动
设计要求
本设计研究的是关于基于STM32的家庭防火防盗的系统,该系统以STM32单片机作为采集和控制核心,利用了多种传感器进行信息的采集,如使用温湿度传感器获取环境温湿度来为家庭提供区域环境信息数字化,使用可燃气体传感器来为系统提供可燃气泄漏、烟雾等用于实时监控房屋内部发生火灾的可能性,做到实时报警,采用语音录放模块进行智能化语音提示,使用OLED屏幕进行信息可视化如温湿度、烟雾浓度、室内人员状态、报警状态的显示功能,使用继电器作为家庭电源开关,总到报警自动关闭的功能,使用风扇进行抽风,放出出现可燃气体浓度过高大致家庭起火的安全隐患,使用嵌入式硬件实现机器视觉进行人脸检测的功能,防止陌生人闯入。使用GSM模块与家庭主人进行实时通信,以便家庭主人能够实时获取到家庭内部的安全信息状态。本系统的设计功能和参数如下所示。
2.1.1 设计功能
(1)实时检测室内可燃气体和烟雾浓度,做到实时监测和触发预警(阈值可自定义设置)。
(2)实时采集室内温湿度,湿度并在OLED屏上显示。
(3)系统触发烟雾预警后会自动打开窗口开启风扇进行抽风,同时切断室内电器电源。
(4)系统可以设置人脸识别(通过宽动态人脸识别摄像头模组,实现活体检测,人脸检测功能),可设定识别数量不少于10位。当识别三次都未成功时判定为未知人员闯入,触发系统预警。
(5)系统触发报警后能够通过短信通知用户预警内容。
2.2.2 设计参数
(1)温度:0℃ ~ +50℃ (可设阈值),精度:±2℃;湿度:20-90%RH,精度:±5%RH
(2)烟雾浓度:10-5000PPM ,精度:±20ppm
(3)设备自检周期:180天
(4)脸部轮廓参数:68或128个特征点
(5)识别成功率:98%以上,识别速度:1S以内
2.2 系统整体框架
本设计以STM32单片机作为系统控制核心,完成对外来人员的人脸检测,采用LCD液晶屏对采集到的人脸数据进行可视化显示,采用OLED屏对采集到的温湿度、烟雾浓度,以及可能需要的人脸信息验证等,尽量做到系统信息显示直观,方便用户能够简洁获取到当前系统运行状态和需要了解的数据信息。故本系统由温湿度检测模块,烟雾传感器MQ2,人脸识别模块K210,独立按键采集模块进行数据的采集,由STM32单片机对采集的数据进行处理,使用LCD和OLED将数据进行分块显示,利用LED和蜂鸣器进行声光报警,使用SIM模块利用短信将报警信息发送到用户手机。本系统的整体框架如图2.1所示。
实物
本系统调试硬件方面主要做的工作为人脸识别模块调试、传感器数据的采集、显示以及报警状态。人脸识别模块相对来说比较复杂,因为该模块数据协议多,故而要具体了解模块的整个工作的通信流程,传感器数据的采集与显示与报警则是本系统的核心,能够正常的采集数据并且在屏幕上可视化显示出来是最主要的实物调试并根据预设进行声光报警。
人脸识别模块的调试
人脸识别模块根据数据手册和本系统对模块的使用需求分为人脸采集(录入)、人脸识别、人脸删除三大功能,根据第四章软件调试内容将这三大过程制作如图5.2所示的流程。
图5.2 人脸识别模块调试
相对应的人脸识别模块的三个实物调试结果如图5.3所示,可以看到模块和单片机能够正常通讯并按照第四章所介绍的人脸识别流程正常工作,模块各个状态的均可在实物中正常工作,在识别成功时OLED屏幕能够正常显示主人,识别到非录入人员是显示非法入侵者,在设定界面能够进行人脸的录入和删除。
传感器采集与显示
如下图所示为本系统的实物图调试时的大致框架,从中可以看到实物需要显示多个界面,用于信息采集、显示、阈值设定等。可以看出预设计界面和通过实物调试出的界面大致相当,中间根据需求做了些许显示改动,但大体一致的。
模块设计
温湿度模块
本系统采用的是DHT11温湿度传感器,通过此温湿度传感器采集家庭环境中的温湿度的数值,因不同的环境温湿度具体数据是不一样的,比如家庭内部和家庭外部的温湿度就有很大不同,故而采用温湿度能够为家庭用户带来更加精准的数字化环境情况参考。
烟雾浓度MQ2
本系统为了检测家庭内部的烟雾、可燃物浓度而使用了MQ2传感器,通过该传感器输出模拟量送入单片机的模拟输入IO口,通过单片机内部内置的12位高精度模数转换器将输入电压转换为数字量,通过非线性运算获得对应的浓度值。MQ2烟雾浓度传感器是金属氧化物二氧化锡为主的N型半导体而制成的气敏性半导体元器件,该金属氧化物半导体元器件具有较低的电导率,能够检测空气冲存在的烟雾等气敏性气体。模块的浓度探测范围光,灵敏度高,驱动电路相对简单,且模块稳定性非常高,对于检测气体响应非常灵敏快速。本系统单片机的IO口最能容忍3.6V的模拟电压输入,但是无法满足烟雾传感器模块的直接输入,因该模块的模拟输出量最高是5V故而如果使用MQ2传感器输出直接连单片机引脚会造成芯片承受不可逆的损害,故而本次为了满足设计要求需要对MQ2的输出做分压处理,将模拟输出电压5V能够降到单片机可容忍的范围,本次采用了简单的电阻分压设计,即采用两个电阻阻值为3:2的电阻串接到输出引脚作为分压处理单元,经过分压后输入到单片机模拟输入引脚PA1的电压最大为3V,用此方法就能满足模拟设计输入需求。
GSM模块
本次使用的是GSMA6-B模块,该模块体积小巧,相比传统的SIM800A等GSM模块来说体积缩小了一倍有余,且该模块供电要求有所降低,传统的SIM800A无线通信模块一般要求电源电压为6V2A以上,而该模块仅需要5V1A即可完成正常的电源供电需求。该模块支持发送SMS短信、语音通话、GPRS传输等基本的通信功能,模块标准的AT指令,默认使用的是115200bps的波特率与单片机进行通信,采用串口方式连接到单片机的串口3即PB10和PB11引脚。使用GSMA6模块需要注意的是模块串口电平是3.3V的不能和5V单片机串口直接连接,通过USB串口模块进行调试时也需要用支持3.3V串口电平的USB调试模块才行,否则模块通信可能会出现问题。
人脸识别模块
本系统采用了基于K210模块的DEMO板用于人脸识别,K210是一个集成RISC-V双核64位CPU的模块,该模块拥有最高1TOPS算力且功耗仅为0.3W,该模块内置了AI人脸识别算法和模型库,使用串口进行人脸识别信息的输出,模块支持波特率可调最低为9600bps最高可达115200bps,模块的时钟频率为600MHZ,继承了一个8MB的闪存SRAM,该模块支持DVP输出,最高输出为60帧。K210模块内置的AI人脸识别算法经过了大量的训练和验证,识别结果成熟可靠,官方说明该AI人脸识别模型的识别率已经大于99.9%,且支持活体检测,因此能够有效防止使用图片蒙混检测系统的问题。K210模块内置了500-8000个人脸特征库,使用了彩色的双目镜头用于人脸采集,使用了两个红外补光灯能够在夜间依然保持有效、高准确、高反应的检测结果。K210模块与本系统主控单片机的串口1即PA9和PA10接口相连接进行信息的通信传输。由于K210的DEMO板设计不合理,导致DEMO板载引脚接口无法使用,本次通过飞线将K210模块的串口引脚和GND引脚引出。
语音报警模块
本系统使用的语音播放模块为JQ8400F,该模块支持MP3、WAV格式的音频硬解码,支持FAT文件系统因此可以像U盘一样直接通过USB口连接电脑进行音频文件的管理如导入导出。模块支持多种控制模式如单线串口模式和异步串口通信模式以及并行IO控制模式,模块支持音量大小调节,将音量分为1-30的等级进行音量调整。
资源占用
源程序
主程序
/*******************************************************************************\* 文件名称:基于STM32单片机的家庭防火防盗系统的设计\* 实验目的:1.\* 2.\* 程序说明:完整程序Q:277 227 2579;@: itworkstation@ hotmail.com\* 日期版本:本项目分享关键细节,熟悉使用单片机的可做参考代码。完整讲解+源代码工程可联系获取,可定制。*******************************************************************************/
#ifndef __main_h
#define __main_h#include "stm32f10x.h"
#include<string.h>
#include<stdio.h>
#include "Def_config.h"
#include "GPIOLIKE51.h"#include "delay.h"
#include "led.h"#include "bsp_i2c_gpio.h"
#include "bsp_i2c_OLED.h"#include "proc.h"#endif
/******************************************************************************* *******************************************************************************//* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "beep.h"
#include "RELAY.h"
#include "dht11.h"
#include "bsp_adc.h"
#include "usart1.h"
#include "usart2.h"
#include "usart3.h"
#include "HLK210.h"
#include "JQ_8400.h"
#include "bsp_timer4.h"
#include "key.h"
#include "gsmA6.h"/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
STRUCT_NVICPriority NVICPriority_Structure;u8 state01[2][12]={
"OFF",
"ON"
};
u8 PersonNum01[3][15]={
" unmanned",
"Illegal person",
" master",
};
/*** @说明 主函数* @参数 None * @返回值 None*/
int main(void)
{int GSMA6_ret = 0;NVICPriority_Structure.Usart1 = 2;NVICPriority_Structure.Usart2 = 3;NVICPriority_Structure.Usart3 = 1;NVICPriority_Structure.Tim4 = 4;Proc_ParamInit();LED_Init();BEEP_Init();RELAY_Init();OLED_Init();LCD_Display();USART2_Init();JQ8400_Init();JQ8400_6x00SendCmd(SELECTE_PLAY,1); //选择指定曲目播放 if(DHT11_Init() == 0){OLED_Showx8_y16(0,3,(unsigned char*)" 温湿度模块正常 "); //测试8*16字符 }else{ OLED_Showx8_y16(0,3,(unsigned char*)" 温湿度模块异常 "); //测试8*16字符 JQ8400_6x00SendCmd(SELECTE_PLAY,2); //选择指定曲目播放 }USART3_Init();Delay_ms(2000); if(GSMA6_Init() != 1){OLED_Showx8_y16(0,3,(unsigned char*)" GSMA6模块异常 "); //测试8*16字符 JQ8400_6x00SendCmd(SELECTE_PLAY,3); //选择指定曲目播放 }else{OLED_Showx8_y16(0,3,(unsigned char*)" GSMA6模块正常 "); //测试8*16字符 }Delay_ms(2000); LCD_Menu = LCD_SHOWMESSAGE; //正常界面LCD_Display();ADC1_Init();USART1_Init();HLK210_CheckFaceID();Key_Init();TIM4_Init();JQ8400_6x00SendCmd(SELECTE_PLAY,4); //选择指定曲目播放 while(1){ Proc_Warning();Proc_Key();Proc_DHT11();Proc_MQ2(); Proc_CVHK210(); if(TIM4_FlagStatus.Flag_1000MS == TRUE){TIM4_FlagStatus.Flag_1000MS = FALSE;LED_Control(1,REVERSE);if(HLK210_Data.NowMode == CHECKFACEID){HLK210_Data.TimeCount ++;if(HLK210_Data.isGetData == FALSE && HLK210_Data.TimeCount>2){LCD_Show.personNum = 0;LCD_Display();HLK210_Data.TimeCount = 0;// HLK210_Data.IllegalPersonWarn=FALSE;
// HLK210_Data.IllegalPersonTime=0;}if(LCD_Show.personNum == 1 && LCD_Show.warningState==1){JQ8400_6x00SendCmd(SELECTE_PLAY,5); //选择指定曲目播放HLK210_Data.IllegalPersonTime++;if(HLK210_Data.IllegalPersonTime>2){HLK210_Data.IllegalPersonTime=3;if(HLK210_Data.IllegalPersonWarn==FALSE){HLK210_Data.IllegalPersonWarn = TRUE; GSMA6_text_message((char *)GSMA6_Data.Send_PhoneNum,(char *)"There is a stranger breaking in, please pay attention!");} }}} LCD_Display();}GSMA6_ret = GSMA6_ReadMessageTest();if(GSMA6_ret == TEXT_CMD_CHECK) //查看{memset(GSMA6_Data.TestMessage, 0, GSMA6_TextLEN);sprintf(GSMA6_Data.TestMessage,"T:%d,H:%d,MQ2:%d,FaceNum:%s,WaringState:%s;CMD:check,WarnOn,WarnOff,RelayOn,RelayOff",LCD_Show.tempe,LCD_Show.humi,LCD_Show.Mq2,PersonNum01[LCD_Show.personNum],state01[LCD_Show.warningState]);GSMA6_text_message((char *)GSMA6_Data.Send_PhoneNum,(char *)GSMA6_Data.TestMessage);}else if(GSMA6_ret == TEXT_CMD_WaringOn) //部署监测报警{LCD_Show.warningState = 1;GSMA6_text_message((char *)GSMA6_Data.Send_PhoneNum,(char *)"Alarm mode turn on!");}else if(GSMA6_ret == TEXT_CMD_WaringOff) //解除监测报警{LCD_Show.warningState = 0;GSMA6_text_message((char *)GSMA6_Data.Send_PhoneNum,(char *)"Alarm mode cancelled!");}else if(GSMA6_ret == TEXT_CMD_RelayOn) {LCD_Show.is_relayHandOpen = TRUE;GSMA6_text_message((char *)GSMA6_Data.Send_PhoneNum,(char *)"Home power on!");}else if(GSMA6_ret == TEXT_CMD_RelayOff) {LCD_Show.is_relayHandOpen = FALSE;GSMA6_text_message((char *)GSMA6_Data.Send_PhoneNum,(char *)"Home power off!");}else{}}
}
处理逻辑
#ifndef __proc_h
#define __proc_h#include "main.h"#define LCD_BUFFMAX 21typedef enum
{LCD_DEFAULT,LCD_SHOWMESSAGE,LCD_SETTH,LCD_SETRH,LCD_SETPH,LCD_SETCV,LCD_SETCV02,LCD_MENUEND,LCD_SETCVMESSAGE,LCD_SETCV02MESSAGE,LCD_SETCV02MESSAGEOK,LCD_GSMSHOWMESSAGE,
// LCD_MENUEND
}LCD_ENUM;
typedef struct {u8 tempe;u8 humi;u16 Mq2;u8 personNum;u8 warningState;u8 setTH;u8 setRH;u16 setMq2H;u8 setHostPersonNum;u8 setGuestPersonNum;ENUM_JUDGE is_relayHandOpen;ENUM_JUDGE is_HK210StorgeFaceSuccess;ENUM_JUDGE is_DHT11_TempeWarn;ENUM_JUDGE is_DHT11_HumiWarn;ENUM_JUDGE is_Mq2_Warn;u8 StorgeFaceId;float test;
}LCD_SHOW_MENU;
extern LCD_SHOW_MENU LCD_Show;
extern LCD_ENUM LCD_Menu;
extern char LCD_Buff[LCD_BUFFMAX];void Proc_ParamInit(void);
void Proc_Warning(void);void LCD_Display(void);void Proc_DHT11(void);
void Proc_MQ2(void);
void Proc_CVHK210(void);void Proc_Key(void);#endif
#include "proc.h"
#include "dht11.h"
#include "bsp_adc.h"
#include "RELAY.h"
#include "HLK210.h"
#include "key.h"
#include "bsp_timer4.h"
#include "gsmA6.h"
#include "BEEP.h"
#include "JQ_8400.h" void Proc_ParamInit(void)
{LCD_Show.setGuestPersonNum = 0;LCD_Show.setHostPersonNum = 0;LCD_Show.setMq2H = 1000; LCD_Show.setRH = 60;LCD_Show.setTH = 30;LCD_Show.warningState = 1; //报警模式 , LCD_Show.is_relayHandOpen = FALSE;LCD_Show.is_HK210StorgeFaceSuccess = FALSE;LCD_Show.is_DHT11_HumiWarn = FALSE;LCD_Show.is_DHT11_TempeWarn = FALSE;LCD_Show.is_Mq2_Warn = FALSE;
}
char is_SendWaring = 0;
void Proc_Warning(void)
{if(LCD_Show.warningState == 1) //报警模式{if(LCD_Show.is_DHT11_TempeWarn || LCD_Show.is_DHT11_HumiWarn || LCD_Show.is_Mq2_Warn){if(is_SendWaring==0){is_SendWaring=1;GSMA6_text_message((char *)GSMA6_Data.Send_PhoneNum,(char *)"Abnormal sensor data is detected, please handle it in time!");}BEEP_Control(ON);LED_Control(2,ON);}else{is_SendWaring=0;BEEP_Control(OFF);LED_Control(2,OFF);}if(LCD_Show.is_Mq2_Warn || LCD_Show.is_relayHandOpen){RELAY_Control(ON);}else{RELAY_Control(OFF);}if(LCD_Show.personNum == 1){}else{HLK210_Data.IllegalPersonWarn=FALSE; HLK210_Data.IllegalPersonTime=0;}}else{ //非报警模式if(LCD_Show.is_relayHandOpen){RELAY_Control(ON);}else{RELAY_Control(OFF);}LED_Control(2,OFF);BEEP_Control(OFF);is_SendWaring=0;HLK210_Data.IllegalPersonWarn=FALSE; HLK210_Data.IllegalPersonTime=0;}
}
char is_TH_YuYin=0,RH_YuYin=0,is_YanWu_YuYin=0;
void Proc_DHT11(void)
{if(DHT11_Read_Data() != 0){LCD_Show.humi = (u8)DHT11_Structure.Humi;LCD_Show.tempe = (u8)DHT11_Structure.Tempe;if(LCD_Show.tempe > LCD_Show.setTH){LCD_Show.is_DHT11_TempeWarn = TRUE;if(is_TH_YuYin==0){is_TH_YuYin=1;JQ8400_6x00SendCmd(SELECTE_PLAY,6); //选择指定曲目播放 }}else{LCD_Show.is_DHT11_TempeWarn = FALSE;is_TH_YuYin=0;}if(LCD_Show.humi > LCD_Show.setRH){LCD_Show.is_DHT11_HumiWarn = TRUE;if(RH_YuYin==0){RH_YuYin=1;JQ8400_6x00SendCmd(SELECTE_PLAY,7); //选择指定曲目播放 }}else{LCD_Show.is_DHT11_HumiWarn = FALSE;RH_YuYin=0;}}
}
void Proc_MQ2(void)
{
// LCD_Show.test= (float)(ADCConvertedValue[0] * 3.3 / 4096); //130 - 3100 1-5000ppmLCD_Show.test= ADCConvertedValue[0]; //130 - 3100 1-5000ppmif(LCD_Show.test<250){LCD_Show.test = 251;}LCD_Show.Mq2 = (u16)((LCD_Show.test - 250)*1.67);if(LCD_Show.Mq2 > LCD_Show.setMq2H){LCD_Show.is_Mq2_Warn = TRUE;if(is_YanWu_YuYin==0){is_YanWu_YuYin=1;JQ8400_6x00SendCmd(SELECTE_PLAY,8); //选择指定曲目播放 }}else{LCD_Show.is_Mq2_Warn = FALSE;is_YanWu_YuYin=0;}
}
void Proc_CVHK210(void)
{if(HLK210_Data.isGetData == TRUE && HLK210_Data.NowMode == CHECKFACEID){HLK210_Data.isGetData = FALSE;HLK210_Data.TimeCount = 0;
// for(i=0;i<HLK210_Data.CmdDataLen;i++)
// {
// USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
// }if(HLK210_Data.HLK210_Buffer[6]==0x02 && HLK210_Data.HLK210_Buffer[7]==0x0D && HLK210_Data.HLK210_Buffer[19]==0X00) {LCD_Show.personNum = 2;}if(HLK210_Data.HLK210_Buffer[6]==0x02 && HLK210_Data.HLK210_Buffer[7]==0x0D && HLK210_Data.HLK210_Buffer[19]!=0X00) {LCD_Show.personNum = 1;}LCD_Display();}
}void Proc_Key2Add(u8 menuNow);
void Proc_Key3Dec(u8 menuNow);
void Proc_Key(void)
{u8 keyValue = 0xff;keyValue = Key_Scan();if(keyValue != 0xff){switch(keyValue){case 1:LCD_Menu++;if(LCD_Menu >= LCD_MENUEND){LCD_Menu = LCD_SHOWMESSAGE; } break;case 2:Proc_Key2Add(LCD_Menu);break;case 3:Proc_Key3Dec(LCD_Menu);break;default:break;}LCD_Display();}
}
void Proc_Key2Add(u8 menuNow)
{switch(menuNow){case LCD_SHOWMESSAGE:if(LCD_Show.is_relayHandOpen == TRUE){ LCD_Show.is_relayHandOpen=FALSE;JQ8400_6x00SendCmd(SELECTE_PLAY,12); //选择指定曲目播放 } else{LCD_Show.is_relayHandOpen=TRUE;JQ8400_6x00SendCmd(SELECTE_PLAY,11); //选择指定曲目播放 } break;case LCD_SETTH:LCD_Show.setTH ++;if(LCD_Show.setTH>99)LCD_Show.setTH=99;break;case LCD_SETRH:LCD_Show.setRH ++;if(LCD_Show.setRH>99)LCD_Show.setRH=99;break;case LCD_SETPH:LCD_Show.setMq2H +=50;if(LCD_Show.setMq2H>5000)LCD_Show.setMq2H=5000;break;case LCD_SETCV:LCD_Show.is_HK210StorgeFaceSuccess = FALSE;LCD_Menu = LCD_SETCVMESSAGE; LCD_Display(); HLK210_InputFaceID();while(LCD_Menu == LCD_SETCVMESSAGE){if(HLK210_Data.isGetData){HLK210_Data.isGetData = FALSE;if(HLK210_Data.HLK210_Buffer[18]!=0x00) //未识别成功{}else{LCD_Show.StorgeFaceId = HLK210_Data.HLK210_Buffer[17]; //获得人脸IDLCD_Show.is_HK210StorgeFaceSuccess = TRUE;LCD_Display(); Delay_ms(3000); //延时显示信息后结束提示。 LCD_Show.is_HK210StorgeFaceSuccess = FALSE;HLK210_CheckFaceID();LCD_Menu = LCD_SETCV;LCD_Display(); }} } break;case LCD_SETCV02:LCD_Menu = LCD_SETCV02MESSAGE;LCD_Display(); break;case LCD_SETCV02MESSAGE: while(LCD_Menu == LCD_SETCV02MESSAGE){HLK210_DeleteAllFaceID();if(HLK210_Data.isGetData){HLK210_Data.isGetData = FALSE;if(HLK210_Data.HLK210_Buffer[15]!=0x00) //未删除成功{Delay_ms(2000); }else{LCD_Menu = LCD_SETCV02MESSAGEOK;LCD_Display(); Delay_ms(3000); //延时显示信息后结束提示。 HLK210_CheckFaceID();LCD_Menu = LCD_SETCV;LCD_Display(); }} } break;default:break;}
}
void Proc_Key3Dec(u8 menuNow)
{switch(menuNow){case LCD_SHOWMESSAGE:if(LCD_Show.warningState!=0){LCD_Show.warningState = 0; JQ8400_6x00SendCmd(SELECTE_PLAY,10); //选择指定曲目播放 }else{LCD_Show.warningState = 1;JQ8400_6x00SendCmd(SELECTE_PLAY,9); //选择指定曲目播放 }break;case LCD_SETTH:LCD_Show.setTH--;if(LCD_Show.setTH<1)LCD_Show.setTH=1;break;case LCD_SETRH:LCD_Show.setRH--;if(LCD_Show.setRH<1)LCD_Show.setRH=1;break;case LCD_SETPH:LCD_Show.setMq2H-=50;if(LCD_Show.setMq2H<50)LCD_Show.setMq2H=50;break;case LCD_SETCV:LCD_Menu = LCD_SETCV02;LCD_Display();break;case LCD_SETCV02:LCD_Menu = LCD_SETCV;LCD_Display();break;case LCD_SETCV02MESSAGE:LCD_Menu = LCD_SETCV02;LCD_Display();break;case LCD_GSMSHOWMESSAGE:GSMA6_text_message((char *)GSMA6_Data.Send_PhoneNum,(char *)"Alarm mode cancelled!");break;default:break;}
}LCD_ENUM LCD_Menu = LCD_DEFAULT,LCD_Menu_Last = LCD_MENUEND;
LCD_SHOW_MENU LCD_Show;
char LCD_Buff[LCD_BUFFMAX];
u8 state[2][12]={
"关闭",
"开启"
};
u8 PersonNum[3][15]={
" 无人",
"非法者",
" 主人",
};
void LCD_Display(void)
{if(LCD_Menu_Last != LCD_Menu){LCD_Menu_Last = LCD_Menu;OLED_CLS();//清屏} if(LCD_Menu == LCD_DEFAULT) {memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"欢迎使用家庭防火");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)" 防盗报警系统 ");OLED_Showx8_y16(0,1,(unsigned char*)LCD_Buff); memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"制作人: ** ");OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符}else if(LCD_Menu == LCD_SHOWMESSAGE){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"温度%d℃ 湿度%d%%",LCD_Show.tempe,LCD_Show.humi);OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"可燃气体:%4dPPM",LCD_Show.Mq2);OLED_Showx8_y16(0,1,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"人脸识别: %s",PersonNum[LCD_Show.personNum]);OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"报警状态: %s",state[LCD_Show.warningState]);OLED_Showx8_y16(0,3,(unsigned char*)LCD_Buff); }else if(LCD_Menu == LCD_SETTH){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)" 设定温度阈值 ");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"TH: %2d℃ ",LCD_Show.setTH);OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符}else if(LCD_Menu == LCD_SETRH){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)" 设定湿度阈值 ");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"RH: %2d%% ",LCD_Show.setRH);OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符}else if(LCD_Menu == LCD_SETPH){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"设定可燃气体阈值");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"PH: %3dPPM ",LCD_Show.setMq2H);OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符}else if(LCD_Menu == LCD_SETCV){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"设定人脸识别数据");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)" → 录入人脸 ");OLED_Showx8_y16(0,1,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)" 删除人脸 ");OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"设置 确定 切换");OLED_Showx8_y16(0,3,(unsigned char*)LCD_Buff); //测试8*16字符}else if(LCD_Menu == LCD_SETCV02){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"设定人脸识别数据");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)" 录入人脸 ");OLED_Showx8_y16(0,1,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)" → 删除人脸 ");OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"设置 确定 切换");OLED_Showx8_y16(0,3,(unsigned char*)LCD_Buff); //测试8*16字符}else if(LCD_Menu == LCD_SETCVMESSAGE){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"请正对摄像头");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"正在识别... ");OLED_Showx8_y16(0,1,(unsigned char*)LCD_Buff); //测试8*16字符if(LCD_Show.is_HK210StorgeFaceSuccess){memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"识别成功,ID为:%2d",LCD_Show.StorgeFaceId);OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"人脸信息已存储 ");OLED_Showx8_y16(0,3,(unsigned char*)LCD_Buff); //测试8*16字符} }else if(LCD_Menu == LCD_SETCV02MESSAGE){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"设定人脸识别数据");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"选择清空人脸信息");OLED_Showx8_y16(0,1,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)" 确定选择? ");OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"设置 确定 返回");OLED_Showx8_y16(0,3,(unsigned char*)LCD_Buff); //测试8*16字符}else if(LCD_Menu == LCD_SETCV02MESSAGEOK){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"设定人脸识别数据");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"人脸信息已清空");OLED_Showx8_y16(0,1,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)" 请重新录入 ");OLED_Showx8_y16(0,3,(unsigned char*)LCD_Buff); //测试8*16字符}else if(LCD_Menu == LCD_GSMSHOWMESSAGE){memset(LCD_Buff,'0',LCD_BUFFMAX); sprintf(LCD_Buff,(char *)"GSMA6 - B Test");OLED_Showx8_y16(0,0,(unsigned char*)LCD_Buff); //测试8*16字符 memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"P:%s ",GSMA6_Data.Rec_PhoneNum);OLED_Showx8_y16(0,1,(unsigned char*)LCD_Buff); //测试8*16字符memset(LCD_Buff,'0',LCD_BUFFMAX);sprintf(LCD_Buff,(char *)"M:%s ",GSMA6_Data.TestMessage);OLED_Showx8_y16(0,3,(unsigned char*)LCD_Buff); //测试8*16字符}else{}
}
AD/DA转换检测烟雾浓度
#ifndef __bsp_adc_h
#define __bsp_adc_h#include "stm32f10x.h"#define ADC_BUFFMAX 1
#define ADC1_DR_Address ((uint32_t)0x4001244C)
extern __IO uint16_t ADCConvertedValue[ADC_BUFFMAX];void ADC1_Init(void);#endif
#include "bsp_adc.h"
// 可燃气体MQ5 PA1 - ADC12_IN1
__IO uint16_t ADCConvertedValue[ADC_BUFFMAX];
static void ADC1_RCC_Configuration(void)
{RCC_ADCCLKConfig(RCC_PCLK2_Div4); /* Enable peripheral clocks ------------------------------------------------*//* Enable DMA1 clock */RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/* Enable ADC1 and GPIOA clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
}
static void ADC1_GPIO_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStructure;/* Configure PA.00 (ADC Channel) as analog input -------------------------*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOA, &GPIO_InitStructure);
}
static void ADC1_Configuration(void)
{ADC_InitTypeDef ADC_InitStructure;DMA_InitTypeDef DMA_InitStructure;/* DMA1 channel1 configuration ----------------------------------------------*/DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCConvertedValue;DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_BufferSize = ADC_BUFFMAX; //1DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; // Disable
// DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // EnableDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;DMA_InitStructure.DMA_Priority = DMA_Priority_High;DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;DMA_Init(DMA1_Channel1, &DMA_InitStructure);/* Enable DMA1 channel1 */DMA_Cmd(DMA1_Channel1, ENABLE);/* ADC1 configuration ------------------------------------------------------*/ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
// ADC_InitStructure.ADC_ScanConvMode = ENABLE; // 如果一次需要对多个通道进行转换,这位就必须设置为ENABLEADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;ADC_InitStructure.ADC_NbrOfChannel = ADC_BUFFMAX; // -----ADC_Init(ADC1, &ADC_InitStructure);/* ADC1 regular channel1 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5); // /* Enable ADC1 DMA */ADC_DMACmd(ADC1, ENABLE);/* Enable ADC1 */ADC_Cmd(ADC1, ENABLE);/* Enable ADC1 reset calibration register */ ADC_ResetCalibration(ADC1);/* Check the end of ADC1 reset calibration register */while(ADC_GetResetCalibrationStatus(ADC1));/* Start ADC1 calibration */ADC_StartCalibration(ADC1);/* Check the end of ADC1 calibration */while(ADC_GetCalibrationStatus(ADC1));/* Start ADC1 Software Conversion */ ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void ADC1_Init(void)
{ADC1_RCC_Configuration();ADC1_GPIO_Configuration();ADC1_Configuration();
}
GSM-A6模块驱动
#ifndef __GSMA6_H__
#define __GSMA6_H__#include "stm32f10x.h"
#include "Def_config.h"#include "usart3.h"
#define GSMA6_USART_SendData USART3_SendByte
#define GSMA6_USART_SendStr USART3_SendString#define GSMA6_USART_REC_LEN 200
#define GSMA6_REC_PHONENUMLEN 20
#define GSMA6_REC_TextNumLEN 4
#define GSMA6_TextLEN 100
typedef struct
{char Rec_Buff[GSMA6_USART_REC_LEN];char Rec_PhoneNum[GSMA6_REC_PHONENUMLEN];char Rec_TextNum[GSMA6_REC_TextNumLEN];char TestMessage[GSMA6_TextLEN];char Send_PhoneNum[GSMA6_REC_PHONENUMLEN];ENUM_JUDGE isGetData; //是否获取到数据ENUM_JUDGE isParseData; //是否解析完成ENUM_JUDGE isUsefull; //信息是否有效}_GSMA6_Data;
extern _GSMA6_Data GSMA6_Data;#define AT_DELET_SMS_ERROR -1
#define COMMUNITE_ERROR 11
#define NO_SIM_CARD_ERROR 22
#define SIM_CARD_NO_REG_ERROR 33
#define CALL_ERROR 44
#define AT_CPMS_ERROR 55
#define AT_CMGF_ERROR 66
#define AT_CSCS_ERROR 77
#define AT_CMGS_ERROR 88
#define END_char_ERROR 99
#define NO_SMS_LEN_ERROR 100
#define AT_CSMP_ERROR 111
#define AT_CNMI_ERROR 101/************* 本地常量声明 **************/
#define TEXT_CMD_READ_ERROR 0
#define TEXT_CMD_READ_NOSM 1#define TEXT_CMD_SMCHECKError 2
#define TEXT_CMD_NOTCMD 3#define TEXT_CMD_CHECK 4 //查看指令
#define TEXT_CMD_WaringOn 5 //部署监测报警指令
#define TEXT_CMD_WaringOff 6 //解除监测报警指令
#define TEXT_CMD_RelayOn 7
#define TEXT_CMD_RelayOff 8/************* 本地变量声明 **************/
//串口发送回车换行
/*注:指令是以\r结束(十六进制就是0X0D)的,以前是以\r\n(0X0D,0X0A)结束的,
串口助手上就是勾上发送回车换行,程序上就是发送0X0D,
但是现在发送串口助手调试勾上,大部分指令是没有问题的,
但是发送短信或者TCP数据的时候,勾上的时候,就会多发送一个回车也就是\n,
发送PDU短信的时候勾上就会发送视频。*/
//#define GSMA6_UART_SendLR() USART_SendData(USART3,0X0D);USART_SendData(USART3,0X0A)
#define GSMA6_UART_SendLR() GSMA6_USART_SendData(0x0D)/************* 本地函数声明 **************/
int GSMA6_text_message(char *phoneNum,char *content);
void GSMA6_Receive_Byte(char res);
int GSMA6_ReadMessageTest(void);
int GSMA6_Find(char *a);int GSMA6_Init(void);#endif
#include "gsmA6.h"
#include <stdio.h>
#include <string.h>
#include "delay.h"
//#include "proc.h"
//#include "usart2.h" char GSMA6_RECEICV_BUFFER[GSMA6_USART_REC_LEN];
uint16_t GSMA6_point = 0;
void GSMA6_Receive_Byte(char res)
{/*发现个很严重的问题,这模块回馈信息不知道怎么回事有0x00,就算我清空用的是255,数组接收中依然有0x00,而这个又代表字符串结束符,导致strstr直接使用时strlen判定字符串长度变成了0*/if(res != 0x00){GSMA6_RECEICV_BUFFER[GSMA6_point++] = res;if(GSMA6_point>6){GSMA6_Data.isGetData = TRUE;}if(GSMA6_point>=GSMA6_USART_REC_LEN){GSMA6_point=0;}}
}
void GSMA6_ClearDate(void)
{uint16_t k=0;for(k=0;k<GSMA6_USART_REC_LEN;k++) //将缓存内容清零{GSMA6_RECEICV_BUFFER[k] = 0;}GSMA6_point=0;
// GSMA6_Data.isGetData = FALSE;
}int GSMA6_Find(char *a)
{ if(strstr(GSMA6_RECEICV_BUFFER,a)!=NULL) {return 1;} else{return 0;}
}/**********************************
发送命令
**********************************/
void GSMA6_Send_Command(char *s)
{GSMA6_ClearDate(); while(*s != '\0')//检测字符串结束符{GSMA6_USART_SendData(*s++);//发送当前字符}GSMA6_UART_SendLR();
// GSMA6_ClearDate();
}
void GSMA6_Send_Command_END(char *s)
{GSMA6_ClearDate(); while(*s != '\0')//检测字符串结束符{GSMA6_USART_SendData(*s++);//发送当前字符}
}
int GSMA6_Send_AT_Command(char *b,char *a,char wait_time,u16 interval_time)
{char i;GSMA6_ClearDate(); // 清除缓存数据i = 0;while(i < wait_time) {GSMA6_Send_Command(b);Delay_ms(interval_time);if(GSMA6_Find(a)) //查找需要应答的字符{return 1;}i++;} return 0;
}
int GSMA6_Send_AT_Command_END(char *b,char *a,char wait_time,u16 interval_time)
{char i;GSMA6_ClearDate(); i = 0;while(i < wait_time) {GSMA6_Send_Command_END(b);Delay_ms(interval_time);if(GSMA6_Find(a)) //查找需要应答的字符{return 1;}i++;} return 0;
}
/***************************************************************
查询状态。
****************************************************************/
int GSMA6_Check_Status(void)
{int ret;ret = GSMA6_Send_AT_Command((char *)"AT",(char *)"OK",3,500);//测试通信是否成功if(ret == 0){return COMMUNITE_ERROR;}ret = GSMA6_Send_AT_Command((char *)"AT+CPIN?",(char *)"READY",2,1000);//查询卡是否插上if(ret == 0){return NO_SIM_CARD_ERROR;}ret = GSMA6_Send_AT_Command((char *)"AT+CREG?",(char *)"+CREG: 1,1",3,1000);//查询卡是否注册到网络if(ret == 0){return SIM_CARD_NO_REG_ERROR;}ret = GSMA6_Send_AT_Command((char *)"AT+CMGD=1,4",(char *)"OK",3,3000);//删除所有短信 新增if(ret == 0){return AT_DELET_SMS_ERROR;}return 1;
}int GSMA6_Config_Format(void)
{int ret;//设置存储位置ret = GSMA6_Send_AT_Command((char *)"AT+CPMS=\"SM\",\"ME\",\"SM\"",(char *)"OK",3,1000);if(ret == 0){return AT_CPMS_ERROR;}ret = GSMA6_Send_AT_Command((char *)"AT+CMGF=1",(char *)"OK",3,1000);//配置为TEXT模式if(ret == 0){return AT_CMGF_ERROR;}ret = GSMA6_Send_AT_Command((char *)"AT+CSCS=\"GSM\"",(char *)"OK",3,1000);//设置字符格式if(ret == 0){return AT_CSCS_ERROR;}ret = GSMA6_Send_AT_Command((char *)"AT+CNMI=2,1",(char *)"OK",3,1000);//设置收到短信提示if(ret == 0){return AT_CNMI_ERROR;}return 1;
}
/***************************************************************
发送短信给对应手机号
****************************************************************/
char AT_Cmd_GMGS[30];
int GSMA6_text_message(char *phoneNum,char *content)
{int ret;char end_char[2]; //信息结束字符串end_char[0] = 0x1A;//结束字符end_char[1] = '\0'; memset(AT_Cmd_GMGS,'\0',30); //先清空,再 对AT_CMGR 赋值 strcpy((char *)AT_Cmd_GMGS,"AT+CMGS=\""); // strcpy从目标地址0 开始拷贝strcat((char *)AT_Cmd_GMGS,(char *)phoneNum); //strcat从目标地址字符串后开始连接strcat((char *)AT_Cmd_GMGS,"\"\r");//设置存储位置ret = GSMA6_Config_Format();if(ret != 1){return ret;}ret = GSMA6_Send_AT_Command(AT_Cmd_GMGS,(char *)">",3,1000);//输入收信人的电话号码 set_phone_numif(ret == 0){return AT_CMGS_ERROR;} GSMA6_USART_SendStr(content); //此函数发送短信内容 不加回车换行ret = GSMA6_Send_AT_Command_END(end_char,(char *)"OK",1,4000);//发送结束符,等待返回ok,等待5S发一次,因为短信成功发送的状态时间比较长if(ret == 0){return END_char_ERROR;} return 1;
}
int GSMA6_ReadMessageTest(void)
{char *subString;char *subStringNext;char AT_CMGR[15];if(GSMA6_Data.isGetData == TRUE){Delay_ms(100);GSMA6_Data.isGetData = FALSE;if(GSMA6_Find("+CMTI")){ memset(GSMA6_Data.Rec_Buff, 0, GSMA6_USART_REC_LEN);memcpy(GSMA6_Data.Rec_Buff, GSMA6_RECEICV_BUFFER, GSMA6_point);
// USART2_SendString(GSMA6_Data.Rec_Buff); if((subString = strstr(GSMA6_Data.Rec_Buff, "SM\",")) != NULL){subString+=4;if ((subStringNext = strstr(subString, "\r")) != NULL){memset(GSMA6_Data.Rec_TextNum, 0, GSMA6_REC_TextNumLEN);memcpy(GSMA6_Data.Rec_TextNum, subString, subStringNext - subString);// memset(LCD_Buff,'0',LCD_BUFFMAX);
// sprintf(LCD_Buff,(char *)"P:%d L:%s ",GSMA6_point,GSMA6_Data.Rec_TextNum);
// OLED_Showx8_y16(0,2,(unsigned char*)LCD_Buff); //测试8*16字符memset(AT_CMGR,'\0',15);strcpy(AT_CMGR,"AT+CMGR=");strcat(AT_CMGR,GSMA6_Data.Rec_TextNum);if(GSMA6_Send_AT_Command((char *)AT_CMGR,(char *)"OK",3,1000)){Delay_ms(100);// USART2_SendString(GSMA6_RECEICV_BUFFER); if((subString = strstr(GSMA6_RECEICV_BUFFER, "+86")) != NULL){subString+=3;if((subStringNext = strstr(subString, "\"")) != NULL){memset(GSMA6_Data.Rec_PhoneNum, 0, GSMA6_REC_PHONENUMLEN);memcpy(GSMA6_Data.Rec_PhoneNum, subString, subStringNext - subString); //获取手机号}}else{GSMA6_ClearDate();return TEXT_CMD_SMCHECKError;}if(GSMA6_Find("check")) //指令{GSMA6_ClearDate();return TEXT_CMD_CHECK;}else if(GSMA6_Find("WarnOn")) //指令{GSMA6_ClearDate();return TEXT_CMD_WaringOn;}else if(GSMA6_Find("WarnOff")) //指令{GSMA6_ClearDate();return TEXT_CMD_WaringOff;}else if(GSMA6_Find("RelayOn")) //指令{GSMA6_ClearDate();return TEXT_CMD_RelayOn;}else if(GSMA6_Find("RelayOff")) //指令{GSMA6_ClearDate();return TEXT_CMD_RelayOff;}else{GSMA6_ClearDate();return TEXT_CMD_NOTCMD;}}else{GSMA6_ClearDate();return TEXT_CMD_SMCHECKError;}}}GSMA6_ClearDate();return TEXT_CMD_READ_NOSM;}else //必须要有{GSMA6_ClearDate();}}return TEXT_CMD_READ_ERROR;
}
_GSMA6_Data GSMA6_Data;
int GSMA6_Init(void)
{int ret = 0;GSMA6_ClearDate();ret = GSMA6_Check_Status();if(ret != 1){return ret;}ret = GSMA6_Config_Format();if(ret != 1){return ret;}GSMA6_ClearDate();GSMA6_Data.isGetData = FALSE;memset(GSMA6_Data.Rec_Buff, 0, GSMA6_REC_PHONENUMLEN);memset(GSMA6_Data.Rec_PhoneNum, 0, GSMA6_REC_PHONENUMLEN);memset(GSMA6_Data.Rec_TextNum, 0, GSMA6_REC_TextNumLEN);memset(GSMA6_Data.TestMessage, 0, GSMA6_TextLEN);memset(GSMA6_Data.Send_PhoneNum, 0, GSMA6_REC_PHONENUMLEN);strcpy(GSMA6_Data.Send_PhoneNum,"15805468097"); //设定指定发送人的手机号return 1;
}
HLK210人脸识别模块驱动
#ifndef __HLK210_h
#define __HLK210_h#include "stm32f10x.h"
#include <string.h>
#include <stdio.h>
#include "Def_config.h"
#include "delay.h"//
#include "usart1.h"
#define HLK210_SendByte USART1_SendByte //模组返回的消息类型说明
#define HLK210_CTROK 0x00 // 操作成功
#define HLK210_CHECKEDFACE 0x01 // 检测到人脸
#define HLK210_LIVINGBODY 0x02 // 活体通过
#define HLK210_STRERROR 0x03 // 存储操作错误
#define HLK210_STRFULL 0x04 // 人脸库已满
#define HLK210_CHECKOUT 0x05 // 检测超时
#define HLK210_IDERROR 0x06 // 人脸编号ID不存在
#define HLK210_FORMERROR 0x07 // 参数或格式错误
#define HLK210_OTHERERROR 0x08 // 其他错误
#define HLK210_RAMERROR 0x09 // RAM中暂缓的模板不存在
#define HLK210_HAVEDFACE 0x0A // 此人脸已注册typedef enum {NORMAL,INPUTFACEID,CHECKFACEID,DELETEFACEID}ENUM_HLK210;#define HLK210_NORMALANSWERLEN 18 //命令发出应答长度
#define HLK210_FACEANSWERLEN 21 //人脸录入时反馈字节长度
#define HLK210_RECOANSWERLEN 22 //人类识别时反馈字节长度#define HLK210_USART_REC_LEN 50
typedef struct SaveData
{char HLK210_Buffer[HLK210_USART_REC_LEN];char CmdDataLen; ENUM_JUDGE isGetData; //是否获取到GPS数据ENUM_JUDGE isParseData; //是否解析完成ENUM_JUDGE isUsefull; //信息是否有效ENUM_HLK210 NowMode;ENUM_JUDGE IllegalPersonWarn;char IllegalPersonTime;char TimeCount;
} _HLK210_Data;
extern _HLK210_Data HLK210_Data;void HLK210_ClearDate(void);
void HLK210_Receive_Byte(u8 res);
void HLK210_InputFaceID(void);
void HLK210_CheckFaceID(void);
void HLK210_DeleteAllFaceID(void);#endif
#include "HLK210.h"#include "bsp_i2c_gpio.h"
#include "bsp_i2c_OLED.h"
#include "delay.h"
//#include "usart3.h" unsigned char HLK210_FaceStorageCmd[18] ={0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE5};//人脸录入指令
unsigned char HLK210_FaceCheckCmd[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x02, 0x0C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xA8}; //人脸识别指令
unsigned char HLK210_AllFaceDeleteCmd[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x0D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x1E}; //人脸清空指令
unsigned char HLK210_LightOn[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xAA, 0x15}; //开补光灯指令unsigned char HLK210_RECEICV_BUFFER[HLK210_USART_REC_LEN];_HLK210_Data HLK210_Data;
u8 HLK210_point=0;
void HLK210_Receive_Byte(u8 res)
{HLK210_RECEICV_BUFFER[HLK210_point++] = res;if(HLK210_point>1 && (HLK210_RECEICV_BUFFER[HLK210_point-2]==0x5a && HLK210_RECEICV_BUFFER[HLK210_point-1]==0x2c)){HLK210_RECEICV_BUFFER[0]=HLK210_RECEICV_BUFFER[HLK210_point-2];HLK210_RECEICV_BUFFER[1]=HLK210_RECEICV_BUFFER[HLK210_point-1];HLK210_point=2;}if(HLK210_point>=HLK210_Data.CmdDataLen){HLK210_Data.isGetData = TRUE;memset(HLK210_Data.HLK210_Buffer, 0, HLK210_USART_REC_LEN); //清空memcpy(HLK210_Data.HLK210_Buffer,HLK210_RECEICV_BUFFER, HLK210_point); //保存数据}if(HLK210_point>HLK210_USART_REC_LEN){HLK210_point=HLK210_USART_REC_LEN-1;}
}
void HLK210_ClearDate(void)
{memset(HLK210_RECEICV_BUFFER, 0, HLK210_USART_REC_LEN); //清空HLK210_point=0;HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;memset(HLK210_Data.HLK210_Buffer, 0, HLK210_USART_REC_LEN); //清空HLK210_Data.isGetData = FALSE;HLK210_Data.isParseData = FALSE;HLK210_Data.isUsefull = FALSE;HLK210_Data.NowMode = NORMAL;HLK210_Data.TimeCount = 0;HLK210_Data.IllegalPersonTime=0;HLK210_Data.IllegalPersonWarn = FALSE;
}void HLK210_Send_Cmd(u8 *cmd)
{u8 i=0;for(i=0;i<18;i++){HLK210_SendByte(*cmd++); // == *(cmd++) 取cmd所指单元的值,cmd指向下一单元,即cmd自加1}
}
void HLK210_InputFaceID(void)
{HLK210_ClearDate();HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;HLK210_Data.NowMode = INPUTFACEID;HLK210_Send_Cmd(HLK210_LightOn); //开补光灯while(HLK210_Data.isGetData == FALSE); //等待接收完应答数据HLK210_Data.isGetData = FALSE;
// for(i=0;i<HLK210_Data.CmdDataLen;i++)
// {
// USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
// }HLK210_Send_Cmd(HLK210_FaceStorageCmd); //存人脸指令while(HLK210_Data.isGetData == FALSE); //等待接收完应答数据HLK210_Data.isGetData = FALSE;
// for(i=0;i<HLK210_Data.CmdDataLen;i++)
// {
// USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
// }HLK210_Data.CmdDataLen = HLK210_FACEANSWERLEN;
// while(HLK210_Data.isGetData == FALSE); //等待接收完应答数据
// HLK210_Data.isGetData = FALSE;
// for(i=0;i<HLK210_Data.CmdDataLen;i++)
// {
// USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
// }
}
void HLK210_CheckFaceID(void)
{HLK210_ClearDate();HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;HLK210_Data.NowMode = CHECKFACEID;HLK210_Send_Cmd(HLK210_LightOn); //开补光灯while(HLK210_Data.isGetData == FALSE); //等待接收完应答数据HLK210_Data.isGetData = FALSE;
// for(i=0;i<HLK210_Data.CmdDataLen;i++)
// {
// USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
// }HLK210_Send_Cmd(HLK210_FaceCheckCmd);while(HLK210_Data.isGetData == FALSE); //等待接收完应答数据HLK210_Data.isGetData = FALSE;
// for(i=0;i<HLK210_Data.CmdDataLen;i++)
// {
// USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
// }HLK210_Data.CmdDataLen = HLK210_RECOANSWERLEN;
}
void HLK210_DeleteAllFaceID(void)
{HLK210_ClearDate();HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;HLK210_Data.NowMode = DELETEFACEID;HLK210_Send_Cmd(HLK210_AllFaceDeleteCmd);while(HLK210_Data.isGetData == FALSE); //等待接收完应答数据
// HLK210_Data.isGetData = FALSE;
// for(i=0;i<HLK210_Data.CmdDataLen;i++)
// {
// USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
// }
}
DHT11模块驱动
#ifndef __DHT11_H
#define __DHT11_H#include "stm32f10x.h"#define GPIO_PORT_DHT11 GPIOB /* GPIO端口 */
#define RCC_DHT11_PORT RCC_APB2Periph_GPIOB /* GPIO端口时钟 */
#define DHT11_DQ_PIN GPIO_Pin_13 /* 连接到DQ数据线的GPIO */typedef struct {uint8_t Humi;uint8_t Tempe;
}STRUCT_DHT11;
extern STRUCT_DHT11 DHT11_Structure;u8 DHT11_Init (void );
unsigned int DHT11_Read_Data(void);#endif
#include "dht11.h"
#include "delay.h"
void mode_input(void )
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = DHT11_DQ_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIO_PORT_DHT11, &GPIO_InitStructure);
}
void mode_output(void )
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = DHT11_DQ_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIO_PORT_DHT11, &GPIO_InitStructure);
}
STRUCT_DHT11 DHT11_Structure;
unsigned int DHT11_Read_Data(void)
{int i;long long val;int timeout;GPIO_ResetBits(GPIO_PORT_DHT11, DHT11_DQ_PIN);Delay_ms(18); //pulldown for 18msGPIO_SetBits(GPIO_PORT_DHT11, DHT11_DQ_PIN);Delay_us(20); //pullup for 30usmode_input();//等待DHT11拉高,80ustimeout = 0;while( (! GPIO_ReadInputDataBit(GPIO_PORT_DHT11, DHT11_DQ_PIN)) && (timeout < 80) ) { timeout++;Delay_us(1); }//wait HIGH//等待DHT11拉低,80ustimeout = 0;while( GPIO_ReadInputDataBit (GPIO_PORT_DHT11, DHT11_DQ_PIN) && (timeout < 80) ) { timeout++;Delay_us(1); } //wait LOW#define CHECK_TIME 28for(i=0;i<40;i++){timeout = 0;while( (! GPIO_ReadInputDataBit(GPIO_PORT_DHT11, DHT11_DQ_PIN)) && (timeout < 80) ) { timeout++;Delay_us(1); }//wait HIGHDelay_us(CHECK_TIME);if ( GPIO_ReadInputDataBit (GPIO_PORT_DHT11, DHT11_DQ_PIN) ){val=(val<<1)+1;} else {val<<=1;}timeout = 0;while( GPIO_ReadInputDataBit (GPIO_PORT_DHT11, DHT11_DQ_PIN) && (timeout < 80) ) { timeout++;Delay_us(1); } //wait LOW}mode_output();GPIO_SetBits(GPIO_PORT_DHT11, DHT11_DQ_PIN);DHT11_Structure.Humi = (u8)(val>>32);DHT11_Structure.Tempe = (u8)(val>>16);if (((val>>32)+(val>>24)+(val>>16)+(val>>8) -val ) & 0xff ) return 0;else return 1;
}
u8 DHT11_Init(void )
{int timeout = 0;GPIO_InitTypeDef GPIO_InitStructure;/* Enable clock */RCC_APB2PeriphClockCmd(RCC_DHT11_PORT , ENABLE);/* Configure Ports */GPIO_InitStructure.GPIO_Pin = DHT11_DQ_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIO_PORT_DHT11, &GPIO_InitStructure);GPIO_ResetBits(GPIO_PORT_DHT11, DHT11_DQ_PIN);Delay_ms(18); //pulldown for 18msGPIO_SetBits(GPIO_PORT_DHT11, DHT11_DQ_PIN);Delay_us(20); //pullup for 30usmode_input();//等待DHT11拉高,80ustimeout = 0;while( (! GPIO_ReadInputDataBit(GPIO_PORT_DHT11, DHT11_DQ_PIN)) && (timeout < 80) ) { timeout++;Delay_us(1); }//wait HIGHif(timeout >= 80)return 1;//等待DHT11拉低,80ustimeout = 0;while( GPIO_ReadInputDataBit (GPIO_PORT_DHT11, DHT11_DQ_PIN) && (timeout < 80) ) { timeout++;Delay_us(1); } //wait LOWif(timeout >= 80)return 1;return 0;
}
JQ8400语音模块驱动
#ifndef __JQ_8400_H__
#define __JQ_8400_H__#include "main.h"
#include "usart2.h" #define JQ8400_GPIO_PORT GPIOA /* GPIO端口 */
#define JQ8400_GPIO_CLK RCC_APB2Periph_GPIOA /* GPIO端口时钟 */
#define JQ8400_GPIO_PIN GPIO_Pin_11 //播放时为高电平,其余时间为低电平#define JQ8400_BUSY GPIO_ReadInputDataBit(JQ8400_GPIO_PORT,JQ8400_GPIO_PIN)//读取判忙状态,是否正在播放#define JQ8400_SendData USART2_SendByte#define SET_CMD 0X00 //仅设置模式,并不送入数据指令#define PLAY_ON 0X02 // 播放
#define PLAY_SUSPEND 0X03 //暂停
#define PLAY_OFF 0X04 //停止
#define PLAY_LAST 0X05 //上一曲
#define PLAY_NEXT 0X06 //下一曲#define SELECTE_PLAY 0X07 //指定曲目 后面要加曲目号#define SET_SOUND 0X13 //音量设置 1-30级,要送16进制即: 0-0X1E
#define SOUND_ADD 0X14 //音量加
#define SOUND_DEC 0X15 //音量减#define SELECTE_MODE 0X18 //模式
#define MODE_DQXH 0X01 //单曲循环
#define MODE_DQTZ 0X02 //单曲停止
#define MODE_SJBF 0X03 //随机播放//sbit JQ8400_BUSY=P2^4; //播放时为高电平,其余时间为低电平
void JQ8400_Init(void);void JQ8400_6x00SendCmd(u8 cmd,u16 dat);//发送命令#endif
#include "JQ_8400.h"
#include "delay.h"
/*****在线语音合成工具http://tools.bugscaner.com/tts/ ********/
void JQ8400_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; /*定义一个GPIO_InitTypeDef类型的结构体*/RCC_APB2PeriphClockCmd(JQ8400_GPIO_CLK,ENABLE);//使能PORTB时钟GPIO_InitStructure.GPIO_Pin = JQ8400_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //设置成上拉输入GPIO_Init(JQ8400_GPIO_PORT, &GPIO_InitStructure); //初始化JQ8400_6x00SendCmd(SET_SOUND,0X1E); //设置默认播放声音JQ8400_6x00SendCmd(SELECTE_MODE,MODE_DQTZ); //设置默认播放模式,单曲停止
// JQ8400_6x00SendCmd(SELECTE_PLAY,1); //选择指定曲目播放
}
void JQ8400_SendMultiByte(u8 *Buff, u8 Len )
{u8 i;for ( i = 0 ; i < Len ; i++ ){JQ8400_SendData( Buff[i] ); }
}
u8 JQ8400_SumCheck ( u8 *Str, u8 len ) //和校验
{u16 xorsum = 0;u8 i;for ( i = 0; i < len; i++ ){xorsum = xorsum + ( *Str++ );}return ( ( u8 ) ( xorsum & 0x00ff ) );
}
void JQ8400_6x00SendCmd(u8 cmd,u16 dat)//发送命令
{u8 pbuff[6];u8 xorsum;pbuff[0]=0xAA;pbuff[1]=cmd;if(cmd==SET_SOUND){pbuff[2]=0x01;pbuff[3]=(u8)dat;xorsum=JQ8400_SumCheck(pbuff,4);pbuff[4]=xorsum;JQ8400_SendMultiByte(pbuff,5); }else if(cmd==SELECTE_PLAY){pbuff[2]=0x02;pbuff[3]=(u8)(dat>>16)&0xff;pbuff[4]=(u8)(dat&0xff);xorsum=JQ8400_SumCheck(pbuff,5);pbuff[5]=xorsum;JQ8400_SendMultiByte(pbuff,6); }else if(cmd==SELECTE_MODE){pbuff[2]=0x01;pbuff[3]=(u8)dat;xorsum=JQ8400_SumCheck(pbuff,4);pbuff[4]=xorsum;JQ8400_SendMultiByte(pbuff,5); }else{ pbuff[2]=0x00;xorsum=JQ8400_SumCheck(pbuff,3);pbuff[3]=xorsum;JQ8400_SendMultiByte(pbuff,4); } Delay_ms(500); while(JQ8400_BUSY); //播放时为高电平,其余时间为低电平
}
串口驱动
由于串口驱动都是类似的,只需要更改不同的串口对应的GPIO,通信格式即可,故放一个模板。
#ifndef __usart1_h
#define __usart1_h#include "stm32f10x.h"void USART1_Init(void);
void USART1_SendByte(u8 date);#endif
#include "usart1.h"
#include <stdio.h>
#include <string.h>#include "proc.h"
#include "HLK210.h"//reference: ..\2.STM32固件库v3.5\stm32f10x_stdperiph_lib\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\USART\Interrupt
//TXD1 - PA9 RXD1 - PA10
static void USART1_NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* Enable the USART1 global Interrupt */NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVICPriority_Structure.Usart1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}
static void USART1_RCC_Configuration(void)
{ /* Enable GPIO clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);/* Enable USARTy Clock */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //在使用串口复用功能的时候,要开启相应的功能时钟USART ,且此时钟源在APB1上!!!
}
static void USART1_GPIO_Configuration(void)
{GPIO_InitTypeDef GPIO_InitStructure;/* Configure USARTy Rx as input floating */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);/* Configure USARTy Tx as alternate function push-pull */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);
}static void USART1_Configuration(void)
{USART_InitTypeDef USART_InitStructure;/* USARTy and USARTz configuration ------------------------------------------------------*//* USARTy and USARTz configured as follow:- BaudRate = 9600 baud - Word Length = 8 Bits- One Stop Bit- No parity- Hardware flow control disabled (RTS and CTS signals)- Receive and transmit enabled*/USART_InitStructure.USART_BaudRate = 115200;//波特率设置;USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
// USART_InitStructure.USART_Mode = USART_Mode_Rx; //收模式USART_Init(USART1, &USART_InitStructure); //初始化串口USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断USART_Cmd(USART1, ENABLE); //使能串口
}
void USART1_Init(void)
{USART1_NVIC_Configuration();USART1_RCC_Configuration();USART1_GPIO_Configuration();USART1_Configuration();HLK210_ClearDate();
}
void USART1_SendByte(u8 date)
{USART_SendData(USART1,date); while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}void USART1_IRQHandler(void) //串口1中断服务程序
{u8 Res=0;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
// Proc_ShowTest(Res);HLK210_Receive_Byte(Res); }
}