基于STM32的种养盆控制系统设计—-蓝牙、显示模块的实现

1 简介

设计一个能够实时的检测盆栽土壤湿度,还能根据湿度进行自动浇水等操作,保证土壤湿度以适应植物的生长环境的智能盆栽装置。针对日常生活中人们热衷于盆栽种植但又因工作繁忙而忘记浇水导致盆栽枯死的问题,采用STM32作为系统主控芯片,构建一个的智能监控种植系统。通过对指定植物种植环境的温度、湿度数据进行统计分析,能实现自动浇灌、调整光照、远程告警及无线监控等功能,最终实现盆栽智能种植,为盆栽种植爱好者提供便利。这个设计有简单、实用性强、可靠性高等特点。

2 系统总体方案的设计

本项目通过构建一个手机APP智能监控种植系统,对指定植物种植环境的温度、湿度数据的统计分析,自动实现浇灌、光照调整、 远程告警及无线监控等功能,实现智能种植。智能盆栽种植监控系统由七个模块组成,包括主控制器模块、温湿度模块、洒水模块、光照模块、显示模块和风扇模块、蓝牙模块。针对不同的花卉,设计了个性化专属控制方式:
第1种是手动控制模式, 用户只需调节所需的模式就可以按照设定周期进行浇水,还可以自定义控制进水量;
第2种是利用湿度传感器检测盆栽的湿度,当土壤湿度较低时,主控制器会在出现低值超过6小时候做出响应,进行水分的补偿,当土壤湿度较高时,水分过多将会发送停止信号到主控制器模块,主控制器模块进行数据处理判断,若水份饱和度超出设定阈值,立即断开洒水模块对花盆水源的供应;
第三种利用手机通过蓝牙发送浇水控制命令,盆栽通过蓝牙HC05连接到手机上,当盆栽主控制器通过蓝牙模块访问到有控制指令下达湿,将按照相应指令解析后,控制洒水模块进行开阀浇花,达到设定量时关闭阀门。此种方式面向不同的花卉,可以在APP端自主选择不同品种的植物,每种植物都设定了不一样的种植环境,方便不同盆栽进行养护,提高了盆栽的多样性处理,体现了系统的智能特性。系统结构如下图所示。

3 模块功能

3.1 OLED液晶显示模块

3.1.1 OLED介绍

OLED,即有机发光二极管( Organic Light Emitting Diode)。OLED 由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。LCD都需要背光,而OLED不需要,因为它是自发光的。这样同样的显示OLED效果要来得好一-些。以目前的技术,OLED的尺寸还难以大型化,但是分辨率确可以做到很高。在此我们使用的是0.96寸OLED显示屏,该屏有以下特点:

  • 1、0.96 寸OLED有黄蓝,白,蓝三种颜色可选;其中黄蓝是屏上1/4部分为黄光,下3/4为蓝;而且是固定区域显示固定颜色,颜色和显区域均不能修改;白光则为纯白,也就是黑底白字;蓝色则为纯蓝,也就是黑底蓝字。

  • 2、分辨率为128*64

  • 3、多种接口方式; OLED裸屏总共种接口包括: 6800、 8080两种并行接口方式、3线或4线的串行SPI接口方式、IC 接口方式(只需要2根线就可以控制OLED了 !),这五种接口是通过屏上的BSO~BS2来配置的。

  • 4、本屏开发了两种接口的Demo板,接口分别为七针的SPI/IC兼容模块,四针的IIC 模块。两种模块都很方便使用;希望大家根据实际需求来选择不同的模块。
  • 5、默认为4线制SPI总线,可以选择3线制SPI总线或者IIC总线
  • 6、超低功耗:正常显示仅为0.06W(远低于TFT显示屏)
  • 7、军工级工艺标准,长期稳定工作
  • 8、提供丰富的STM32、C51、Arduino、Raspberry Pi以及MSP430平台示例程序
  • 9、提供底层驱动技术支持
  • 10、宽电压供电(3V~5V),兼容3.3V和5V逻辑电平,无需电平转换芯片

3.1.2 IC接口模块模块接口定义

  • 1.GND电源地
  • 2.VCC` 电源正(3~5.5V)
  • 3.SCL OLED的DO脚,在IC通信中为时钟管脚
  • 4.SDA OLED的D1脚,在IIC通信中为数据管脚

3.1.3 OLCD驱动IC

本屏所用的驱动IC为SSD1306;其具有内部升压功能;所以在设计的时候不需要再专一设计升压电路;当然了本屏也可以选用外部升压。SSD1306 的每页包含了128个字节,总共8页,这样刚好是128*64 的点阵大小。这点与1.3寸OLED驱动IC SSD1106 ,稍有不同,SSD1106 每页是132个字节,也是8页。所以在用0.96寸OLED移植1.3寸OLED程序的时候需要将0.96寸的显示地址向右偏移2,这样显示就正常了;否则在用1.3寸的时候1.3寸屏右边会有4个像素点宽度显示不正常或是全白,这点大家注意一下。其它的SSD1306和SSD1106区别不大。系统中采用OLED作为显示器件输出信息。其具体电路原理图如下图所示。

其实物图如下图所示。

3.2 HC05蓝牙模块

蓝牙模块是指集成蓝牙功能的芯片基本电路集合,用于无线网络通讯。本蓝牙模块就是为了只能无线数据传输而专门打造的,本模块支持串行接口,支持SP蓝牙串口协议,具有成本低、体积小、收发灵敏性高等特点,只需配备少许的外围元件就能实现大功能。BH-HCO5是秉火科技推出的蓝牙串口模块,它采用蓝牙2.0 协议,可与任何版本的蓝牙兼容通讯,包括与具有蓝牙功能的电脑、蓝牙主机、手机、PDA、PSP 等终端配对,可实现串口透传功能。驱动HC05模块时只需要使用TTL电平标准的串口即可(5V/3.3V电压均可),支持的波特率范围为4800~ 1382400,非常适合用于单片机系统扩展蓝牙特性。

3.2.1 模块参数

3.2.2 模块引脚说明

3.2.3 产品应用范围

  • (1) POS 机
  • (2)蓝牙打印机
  • (3)蓝牙玩具
  • (4)蓝牙高速数据传输产品应用
  • (5)小家电
  • (6)汽车电子

3.2.4 模块特性

  • 1、核心模块是HCO5主从一体模块,引出接口包括VCC、GND、TXD、RXD、 KEY引脚,蓝牙状态引出脚(STATE),未连接输出低,连接后输出高。
  • 2、LED 指示蓝牙连接状态,快闪表示没有蓝牙连接,慢闪表示进入AT模式,双闪表示蓝牙已经连接并打开了端口。
  • 3、底板设置防反接-二极管,带3.3VLDO, 输入电压3.6~6V, 未配对时电流约30mA,配对后约10mA,输入电压禁止超过7V!
  • 4、接口电平3.3V,可以直接连接各种单片机(51、AVR、 PIC、 ARM、MSP430 等),5V单片机也可直接连接,无需MAX232也不能经过MAX232!
  • 5、空旷地有效距离10米(功率等级为CLASS2),超过10米也是可能的,但不对此距离的连接质量做保证。
  • 6、配对以后当全双工串口使用,无需了解任何蓝牙协议,支持8位数据位、1位停止位、可设置奇偶校检的通信格式,这也是常用的通信格式,不支持其他格式。
  • 7、可以通过拉高34角进入AT命令模式设置参数和查询信息。
  • 8、体积小巧(3.57cm*1.52cm), 工厂贴片生产,保证贴片质量。并套透明热缩管,防尘美观,且有一-定的防静电能力。
  • 9、可通过AT命令切换为主机或者从机模式,可通过AT命令连接指定设备。
  • 10、支持从4800bps~1382400bps间的标准波特率。

2.2.5 模块接口说明

  • (1)RXD 串口输入,电平为TTL电平
  • (2)TXD 串口输出,电平为TTL电平
  • (3)GND 接GND
  • (4)VCC 接3.3V-6V

蓝牙模块接口电路图如下图所示。

蓝牙模块实物图如下图所示。

3.3 显示模块、蓝牙模块的测试实现

将温湿度、光照强度等测量值在OLED上显示,显示屏上能显示实时的数值,BLE显示的是蓝牙的状态,MAMUF显示的是手动模式,TEMP显示的是温度值,Hum显示的是湿度值;S-T是温度设定值,S-H是湿度限定值。

蓝牙模块能够同时显示温湿度值,光照强度值,可以自定义三个按钮,分别用三个按钮也可以手动控制水泵、风扇的启停,与实物版上的按键开关能达到具体的功能。

4 实物制作

4.1 原理图

4.2 PCB

4.3 3D图

4.4 BOM

5 最终代码

5.1 LED代码

#include "led.h"   
//初始化PC.13 PC.14 PC.15为输出口.并使能这3个口的时钟            
//LED IO初始化
void LED_Init(void)
{

    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);     //使能PC端口   时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;                 //LED1-->PC.13 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);                     //根据设定参数初始化GPIOC.13
    GPIO_SetBits(GPIOC,GPIO_Pin_13);                         //PC.13 输出高 
    GPIO_SetBits(GPIOC,GPIO_Pin_14);                         //PC.13 输出高 
    GPIO_SetBits(GPIOC,GPIO_Pin_15);                         //PC.13 输出高 
}

5.2 按键代码

#include "stm32f10x.h"
#include "key.h"
//按键初始化函数
void KEY_Init(void) //IO初始化
{ 
     GPIO_InitTypeDef GPIO_InitStructure;

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);//使能PORTB时钟

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_15|GPIO_Pin_14|GPIO_Pin_13|GPIO_Pin_12;//KEY1-KEY4
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
     GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB15,14,13,12

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_4;//BLUE
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOBA4

}

5.3 蜂鸣器代码

#include "beep.h"
//初始化PA1为输出口.并使能这个口的时钟            
//蜂鸣器初始化
void BEEP_Init(void)
{

    GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     //使能GPIOA端口时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;                 //BEEP-->PA.1 端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);     //根据参数初始化GPIOA.1

    GPIO_SetBits(GPIOA,GPIO_Pin_1);//输出1,关闭蜂鸣器输出

}

5.4 OLED 部分代码

//////////////////////////////////////////////////////////////////////////////////     
//  功能描述   : 0.69寸OLED 接口演示例程(STM32F103C8T6系列IIC)
//              说明: 
//              ----------------------------------------------------------------
//              GND   电源地
//              VCC   接5V或3.3v电源
//              SCL   接PB9(SCL)
//              SDA   接PB8(SDA)            
//              ----------------------------------------------------------------
//@yuan
//坐标设置              
//显示2个数字
//x,y :起点坐标     
//len :数字的位数
//size:字体大小
//mode:模式    0,填充模式;1,叠加模式
//num:数值(0~4294967295);               
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
{             
    u8 t,temp;
    u8 enshow=0;                           
    for(t=0;t<len;t++)
    {
        temp=(num/oled_pow(10,len-t-1))%10;
        if(enshow==0&&t<(len-1))
        {
            if(temp==0)
            {
                OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
                continue;
            }else enshow=1; 

        }
         OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); 
    }
} 
//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
{
    unsigned char j=0;
    while (chr[j]!='\0')
    {        OLED_ShowChar(x,y,chr[j],Char_Size);
            x+=8;
        if(x>120){x=0;y+=2;}
            j++;
    }
}
//显示汉字
void OLED_ShowCHinese(u8 x,u8 y,u8 no)
{                      
    u8 t,adder=0;
    OLED_Set_Pos(x,y);    
    for(t=0;t<16;t++)
        {
                OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
                adder+=1;
     }    
        OLED_Set_Pos(x,y+1);    
    for(t=0;t<16;t++)
            {    
                OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
                adder+=1;
      }                    
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
{     
 unsigned int j=0;
 unsigned char x,y;

  if(y1%8==0) y=y1/8;      
  else y=y1/8+1;
    for(y=y0;y<y1;y++)
    {
        OLED_Set_Pos(x0,y);
    for(x=x0;x<x1;x++)
        {      
            OLED_WR_Byte(BMP[j++],OLED_DATA);            
        }
    }
} 

//初始化SSD1306                        
void OLED_Init(void)
{     
     GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);     //使能B端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;     
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //速度50MHz
     GPIO_Init(GPIOB, &GPIO_InitStructure);                //初始化GPIOB,8.9
     GPIO_SetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9);    


    delay_ms(800);

    OLED_WR_Byte(0xAE,OLED_CMD);//--display off
    OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
    OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
    OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  
    OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
    OLED_WR_Byte(0x81,OLED_CMD); // contract control
    OLED_WR_Byte(0xFF,OLED_CMD);//--128   
    OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap 
    OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
    OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
    OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
    OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
    OLED_WR_Byte(0x00,OLED_CMD);//

    OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
    OLED_WR_Byte(0x80,OLED_CMD);//

    OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
    OLED_WR_Byte(0x05,OLED_CMD);//

    OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
    OLED_WR_Byte(0xF1,OLED_CMD);//

    OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
    OLED_WR_Byte(0x12,OLED_CMD);//

    OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
    OLED_WR_Byte(0x30,OLED_CMD);//

    OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
    OLED_WR_Byte(0x14,OLED_CMD);//

    OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
}

5.5 DHT11 代码

#include "dht11.h"
#include "delay.h"
//复位DHT11
void DHT11_Rst(void)       
{                 
    DHT11_IO_OUT();     //SET OUTPUT
    DHT11_DQ_OUT=0;     //拉低DQ
    delay_ms(20);        //拉低至少18ms
    DHT11_DQ_OUT=1;     //DQ=1 
    delay_us(30);         //主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void)        
{   
    u8 retry=0;
    DHT11_IO_IN();//SET INPUT     
    while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
    {
        retry++;
        delay_us(1);
    };     
    if(retry>=100)return 1;
    else retry=0;
    while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
    {
        retry++;
        delay_us(1);
    };
    if(retry>=100)return 1;        
    return 0;
}
//从DHT11读取一个位
//返回值:1/0
u8 DHT11_Read_Bit(void)              
{
     u8 retry=0;
    while(DHT11_DQ_IN&&retry<100)//等待变为低电平
    {
        retry++;
        delay_us(1);
    }
    retry=0;
    while(!DHT11_DQ_IN&&retry<100)//等待变高电平
    {
        retry++;
        delay_us(1);
    }
    delay_us(40);//等待40us
    if(DHT11_DQ_IN)return 1;
    else return 0;           
}
//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
    for (i=0;i<8;i++) 
    {
           dat<<=1; 
        dat|=DHT11_Read_Bit();
    }                            
    return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
     u8 buf[5];
    u8 i;
    DHT11_Rst();
    if(DHT11_Check()==0)
    {
        for(i=0;i<5;i++)//读取40位数据
        {
            buf[i]=DHT11_Read_Byte();
        }
        if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
        {
            *humi=buf[0];
            *temp=buf[2];
        }
    }else return 1;
    return 0;        
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在         
u8 DHT11_Init(void)
{     
     GPIO_InitTypeDef  GPIO_InitStructure;

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);     //使能PA端口时钟

     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                 //PA0端口配置
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOA, &GPIO_InitStructure);                 //初始化IO口
     GPIO_SetBits(GPIOA,GPIO_Pin_0);                         //PA0 输出高


    DHT11_Rst();  //复位DHT11

    return DHT11_Check();//等待DHT11的回应
}

5.6 main 代码

#include "sys.h"    
#include "delay.h"    
#include "led.h" 
#include "beep.h" 
#include "oled.h" 
#include "bmp.h"
#include "dht11.h"
#include "bh1750.h"
#include "stdio.h"
#include "usart.h"
#include "usart2.h"      
#include "key.h"
#include "jdq.h"
#include "usart2.h"    


//获取传感器数据
u8 temperature =0;          
u8 humidity = 0;
float Light = 0; //光照度


//设置的数据
u8 S_temperature = 26;          
u8 S_humidity = 60;




char str[256];

u8 sw = 0; //自动的时候,选择温度还是湿度


int main(void)
{
    u8 t = 0;
    delay_init();             //延时函数初始化    
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE); 
    LED_Init();                    //初始化与LED连接的硬件接口
    uart_init(115200);       //初始化串口1 蓝牙模块
    uart2_init(115200);       //初始化串口2 蓝牙模块
    BEEP_Init();              //初始化蜂鸣器端口
    BH1750_Init();           //初始化与BH1750光照强度连接的硬件接口
    OLED_Init();             //初始化OLED  
    KEY_Init();              //初始化与按键连接的硬件接口
    OLED_Init();             //初始化OLED  
    JDQ_Init();              //初始化风扇、水开关 
    OLED_Clear();            //清除oled屏幕

    while(DHT11_Init())    //DHT11初始化    
    {
        OLED_ShowString(25,3,"DHT11 Error:",16); //oled显示DHT11错误
        delay_ms(200);  //延时200ms
    }        

    OLED_Clear();//清除oled屏幕
    LED1 = LED2 = LED3 = 0;
    BEEP = 0;  
    delay_ms(500);//延时500ms
    LED1 = LED2 = LED3 = 1;      
    BEEP = 1;
    delay_ms(500);//延时500ms

    //显示一个图片
    OLED_DrawBMP(0,0,128,8,BMP2);  //图片显示

    delay_ms(1000);//延时500ms
    OLED_Clear();          //清除oled屏幕

    OLED_ShowString(60,0,"BLE:OFF",16); //OLED显示蓝牙连接状态
    OLED_ShowString(60,0,"S:MAMU",16); //OLED显示手动


    //在OLEd显示设置温度、湿度
    sprintf(str,"S_T:%d",S_temperature);
    OLED_ShowString(5,6,(u8*)str,16); //oled显示温度

    sprintf(str,"S_H:%d",S_humidity);
    OLED_ShowString(70,6,(u8*)str,16); //oled显示湿度

    while(1)
    {

        //查询蓝牙状态
        if(BLUE == 0)
        {
            OLED_ShowString(0,0,"BLE:OFF",16); //OLED显示蓝牙连接状态
        }else{

            OLED_ShowString(0,0,"BLE:ON ",16); //OLED显示蓝牙连接状态
        }

        //查询运行状态状态
        if(flag_state == 0)
        {
            OLED_ShowString(60,0,"S:MAMU",16); //OLED显示手动
        }else{
            OLED_ShowString(60,0,"S:AUTO",16); //OLED显示自动
        }


         //  每100ms读取一次 读取温湿度值     获取光照强度
         if(t%10==0)            //每100ms读取一次
        {                                      
            DHT11_Read_Data(&temperature,&humidity);    //读取温湿度值    
            if (!i2c_CheckDevice(BH1750_Addr))
            {
                Light = LIght_Intensity();              //获取光照强度
            }            

        }    

        //根据光照强度控制LED
        if(Light <= 100)
        {
            LED1 = 0;
        }else{
            LED1 = 1;
        }


        //在OLEd显示温度、湿度、光照强度
        sprintf(str,"Light:%.2f",Light);
        OLED_ShowString(5,2,(u8*)str,16); //oled显示光照强度

        sprintf(str,"Temp:%d",temperature);
        OLED_ShowString(5,4,(u8*)str,16); //oled显示温度

        sprintf(str,"Hum:%d",humidity);
        OLED_ShowString(70,4,(u8*)str,16); //oled显示湿度


        //每500ms发送一次数据去手机
        if(t%50 == 0)
        {
            printf("T:%d,H:%d,L:%.2f",temperature,humidity,Light);
            UsartPrintf(USART2,"T:%d,H:%d,L:%.2f\n\t",temperature,humidity,Light);
        }


        //按键功能

        //按键一 自动和手动切换 0是默认值手动 1是自动(实现根据光照强度控制LED、根据温度控制风扇、根据湿度控制电机)
        if( KEY1 == 0)
        {
            delay_ms(10);
            if(KEY1 == 0)
            {
                while(!KEY1);
                flag_state = !flag_state;
            }
        }


        if( KEY2 == 0)
        {
            delay_ms(10);
            if(KEY2 == 0)
            {
                while(!KEY2);
                sw = !sw;

            }


        }


        // SW=0的时候是调整温度的数字
        if( (sw == 0) && (flag_state == 1))
        {
            if( KEY3 == 0)
            {
                delay_ms(10);
                if(KEY3 == 0)
                {
                    while(!KEY3);
                    LED3 = !LED3;
                        S_temperature++;
                    if(S_temperature > 50)
                        S_temperature = 50;
                }
            }

            if( KEY4 == 0)
            {
                delay_ms(10);
                if(KEY4 == 0)
                {
                    while(!KEY4);
                    LED3 = !LED3;
                        S_temperature--;
                    if(S_temperature <= 0)
                        S_temperature = 0;
                }
            }
            sprintf(str,"S_T:%d",S_temperature);
            OLED_ShowString(5,6,(u8*)str,16); //oled显示温度

        }    


        // SW=1的时候是调整湿度的数字
        if( (sw == 1) && (flag_state == 1 ) )
        {
            if( KEY3 == 0)
            {
                delay_ms(10);
                if(KEY3 == 0)
                {
                    while(!KEY3);
                    LED3 = !LED3;
                        S_humidity++;
                    if(S_humidity > 100)
                        S_humidity = 99;
                }
            }

            if( KEY4 == 0)
            {
                delay_ms(10);
                if(KEY4 == 0)
                {
                    while(!KEY4);
                    LED3 = !LED3;
                        S_humidity--;
                    if(S_humidity <= 0)
                        S_humidity = 0;
                }
            }
            sprintf(str,"S_H:%d",S_humidity);
            OLED_ShowString(70,6,(u8*)str,16); //oled显示湿度
        }    

        //实现自动功能
        if(flag_state == 1)
        {
            if(S_temperature <= temperature)
            {
                JDQ2 = 1;
            }
            else{
                JDQ2 = 0;
            }

            if(S_humidity >= humidity)
            {
                JDQ1 = 1;
            }
            else{
                JDQ1 = 0;
            }
        }


        //手动时候
        if(flag_state == 0)
        {
            if( KEY3 == 0)
            {
                delay_ms(10);
                if(KEY3 == 0)
                {
                    while(!KEY3);
                    LED3 = !LED3;
                    JDQ2 = !JDQ2;
                }
            }

            if( KEY4 == 0)
            {
                delay_ms(10);
                if(KEY4 == 0)
                {
                    while(!KEY4);
                    LED3 = !LED3;
                    JDQ1 = !JDQ1;
                }
            }
        }


        delay_ms(10);
        t++;
    }
 }