目录
第1章 前言 1
1.1 课题研究的背景和实际意义 1
1.1.1课题背景 1
1.1.2实际意义 1
1.2国内外发展现状、存在问题以及前景 2
1.2.1发展现状 2
1.2.2存在问题 2
1.2.3发展前景 2
1.3 主要工作、内容安排及预期成果 3
1.3.1主要研究工作 3
1.3.2预期成果 3
第2章 总体设计方案 5
2.1 系统总体方案设计 5
2.2 系统方案选择 6
2.2.1 无线通讯方案选择 6
2.2.2 显示器方案选择 6
第3章 系统硬件设计 7
3.1 控制单元模块 7
3.2 人机交互模块 8
3.3 GPRS电路设计 9
3.4 温湿度传感器电路设计 10
3.5 光强检测电路设计 10
3.6 窗帘控制电路设计 11
3.6.1 步进电机的选用 11
3.6.2 步进电机28BYJ-48介绍 11
3.6.3 步进电机驱动 12
3.7 继电器驱动电路设计 12
3.8 电源电路设计 13
第4章 系统软件设计 15
4.1 软件开发环境介绍 15
4.2 软件总体设计 15
4.2.1 程序结构分析 15
4.2.2 主程序设计 15
4.2.3 OLED驱动程序分析 17
4.2.4 SIM900通信程序设计 17
第5章 系统调试与结果分析 19
5.1 程序仿真设计 19
5.2 实物调试 20
结论 22
致谢 23
参考文献 24
1.3 主要工作、内容安排及预期成果
1.3.1 主要研究工作
消费者们对于智能家居呈现出一种多样化的迫切性需求,一方面是居住环境的安全性,体现在门窗安全、煤气泄漏及火灾隐患自动报警等要求;另一方面是居住环境的舒适便捷性,体现在无线通信的控制方式、室内灯光以及直观性人机交互操作等方面。
在了解到消费者对智能家居实质性需求的基础上,结合本人自身的开发能力,本课题最终确定研究的简易智能家居控制系统涵盖了如下几个模块:传感器模块、控制器模块,GPRS通讯模块,继电器输出控制模块,显示器模块等五大电路模块。本系统主要是侧重点是在远程报警(室内温度异常时,通过GPRS通讯模块向手机发送报警短信)和远程控制(需要时,远程终端通过GPRS通讯模块向本地控制器发送控制指令,控制继电器开闭)方面。除此之外,还有窗帘根据光照强度自动开闭以及本地按键执行中断控制(应用于特殊情况,如自动控制出错时)。
1.3.2预期成果
通过本系统设计各个模块的搭建,预计能够实现如下功能:
1、本地温度湿度报警器实时监测室内情况,当温度异常时发送室内实时数据到设定手机上;测量范围为湿度:2090%RH;温度:050℃。所以本设计使用范围广泛,既可用于气候干燥的北方,也可用于较为湿润的南方;既可适用于工地环境,也可用于婴儿房环境;
2、窗帘的自动控制和按键控制(本设计中用电机正反转表示窗帘的开闭),这个功能解决了用户频繁手动打开窗帘的麻烦。日常生活中,当遇到有强光的晴天,本设计的窗帘则能自动关闭,减少用户亲自打开窗帘的麻烦,遇到相反情况则相反处理。此外设计的按键控制窗帘,也可减少用户手拨窗帘的不便;
3、手机发送控制指令的短信到GPRS通讯模块,实现继电器的开闭。本设计用两个发光二极管代替所控制的家电,实际应用中,可通过继电器控制空调、电饭煲等家用电器。例如炎炎夏季,空调制冷需要一定时间,用户在回家前提前远程控制空调打开,回家即可享受到冰爽的体验。
第2章 总体设计方案
2.1 系统总体方案设计
本设计硬件电路结构包含6个部分,分别是STM32控制器、输入部分、输出部分、电源模块、环境探测、SIM900无线通讯。其中控制器选用32位微控制器STM32F103R8T6OLED显示器;输入部分包含按键输入、SMS指令输入;输出部分包含0.96寸12864 OLED显示器、继电器输出、窗帘控制输出;环境探测包含一体化温湿度检测模块DHT11、光强检测4线制光敏传感器模块。结构框图如下图1.1所示。
光强检测选用的是光感电阻传感器模块,可输出模拟量(电压)至STM32控制器处理后由OLED显示器显示出当前光照强度,同时输出经比较器LM393比较后输出的开关量(0或1)至STM32来控制窗帘的开关从而控制家居的通光率。在系统接通电源开始运行后,控制器通过串口访问SIM900通讯模块,不断判断是否收到绑定手机发送的短信指令,若接受到有效命令则解析指令控制继电器的开闭,从而达到控制家电开闭的目的。在系统工作过程中,温湿度传感器DHT11不断采集环境的实时温湿度并通过串口送入控制器。设置阈值来判别正常和异常情况,本文转载自http://www.biyezuopin.vip/onews.asp?id=12500当发现异常时触发SIM900模块向设定手机号发送状态信息。此外,系统通过按键扫描的方式实现人机交互,控制器响应按键输入同时控制OLED显示各类相关数据信息。
//头文件调用
#include "usually.h"
#include "usart.h"
#include "oled.h"
#include "dht11.h"
#include "rtc.h"
#include "delay.h"
#include "stm32f10x_adc.h"
#include <string.h>
#include "BSP_Config.h"
#include "gpio.h"
#include "gsm.h"
//宏定义
#define ADC_CH0 0 //通道0
#define ADC_CH1 1 //通道1
#define ADC_CH2 2 //通道2
#define ADC_CH3 3 //通道3
#define SEC 0
#define MIN 1
#define HOUR 2
#define DATE 3
#define MON 4
#define YEAR 6
#define MODE_NORMAL 0
#define MODE_SET_HOUR 1
#define MODE_SET_MIN 2
#define MODE_SET_SEC 3
#define MODE_SET_YEAR 4
#define MODE_SET_MON 5
#define MODE_SET_DATE 6
#define MODE_SET_HUMI_HIGH 8
#define MODE_SET_TEMP_HIGH 7
#define MODE_SET_LIGHT 9
#define KEY_MENU_IN PBin(0)
#define KEY_ADD_IN PBin(1)
#define KEY_SUB_IN PBin(2)
//步进控制 A-AB-B-BC-C-CD-D-DA
#define Motor1_A_run { GPIO_SetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);GPIO_ResetBits(GPIOB,GPIO_Pin_10);GPIO_ResetBits(GPIOB,GPIO_Pin_11);}
#define Motor1_AB_run { GPIO_SetBits(GPIOB,GPIO_Pin_8); GPIO_SetBits(GPIOB,GPIO_Pin_9); GPIO_ResetBits(GPIOB,GPIO_Pin_10);GPIO_ResetBits(GPIOB,GPIO_Pin_11);}
#define Motor1_B_run { GPIO_ResetBits(GPIOB,GPIO_Pin_8);GPIO_SetBits(GPIOB,GPIO_Pin_9); GPIO_ResetBits(GPIOB,GPIO_Pin_10);GPIO_ResetBits(GPIOB,GPIO_Pin_11);}
#define Motor1_BC_run { GPIO_ResetBits(GPIOB,GPIO_Pin_8);GPIO_SetBits(GPIOB,GPIO_Pin_9); GPIO_SetBits(GPIOB,GPIO_Pin_10); GPIO_ResetBits(GPIOB,GPIO_Pin_11);}
#define Motor1_C_run { GPIO_ResetBits(GPIOB,GPIO_Pin_8);GPIO_ResetBits(GPIOB,GPIO_Pin_9);GPIO_SetBits(GPIOB,GPIO_Pin_10); GPIO_ResetBits(GPIOB,GPIO_Pin_11);}
#define Motor1_CD_run { GPIO_ResetBits(GPIOB,GPIO_Pin_8);GPIO_ResetBits(GPIOB,GPIO_Pin_9);GPIO_SetBits(GPIOB,GPIO_Pin_10); GPIO_SetBits(GPIOB,GPIO_Pin_11);}
#define Motor1_D_run { GPIO_ResetBits(GPIOB,GPIO_Pin_8);GPIO_ResetBits(GPIOB,GPIO_Pin_9);GPIO_ResetBits(GPIOB,GPIO_Pin_10);GPIO_SetBits(GPIOB,GPIO_Pin_11);}
#define Motor1_DA_run { GPIO_SetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);GPIO_ResetBits(GPIOB,GPIO_Pin_10);GPIO_SetBits(GPIOB,GPIO_Pin_11);}
#define Motor1_STOP_run { GPIO_ResetBits(GPIOB,GPIO_Pin_8); GPIO_ResetBits(GPIOB,GPIO_Pin_9);GPIO_ResetBits(GPIOB,GPIO_Pin_10);GPIO_ResetBits(GPIOB,GPIO_Pin_11);}
#define motorSpdDelayUs 1100
//声明变量
extern struct Data_Time timer;
unsigned char *pUart1_Rxd;//接收数据指针
unsigned int uart1_RxNum=0;//串口1接收字数
unsigned char Num_TXD=0;//串口1发送缓冲区的字节数
unsigned char Uart1_TxBuf[256]={0,2,3,};//串口1发送缓冲区
unsigned char Uart1_RxBuf[256]; //串口1接收缓冲区
unsigned char *pUart2_Rxd; //串口2接收数据指针
unsigned int uart2_RxNum=0; //串口2接收字数
unsigned char uart2_TxNum=0; //串口2发送缓冲区的字节数
unsigned char Uart2_TxBuf[256]={0,2,3,};//串口2发送缓冲区
unsigned char Uart2_RxBuf[256]; //串口2接收缓冲区
//变量声明
//extern struct tm timer;
char line1str[17]="Welcome to use!";
char line2str[17]="Wating gsm... ";
char line3str[17]=" ";
char line4str[17]=" ";
uint8_t dht11_buf[5];
uint8_t nowtemp,nowhumi;//当前温湿度值
uint8_t thalmflg; //温湿度过高报警
uint16_t adtemp[12]={0}; //连续采集12点算平均值
uint16_t light_adc,set_lit_high,lit_high;
uint8_t almtmp_high,almhumi_high;
uint8_t mode_status; //模式
uint8_t flashflg; //模式
uint8_t settimeflg; //时间被设置标志位
uint8_t solid1flg,solid2flg,winflg;
unsigned char settime[8]={0x00,30,12,0x6,10,0x01,15};//??sec,min,hour,date,month,week,year
char recephonenum[12]="13538510586";
char phonenum_flash;
uint8_t adci=0;
char strLs[32];
//按键输入初始化
void Key_init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口时钟
//Configure pin Pb1 as output
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA13,PA14,PA15按键输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
//继电器输出IO初始化
void Solid_Init(){
GPIO_InitTypeDef GPIO_InitStructure;
//Configure pin Pb0 as output
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOB,&GPIO_InitStructure);
//Configure pin Pb1 as output
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOB,&GPIO_InitStructure);
/* GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits(GPIOB,GPIO_Pin_6);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_ResetBits(GPIOB,GPIO_Pin_6); */
}
//步进输出IO初始化
void Motor_Init(){
GPIO_InitTypeDef GPIO_InitStructure;
//Configure pin Pb0 as output
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOB,&GPIO_InitStructure);
//Configure pin Pb1 as output
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOB,&GPIO_InitStructure);
//Configure pin Pb0 as output
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOB,&GPIO_InitStructure);
//Configure pin Pb1 as output
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOB,&GPIO_InitStructure);
/* GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits(GPIOB,GPIO_Pin_6);
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_ResetBits(GPIOB,GPIO_Pin_6); */
}
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3
void Adc_Init(void)
{
//先初始化IO口
RCC->APB2ENR|=1<<2; //使能PORTA口时钟
GPIOA->CRL&=0XFFFF0000;//PA0 1 2 3 anolog输入
//通道10/11设置
RCC->APB2ENR|=1<<9; //ADC1时钟使能
RCC->APB2RSTR|=1<<9; //ADC1复位
RCC->APB2RSTR&=~(1<<9);//复位结束
RCC->CFGR&=~(3<<14); //分频因子清零
//SYSCLK/DIV2=12M ADC时钟设置为12M,ADC最大时钟不能超过14M!
//否则将导致ADC准确度下降!
RCC->CFGR|=2<<14;
ADC1->CR1&=0XF0FFFF; //工作模式清零
ADC1->CR1|=0<<16; //独立工作模式
ADC1->CR1&=~(1<<8); //非扫描模式
ADC1->CR2&=~(1<<1); //单次转换模式
ADC1->CR2&=~(7<<17);
ADC1->CR2|=7<<17; //软件控制转换
ADC1->CR2|=1<<20; //使用用外部触发(SWSTART)!!! 必须使用一个事件来触发
ADC1->CR2&=~(1<<11); //右对齐
ADC1->SQR1&=~(0XF<<20);
ADC1->SQR1&=0<<20; //1个转换在规则序列中 也就是只转换规则序列1
//设置通道0~3的采样时间
ADC1->SMPR2&=0XFFFFF000;//通道0,1,2,3采样时间清空
ADC1->SMPR2|=7<<9; //通道3 239.5周期,提高采样时间可以提高精确度
ADC1->SMPR2|=7<<6; //通道2 239.5周期,提高采样时间可以提高精确度
ADC1->SMPR2|=7<<3; //通道1 239.5周期,提高采样时间可以提高精确度
ADC1->SMPR2|=7<<0; //通道0 239.5周期,提高采样时间可以提高精确度
ADC1->CR2|=1<<0; //开启AD转换器
ADC1->CR2|=1<<3; //使能复位校准
while(ADC1->CR2&1<<3); //等待校准结束
//该位由软件设置并由硬件清除。在校准寄存器被初始化后该位将被清除。
ADC1->CR2|=1<<2; //开启AD校准
while(ADC1->CR2&1<<2); //等待校准结束
//该位由软件设置以开始校准,并在校准结束时由硬件清除
}
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)
{
//设置转换序列
ADC1->SQR3&=0XFFFFFFE0;//规则序列1 通道ch
ADC1->SQR3|=ch;
ADC1->CR2|=1<<22; //启动规则转换通道
while(!(ADC1->SR&1<<1));//等待转换结束
return ADC1->DR; //返回adc值
}
//
uint16_t adc_avg(void)
{
uint8_t i;
uint32_t sum=0;
uint16_t ret=0;
for(i=0;i<12;i++) sum+=adtemp[i];
ret= sum/12;
return ret;
}
//马达正转开窗帘
void motor_Foreward(void)
{
Motor1_A_run;
delay_us(motorSpdDelayUs);
Motor1_AB_run;
delay_us(motorSpdDelayUs);
Motor1_B_run;
delay_us(motorSpdDelayUs);
Motor1_BC_run;
delay_us(motorSpdDelayUs);
Motor1_C_run;
delay_us(motorSpdDelayUs);
Motor1_CD_run;
delay_us(motorSpdDelayUs);
Motor1_D_run;
delay_us(motorSpdDelayUs);
Motor1_DA_run;
delay_us(motorSpdDelayUs);
}
//马达反转关窗帘
void motor_Backward(void)
{
Motor1_DA_run;
delay_us(motorSpdDelayUs);
Motor1_D_run;
delay_us(motorSpdDelayUs);
Motor1_CD_run;
delay_us(motorSpdDelayUs);
Motor1_C_run;
delay_us(motorSpdDelayUs);
Motor1_BC_run;
delay_us(motorSpdDelayUs);
Motor1_B_run;
delay_us(motorSpdDelayUs);
Motor1_AB_run;
delay_us(motorSpdDelayUs);
Motor1_A_run;
delay_us(motorSpdDelayUs);
}
//显示设置页面
void Show_Normal(void){
//显示温湿度
strncpy(line1str,"tmp:99C/hm:99%RH",16);
line1str[4]=0x30+nowtemp/10;
line1str[5]=0x30+nowtemp%10;
line1str[11]=0x30+nowhumi/10;
line1str[12]=0x30+nowhumi%10;
OLED_8x16Str(0,0,line1str);
//显示光照强度及窗帘状态
if(winflg){
strncpy(line2str,"lit:99 /wn:open ",16);
}else{
strncpy(line2str,"lit:99 /wn:close",16);
}
line2str[4]=0x30+light_adc/41/10; //100%显示
line2str[5]=0x30+light_adc/41%10;
OLED_8x16Str(0,2,line2str);
//显示继电器输出状态
strncpy(line3str, "s1:open s2:open ",16);
if(solid1flg) {
line3str[3]='o';line3str[4]='p';line3str[5]='e';line3str[6]='n';line3str[7]=' ';
}else{
line3str[3]='c';line3str[4]='l';line3str[5]='o';line3str[6]='s';line3str[7]='e';
}
if(solid2flg) {
line3str[11]='o';line3str[12]='p';line3str[13]='e';line3str[14]='n';line3str[15]=' ';
}else{
line3str[11]='c';line3str[12]='l';line3str[13]='o';line3str[14]='s';line3str[15]='e';
}
OLED_8x16Str(0,4,line3str);
//显示时间
//line4str[0]= 0x30+ timer.w_year%1000%100/10;
line4str[0]= 0x30+ timer.w_year%1000%100%10;
line4str[1]= '/';
line4str[2]= 0x30+timer.w_month/10;
line4str[3]= 0x30+ timer.w_month%10;
line4str[4]= '/';
line4str[5]= 0x30+timer.w_date/10;
line4str[6]= 0x30+ timer.w_date%10;
line4str[7]= ' ';
line4str[8]= 0x30+ timer.hour/10;
line4str[9]= 0x30+ timer.hour%10;
line4str[10]= ':';
line4str[11]= 0x30+timer.min/10;
line4str[12]= 0x30+ timer.min%10;
line4str[13]= ':';
line4str[14]= 0x30+timer.sec/10;
line4str[15]= 0x30+timer.sec%10;
OLED_8x16Str(0,6,line4str);
}
/*
显示设置页面
*/
void Show_SetPage(void){
uint8_t i;
//显示温湿度
strncpy(line1str,"tH:99C/hH:99%RH ",16);
if(MODE_SET_TEMP_HIGH== mode_status && flashflg){
line1str[3]=' ';
line1str[4]=' ';
}else{
line1str[3]=0x30+almtmp_high/10;
line1str[4]=0x30+almtmp_high%10;
}
if(MODE_SET_HUMI_HIGH== mode_status && flashflg){
line1str[10]=' ';
line1str[11]=' ';
}else{
line1str[10]=0x30+almhumi_high/10;
line1str[11]=0x30+almhumi_high%10;
}
OLED_8x16Str(0,0,line1str);
//设置光强度
strncpy(line2str,"litH:99 15/04/25",16);
if(MODE_SET_LIGHT== mode_status && flashflg){
line2str[5]=' '; //100%显示
line2str[6]=' ';
}else{
line2str[5]=0x30+set_lit_high/10; //100%显示
line2str[6]=0x30+set_lit_high%10;
}
if(MODE_SET_YEAR== mode_status && flashflg){
line2str[8]=' '; //100%显示
line2str[9]=' ';
}else{
line2str[8]=0x30+settime[YEAR]/10; //100%显示
line2str[9]=0x30+settime[YEAR]%10;
}
if(MODE_SET_MON== mode_status && flashflg){
line2str[11]=' '; //100%显示
line2str[12]=' ';
}else{
line2str[11]=0x30+settime[MON]/10; //100%显示
line2str[12]=0x30+settime[MON]%10;
}
if(MODE_SET_DATE== mode_status && flashflg){
line2str[14]=' '; //100%显示
line2str[15]=' ';
}else{
line2str[14]=0x30+settime[DATE]/10; //100%显示
line2str[15]=0x30+settime[DATE]%10;
}
OLED_8x16Str(0,2,line2str);
//设置时间
strncpy(line3str," 10/59/00 ",16);
if(MODE_SET_HOUR== mode_status && flashflg){
line3str[1]=' '; //100%显示
line3str[2]=' ';
}else{
line3str[1]=0x30+settime[HOUR]/10; //100%显示
line3str[2]=0x30+settime[HOUR]%10;
}
if(MODE_SET_MIN== mode_status && flashflg){
line3str[4]=' '; //100%显示
line3str[5]=' ';
}else{
line3str[4]=0x30+settime[MIN]/10; //100%显示
line3str[5]=0x30+settime[MIN]%10;
}
if(MODE_SET_SEC== mode_status && flashflg){
line3str[7]=' '; //100%显示
line3str[8]=' ';
}else{
line3str[7]=0x30+settime[SEC]/10; //100%显示
line3str[8]=0x30+settime[SEC]%10;
}
OLED_8x16Str(0,4,line3str);
//显示手机
strncpy(line4str,"NO:13538510586 ",16);
for(i=3;i<14;i++){
line4str[i]= recephonenum[i-3];
}
OLED_8x16Str(0,6,line4str);
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
int main(void)
{
uint8_t check,flashi,t,posi;
uint16_t adcx,motori,tt;
u32 i=0,xx;
SystemInit(); //系统时钟配置
OLED_Init(); //初始化OLED
NVIC_Configuration(); //初始化中断向量
Init_RTC(); //内部RTC初始化
Adc_Init(); //adc 初始化
Usart1_Configuration(9600); //串口配置 设置波特率9600
USART2_Config(9600);
Key_init(); //按键初始化输入
OLED_8x16Str(0,0,line1str);
OLED_8x16Str(0,2,line2str);
OLED_8x16Str(0,4,line3str);
OLED_8x16Str(0,6,line4str);
Motor_Init(); //马达控制IO初始化
Uart1_ClrBuf();
while(0==Sim_Send_AT()) delay_ms(1000); //??SIM ???? ,SIM900?????
Sim_Set_MODE(1);
delay_ms(800);
Sim_ReSms_Config();
delay_ms(800);
Sim_Sms_Config_Cscs();
Solid_Init(); //继电器IO配置输出
Uart2_ClrBuf();
Uart1_ClrBuf();
set_lit_high=85;
almtmp_high=40;
almhumi_high=60;
mode_status=0;
//RTC_Set(2015,4,25,20,35,00);
adci=0;
while(1)
{
if(KEY_MENU_IN==0){
delay_ms(5);
if(KEY_MENU_IN==0){
mode_status++; //
if(mode_status>9) mode_status=0;
if( settimeflg){
settimeflg=0;
Time_Update(settime[YEAR]+2000,settime[MON],settime[DATE],settime[HOUR],settime[MIN],settime[SEC]);
}
}
while(KEY_MENU_IN==0) ; //等待放键
}
if(KEY_ADD_IN==0){ //加键
delay_ms(5);
if(KEY_ADD_IN==0){
switch(mode_status ){ //
case MODE_SET_HOUR:
if(settime[HOUR]<24) settime[HOUR]++;
else settime[HOUR]=0;
settimeflg=1;
break;
case MODE_SET_MIN:
if(settime[MIN]<60) settime[MIN]++;
else settime[MIN]=0;
settimeflg=1;
break;
case MODE_SET_SEC:
if(settime[MIN]<60) settime[SEC]++;
else settime[SEC]=0;
settimeflg=1;
break;
case MODE_SET_YEAR:
if(settime[YEAR]<99) settime[YEAR]++;
else settime[YEAR]=0;
settimeflg=1;
break;
case MODE_SET_MON:
if(settime[MON]<12) settime[MON]++;
else settime[MON]=0;
settimeflg=1;
break;
case MODE_SET_DATE:
if(settime[DATE]<31) settime[DATE]++;
else settime[DATE]=0;
settimeflg=1;
break;
case MODE_SET_TEMP_HIGH:
if(almtmp_high<99) almtmp_high++;
else almtmp_high=0;
break;
case MODE_SET_HUMI_HIGH :
if(almhumi_high<99) almhumi_high++;
else almhumi_high=0;
break;
case MODE_SET_LIGHT :
if(set_lit_high<99) set_lit_high++;
else set_lit_high=0;
break;
}
}
while(KEY_ADD_IN==0) ;
}
if(KEY_SUB_IN==0){
delay_ms(5);
if(KEY_SUB_IN==0){
switch(mode_status ){ //
case MODE_SET_HOUR:
if(settime[HOUR]>0) settime[HOUR]--;
else settime[HOUR]=0;
settimeflg=1;
break;
case MODE_SET_MIN:
if(settime[MIN]>0) settime[MIN]--;
else settime[MIN]=0;
settimeflg=1;
break;
case MODE_SET_SEC:
if(settime[MIN]>0) settime[SEC]--;
else settime[SEC]=0;
settimeflg=1;
break;
case MODE_SET_YEAR:
if(settime[YEAR]>0) settime[YEAR]--;
else settime[YEAR]=0;
settimeflg=1;
break;
case MODE_SET_MON:
if(settime[MON]>0) settime[MON]--;
else settime[MON]=0;
settimeflg=1;
break;
case MODE_SET_DATE:
if(settime[DATE]>0) settime[DATE]--;
else settime[DATE]=0;
settimeflg=1;
break;
case MODE_SET_TEMP_HIGH:
if(almtmp_high>0) almtmp_high--;
else almtmp_high=0;
break;
case MODE_SET_HUMI_HIGH :
if(almhumi_high>0) almhumi_high--;
else almhumi_high=0;
break;
case MODE_SET_LIGHT :
if(set_lit_high>0) set_lit_high--;
else set_lit_high=0;
break;
}
}
while(KEY_SUB_IN==0) ;
}
switch(mode_status){ ///不同状态显示不同页面
case MODE_NORMAL:
dht11_readdata(dht11_buf);
check= dht11_buf[0]+ dht11_buf[1]+ dht11_buf[2]+ dht11_buf[3];
if(dht11_buf[4]==check){
nowhumi = dht11_buf[0];
nowtemp = dht11_buf[2];
thalmflg =0;
if(nowtemp> almtmp_high) thalmflg=1;
if(nowhumi> almhumi_high) thalmflg=1;
if (thalmflg){ //触发短息发送
tt++;
if(tt>300){
strncpy(strLs,"Alarm Temp:99 oC, Humi:99 %RH",29);
strLs[11]=0x30+nowtemp/10;
strLs[12]=0x30+nowtemp%10;
strLs[23]=0x30+nowhumi/10;
strLs[24]=0x30+nowhumi%10;
OLED_8x16Str(0,2,"Sending msg.... ");
delay_ms(1000);
Sim_Send_Text(recephonenum,strLs);
tt=0;
}
}
}
adtemp[adci]=Get_Adc(ADC_CH0);
adci++;
if( adci>11) {
adci=0;
light_adc = adc_avg();
if(light_adc > set_lit_high*41) {//光照充足关闭窗帘
if(winflg==1){
motori=800;
while(motori--) { motor_Backward();}
Motor1_STOP_run;
}
winflg=0;}
else {
if(winflg==0){
motori=800;
while(motori--) { motor_Foreward();}
Motor1_STOP_run;
}
winflg=1; //打开窗帘
}
}
if(t!=timer.sec)
{
t=timer.sec;
//printf("%d年%d月%d日%d点%d分%d秒\r\n",timer.w_year,timer.w_month,timer.w_date,timer.hour,timer.min,timer.sec);
}
Show_Normal();
memset(strLs,0,sizeof(strLs));
strLs[0]=0x3a;
strLs[1]=nowtemp/10+0x30;
strLs[2]=nowtemp%10+0x30;
strLs[3]=nowhumi/10+0x30;
strLs[4]=nowtemp%10+0x30;
strLs[5]=0x30+light_adc/41/10;
strLs[6]=0x30+light_adc/41%10;
strLs[7]=timer.w_year%1000%100/10+0x30;
strLs[8]=timer.w_year%1000%100%10+0x30;
strLs[9]=timer.w_month/10+0x30;
strLs[10]=timer.w_month%10+0x30;
strLs[11]=timer.w_date/10+0x30;
strLs[12]=timer.w_date%10+0x30;
if(solid1flg) strLs[14]=1+0x30;
else strLs[14]=0+0x30;
if(solid2flg) strLs[15]=1+0x30;
else strLs[15]=0+0x30;
if(winflg) strLs[16]=1+0x30;
else strLs[16]=0+0x30;
for(i=0;i<17;i++) USART2_Senddata(strLs[i]);
break;
case MODE_SET_HOUR:
case MODE_SET_MIN:
case MODE_SET_SEC:
case MODE_SET_YEAR:
case MODE_SET_MON:
case MODE_SET_DATE:
case MODE_SET_HUMI_HIGH:
case MODE_SET_TEMP_HIGH:
case MODE_SET_LIGHT:
flashi++;
if(flashi>2){
flashflg=~flashflg;
flashi=0;
}
Show_SetPage();
break;
default:
break;
}
if(mystrstr(Uart1_RxBuf,"+CMTI:")!= NULL ){ //接收到手机短息
delay_ms(300);
OLED_8x16Str(0,2,"Receing msg.... ");
Uart1_ClrBuf();
delay_ms(1000);
USART1_SendString("AT+CMGR=1\r\n"); //??????
while(Uart1_RxBuf[0]==0); //等级待接收
delay_ms(1000); //set 1lu:
delay_ms(1000); //set 1lu:
delay_ms(1000); //set 1lu:
if( mystrstr(Uart1_RxBuf,"1 Close")!= NULL ){
GPIO_ResetBits(GPIOB,GPIO_Pin_5); //关闭1路继电器输出
solid1flg=0;
}
if( mystrstr(Uart1_RxBuf,"1 Open")!= NULL ){
GPIO_SetBits(GPIOB,GPIO_Pin_5); //关闭1路继电器输出
solid1flg=1;
}
if( mystrstr(Uart1_RxBuf,"2 Close")!= NULL ){
GPIO_ResetBits(GPIOB,GPIO_Pin_6); //关闭2路继电器输出
solid2flg=0;
}
if( mystrstr(Uart1_RxBuf,"2 Open")!= NULL ){
GPIO_SetBits(GPIOB,GPIO_Pin_6); //打开2路继电器输出
solid2flg=1;
}
Sim_delt_Sms(); //删除短信
delay_ms(2000);
Uart1_ClrBuf();
}
if( mystrstr(Uart2_RxBuf,"num")!=NULL ){
//USART2_SendString(Uart2_RxBuf);
posi =0;
for(i=0;i<255;i++){
if(Uart2_RxBuf[i]==0x3a) {posi=i+1; break;}
}
if(posi){
for(i=0;i<11;i++) recephonenum[i]=Uart2_RxBuf[posi+i]; //更新手机号
}
Uart2_ClrBuf();
}
delay_ms(100);
}
}
/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: Init_NVIC
** 功能描述: 系统中断配置
** 参数描述:无
** 作 者: Dream
** 日 期: 2011年5月14日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void Init_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure; //定义一个NVIC向量表结构体变量
#ifdef VECT_TAB_RAM //向量表基地址选择
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //将0x20000000地址作为向量表基地址(RAM)
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //将0x08000000地址作为向量表基地址(FLASH)
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断组 为2
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //配置串口1为中断源
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //设置占先优先级为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置副优先级为0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能串口1中断
NVIC_Init(&NVIC_InitStructure); //根据参数初始化中断寄存器
}