目录
第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); //根据参数初始化中断寄存器
}



















我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc