目录
一、方案流程及技术规格书设计
二、系统硬件电路设计
三、软件编写及调试
四、系统调试测试与分析
前言
随着我国科技水平的高速发展以及传统花卉种植设施化、产业化不断推进,我国在花卉种植领域的科学技术发展已经进入了一个新阶段。在这一阶段,我国花卉种植产业发展的主要目标,不仅是建设高水平的现代化花卉种植业,同时还要提高该产业在国际市场上的竞争力。这也成为我国在当前及未来一段时间内,花卉种植产业发展的重要任务。
近几年来,我国温室产业发展迅速,温室面积居世界各国首位。据统计,目前我国日光温室和塑料大棚分别达到 330 千公顷(496 万亩)和 670 公顷(1007 万亩)。但是,我国的温室自动控制技术远远跟不上温室数量的增长,农民朋友还在使用大量的人力劳动,不仅劳累,而且因为无法对温室环境进行精确监测,不仅浪费了大量的资源,还使作物产量受到了影响,降低了收入。与发达国家的现代化农业相比,还有相当大的差距,尤其在是在温室生产环境各个因子的自动控制方面。
建造先进温室有利于解决靠天吃饭的问题,防止恶劣天气,排除季节因素给生物创造出一个适宜的生长环境,消除对作物生长不利的环境因素来促进生物生长,使其部分或完全克服外界气候的制约,从而缩短作物的生长周期,提高作物的产量,获得一定的经济效益。
本课题目的在于研究一个基于单片机为主控芯片下的温室自动检测控制系统,用于监测温度、湿度、光照,通过单片机处理数据并控制喷水和照明设备,自动完成花卉温室的控制。并且有报警功能。本系统能控制温室在理想的温湿度和光照环境,有利于花卉的生长,并且是全自动运行,节省人力物力,具有很好的实用和推广价值。
软件工具准备
软件:
电路设计:protel99 se(up主使用版本) 或者其他版本,或者其他电路设计软件;
单片机开发:Keil5;
调试测试:串口调试助手,逻辑分析仪等;
工具:
电路焊接:电烙铁,SMT(有条件的);
调试:
万用表、示波器(基础入门即可,可以白嫖学校或者公司)USB转串口工具、仿真器;
一、方案流程及技术规格书设计
方案流程设计
技术规格书设计
1.本设计采用DHT11温湿度传感器,光敏电阻检测温湿度和光照度。用320X240TFT彩色液晶显示温室参数。
2.单片机采集温湿度、光照度,经处理数据后,控制灯光和喷水设备保持温湿度和光照在设定状态。
3.控制设备有灯(LED灯模拟)、喷水设备(继电器输出)。
4、超出设置范围,系统蜂鸣器报警。
5、4个按键可以设置报警参数。
二、系统硬件电路设计
本设计采用STM32F103单片机,DHT11温湿度传感器、TFT LCD液晶显示、光敏电阻、蜂鸣器和LED报警等电路。单片机与DHT11温湿度传感器通信,采集温湿度值。光敏电阻输出模拟信号,经AD转换处理,得到光照。温湿度超过范围时,进行声光报警。
2.1微处理控制电路
系统采用STM32F103C8T6单片机。LQFP48封装,STM32F103是ARM系列单片机,电路图如图所示:
图中VCC3.3供电电压3.3V。R12、C19复位电路,C20、C101、C102滤波作用,J6是仿真烧录口。
单片机IO口连接介绍:
PB0-PB2(18-20脚):LCD数据口。
PB3-PB7(39-43脚):LCD数据口。
PB8-PB9(45-46脚):LCD数据口。
PB10-PB11(21-22脚):LCD数据口。
PB12-PB15(25-28脚):LCD数据口。
PC13-PC14:LCD控制。
PA8-PA9:LCD控制。
PA7:LCD背光。
PA0-PA2:按键。
PA3:光敏电阻输入。
PA4:蜂鸣器控制。
PA5:LED灯控制。
PA6:DHT11温湿度控制。
2.2 温湿度传感器电路
DHT11是集成温湿度传感器、内置MCU,温湿度传感器与单片机单线数字通信,电路如图:
1脚是电源VCC,4脚接地,2脚是传感器输出脚。C18滤波,R21上拉电阻。
2.3 TFT LCD显示电路
设计采用2.8寸TFT LCD,16位并行总线,控制芯片是ILI9341,电路如图:
C17是滤波电容。IO口连接介绍:
LCD_CS、LCD_RS、LCD_WR、LCD_RD(1-4脚):LCD读写控制脚。
RESET(5脚):复位。
LCD_D0-LCD_D15(6-21脚):LCD数据接口。
LCD_BL(23脚):背光控制。
VCC3.3、GND:电源和地。
BL_VDD(28脚):背光供电。
其他引脚是触摸屏控制脚,本设计未使用。
2.4按键电路
没有按下按键,对应IO口是高电平,按键按下,对应IO口接地,是低电平。单片机检测各个按键IO口电平,判断按键状态。电路如图:
2.5 LED电路
LED通过单片机IO口控制,R22是限流电阻。电路如图。
2.6蜂鸣器驱动电路
蜂鸣器模拟报警设备。由于IO口驱动能力有限,所以使用三极管放大电路,扩大驱动电流。电路如图。
2.7 光敏电阻电路
G1是光敏电阻,R14是固定电阻,OK是输出信号,光敏电阻阻值越大、输出信号越大,AD转换后,就可以判断光照度。光敏电阻接口电路如图:
2.8电源电路
电源是整个系统能源供给中心,稳定的电压是系统工作的必要条件。由于单片机和温湿度传感器都需要纹波小干扰少的电源,所以系统采用线性稳压电路。外部9V电源适配器经过7805稳压输出5V,C4输入滤波电容、C5输出滤波电容。电路如图。
单片机等3.3V供电采用ASM1117线性稳压电路,电路如图。
三、软件编写及调试
3.1主程序设计
本系统使用STM32F103C8T6单片机主控芯片,传感器使用DHT11温湿度传感器,光敏电阻传感器,控制部分有继电器控制,蜂鸣器报警控制,LED灯控制。首先需要初始化单片机系统时钟和外设。正常工作时,DHT11模块检测温度和湿度,单片机单线通信读取温度值和湿度值。光敏电阻检测光照情况。单片机判断温度值、湿度值、光照情况,满足条件打开照明设备和灌溉设备。如果温度值超过预先设定范围,控制蜂鸣器报警。
单片机程序设计一般采用汇编语言和C语言。汇编语言接近机器语言,学习困难,对复杂计算和逻辑控制难以实现。C语言接近人类语言,通俗易懂,比较容易实现计算和逻辑控制。本设计采用C语音设计程序。
本系统需要实现温度湿度和光照检测,通过计算分析,控制照明设备和灌溉设备开关,实现温室恒温、恒湿效果。温度超过一定范围,蜂鸣器报警,提醒管理人员处理。
图是主程序流程图,单片机读取DHT11温度和湿度,判断温度湿度大小,开启关闭照明设备和灌溉设备,光敏电阻经过AD转换,计算得到阻值,通过和阻值表比对,计算光照度。温度超过范围,控制蜂鸣器鸣响。
系统上电后,首先初始化单片机,然后才进入工作状态。
3.2 DHT11温湿度传感器程序设计
DHT11温湿度传感器是数字传感器,其内部有一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。与单片机的连接采用单总线。一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:一次完整的数据传输为40bit,高位先出。数据格式:
8bit湿度整数数据+8bit湿度小数数据
+8bi温度整数数据+8bit温度小数数据
+8bit校验和
数据传送正确时校验和数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。
1.通讯过程如图所示
2、总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。图是主机和DHT11开始通信图。
图是DHT11温湿度传感器程序流程图。
程序代码:
#include "stm32f10x.h"
#include "dht11.h"
#define TRH PAout(6) // PA6
#define TRH_in PAin(6) // PA6
u8 str[]={0,0,0,0,0,0,0,0};
u16 TH,TL,RH,RL,CK;
u16 THc,TLc,RHc,RLc,CKc;
u16 xh,sum;
//IO初始化 PA6
void DHT11_io_Output(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //LED0-->PA.6 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化
}
void DHT11_io_Input(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void delay(u8 b) //误差 0us
{
unsigned char a;
for(;b>0;b--)
{
for(a=2;a>0;a--);
}
}
void delay1(u8 c) //误差 0us
{
unsigned char a,b;
for(;c>0;c--)
{
for(b=142;b>0;b--)
{
for(a=2;a>0;a--);
{
}
}
}
}
void start()
{
TRH = 1;
delay(2);
TRH = 0; //主机拉低18ms
delay1(20);
TRH = 1; //DATA总线由上拉电阻拉高主机延时20
delay(3);
}
u8 receive()
{
u8 i,temp;
xh=0;
while(TRH);
for(i=0;i<8;i++)
{
while(!TRH);
delay(3);
if(TRH)
{
temp=1;
while(TRH);
}
else
{
temp=0;
xh<<=1;
xh|=temp;
}
}
return (xh);
}
void read_dht11(void)
{
while(1)
{
start();
TRH=1; // 读取数据并写入指令
if(!TRH)
{
while(!TRH);//判断DHT11发出 80us 的低电平响应信号是否结束
while(TRH);
delay(8);
RHc = receive(); //数据接收状态
RLc = receive();
THc = receive();
TLc = receive();
CKc = receive();
}
TRH=1;
sum=(RHc+RLc+THc+TLc);//数据校验
if(sum==CKc)
{
RH = RHc;
RL = RLc;
TH= THc;
TL = TLc;
CK = CKc;
str[0] =RH/10; //湿度整数部分
str[1] =RH%10;
str[2] = RL/10 ;
str[3] = TH/10; //温度整数部分
str[4] = TH%10;
str[5] = TL/10;
}
}
}
3.3 TFT LCD 显示程序设计
本设计采用的液晶显示器是320x240TFTLCD。单片机控制的TFTLCD屏一般有MCU屏和RGB屏。MCU屏内置LCD驱动器和显示RAM,接口比较简单,本设计屏驱动IC是ILI9341。
TFTLCD显示采用红、绿、蓝三基色合成各种颜色,简称为RGB。ILI9341可以显示8x8x8共24位真彩色。由于单片机IO口是16位,为了加快刷新速度,设计采用16位真彩色。
ILI9341驱动器显示前需要初始化。首先是单片机IO口的初始化,然后是LCD初始化。
初始化代码:
//写寄存器函数
void LCD_WR_REG(u16 data)
{
LCD_RS_CLR;//写地址
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
//写数据函数
void LCD_WR_DATAX(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
//初始化lcd
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE); //使能PORTA,B,C时钟和AFIO时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);//开启SWD,失能JTAG
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7; ///PORTA7~9复用推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14; ///PORTC13,14复用推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
GPIO_SetBits(GPIOC,GPIO_Pin_13|GPIO_Pin_14);
GPIO_SetBits(GPIOA,GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; // PORTB推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_All);
delay_ms(50); // delay 50 ms
LCD_WriteReg(0x0000,0x0001);
delay_ms(50); // delay 50 ms
lcddev.id = LCD_ReadReg(0x0000);
//9341初始化
LCD_WR_REG(0xCF);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0xC1);
LCD_WR_DATAX(0X30);
LCD_WR_REG(0xED);
LCD_WR_DATAX(0x64);
LCD_WR_DATAX(0x03);
LCD_WR_DATAX(0X12);
LCD_WR_DATAX(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATAX(0x85);
LCD_WR_DATAX(0x10);
LCD_WR_DATAX(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATAX(0x39);
LCD_WR_DATAX(0x2C);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x34);
LCD_WR_DATAX(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATAX(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATAX(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control
LCD_WR_DATAX(0x01); //SAP[2:0];BT[3:0]
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATAX(0x30); //3F
LCD_WR_DATAX(0x30); //3C
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATAX(0XB7);
LCD_WR_REG(0x36); // Memory Access Control
LCD_WR_DATAX(0x48);
LCD_WR_REG(0x3A);
LCD_WR_DATAX(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x1A);
LCD_WR_REG(0xB6); // Display Function Control
LCD_WR_DATAX(0x0A);
LCD_WR_DATAX(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable
LCD_WR_DATAX(0x00);
LCD_WR_REG(0x26); //Gamma curve selected
LCD_WR_DATAX(0x01);
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x2A);
LCD_WR_DATAX(0x28);
LCD_WR_DATAX(0x08);
LCD_WR_DATAX(0x0E);
LCD_WR_DATAX(0x08);
LCD_WR_DATAX(0x54);
LCD_WR_DATAX(0XA9);
LCD_WR_DATAX(0x43);
LCD_WR_DATAX(0x0A);
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x15);
LCD_WR_DATAX(0x17);
LCD_WR_DATAX(0x07);
LCD_WR_DATAX(0x11);
LCD_WR_DATAX(0x06);
LCD_WR_DATAX(0x2B);
LCD_WR_DATAX(0x56);
LCD_WR_DATAX(0x3C);
LCD_WR_DATAX(0x05);
LCD_WR_DATAX(0x10);
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x3F);
LCD_WR_DATAX(0x3F);
LCD_WR_DATAX(0x0F);
LCD_WR_REG(0x2B);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x01);
LCD_WR_DATAX(0x3f);
LCD_WR_REG(0x2A);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0xef);
LCD_WR_REG(0x11); //Exit Sleep
delay_ms(120);
LCD_WR_REG(0x29); //display on
LCD_Display_Dir(0); //默认为横屏
LCD_LED = 1; //点亮背光
LCD_Clear(WHITE);
}
初始化完成后,可以正常显示内容。正常工作状态,显示温度、湿度、光照。如果有报警,显示报警信息。设置状态,显示设置值。图是显示功能流程图。
程序代码:
//在指定位置显示一个字符
//x,y:起始坐标
//num:要显示的字符:" "--->"~"
//size:字体大小 12/16/24
//mode:叠加方式(1)还是非叠加方式(0)
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
{
u8 temp,t1,t;
u16 y0=y;
u8 csize=(size/8+((size%8)?1:0))*(size/2); //得到字体一个字符对应点阵集所占的字节数
num=num-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
for(t=0;t<csize;t++)
{
if(size==12)
{
temp=asc2_1206[num][t]; //调用1206字体
}
else if(size==16)
{
temp=asc2_1608[num][t]; //调用1608字体
}
else if(size==24)
{
temp=asc2_2412[num][t]; //调用2412字体
}
else
{
return;
}
for(t1=0;t1<8;t1++)
{
if(temp&0x80)
{
LCD_Fast_DrawPoint(x,y,POINT_COLOR);
}
else if(mode==0)
{
LCD_Fast_DrawPoint(x,y,BACK_COLOR);
}
temp<<=1;
y++;
if(y>=lcddev.height)
{
return; //超区域了
}
if((y-y0)==size)
{
y=y0;
x++;
if(x>=lcddev.width)
{
return; //超区域了
}
break;
}
}
}
}
//m^n函数
//返回值:m^n次方.
u32 LCD_Pow(u8 m,u8 n)
{
u32 result=1;
while(n--)
{
result *= m;
}
return result;
}
//显示数字,高位为0,则不显示
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//color:颜色
//num:数值(0~4294967295);
void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
{
u8 t,temp;
u8 enshow=0;
for(t=0;t<len;t++)
{
temp=(num/LCD_Pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
LCD_ShowChar(x+(size/2)*t,y,' ',size,0);
continue;
}else enshow=1;
}
LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,0);
}
}
//显示字符串
//x,y:起点坐标
//width,height:区域大小
//size:字体大小
//*p:字符串起始地址
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)
{
u8 x0 = x;
width += x;
height += y;
while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
{
if(x >= width)
{
x = x0;
y+=size;
}
if(y >= height)
break;//退出
LCD_ShowChar(x,y,*p,size,0);
x+=size/2;
p++;
}
}
//开机菜单
void Dsp_On(void)
{
POINT_COLOR = RED;
LCD_ShowString(10,10,200,24,24,"temperature:");
POINT_COLOR = WHITE;
LCD_ShowxNum(10,40,Temproom,3,24,0);
LCD_ShowChar(50,40,'C',24,0);
POINT_COLOR = RED;
LCD_ShowString(10,80,200,24,24,"humidity:");
POINT_COLOR = WHITE;
LCD_ShowxNum(10,110,Humi,3,24,0);
LCD_ShowChar(50,110,'%',24,0);
POINT_COLOR = RED;
LCD_ShowString(10,150,200,24,24,"light:");
POINT_COLOR = WHITE;
LCD_ShowxNum(10,180,Light,3,24,0);
LCD_ShowChar(50,180,'%',24,0);
}
//设置菜单
void Dsp_Setup(void)
{
POINT_COLOR = RED;
LCD_ShowString(10,10,200,24,24,"Setup: ");
POINT_COLOR = WHITE;
LCD_ShowxNum(10,40,TempMax,3,24,0);
LCD_ShowChar(46,40,'C',24,0);
POINT_COLOR = BLUE;
LCD_ShowString(10,80,200,24,24," ");
POINT_COLOR = BLUE;
LCD_ShowxNum(10,110,Humi,3,24,0);
LCD_ShowChar(46,110,'%',24,0);
POINT_COLOR = BLUE;
LCD_ShowString(10,150,200,24,24,"light:");
POINT_COLOR = BLUE;
LCD_ShowxNum(10,180,Light,3,24,0);
LCD_ShowChar(46,180,'%',24,0);
}
//显示任务
void DisplayTask(void)
{
if(WorkState == WORK_STATE_NORMAL)
{
Dsp_On();
}
else
{
Dsp_Setup();
}
}
3.4蜂鸣器驱动程序设计
当温度超过范围时,蜂鸣器鸣响,提醒管理人员。蜂鸣器是4KHz无源蜂鸣器,需要4KHz方波驱动。设计采用125US定时器定时翻转IO口电平输出4KHz方波。蜂鸣器输入输出口需要初始化,配置推挽输出功能。
代码:
void Buzz_io_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //LED0-->PA.4 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA.8
GPIO_ResetBits(GPIOA,GPIO_Pin_4); //PA.5 输出高
}
蜂鸣器功能比较简单,就是报警状态,蜂鸣器响,其他状态蜂鸣不响。图是蜂鸣器报警功能流程图。
程序代码:
//设置蜂鸣器响时间
void User_SetBeepTime(void)
{
TimerBeepOn = TIMER_BEEP_ON;
}
//蜂鸣器响时间计算
void User_BeepTick(void)
{
if(TimerBeepOn)
{
TimerBeepOn--;
}
}
//蜂鸣器响任务
void User_BeepTask(void)
{
if(TimerBeepOn)
{
if(BeepState)
{
BeepState = 0;
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
}
else
{
BeepState = 1;
GPIO_SetBits(GPIOA,GPIO_Pin_4);
}
}
else
{
BeepState = 0;
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
}
}
//初始化
void User_BeepInit(void)
{
TimerBeepOn = 0;
Buzz_io_init();
}
4.5光敏电阻程序设计
光敏电阻对可见光敏感,当没有光照时,电阻阻值很大,一般是几百千欧到几兆欧,当有光照时,电阻值下降,光照越强阻值越小,最小只有一点几千欧,通过光敏电阻阻值,可以得到光照强度。
STM32F103单片机内部有12位AD转换器,所以采用内部转换器。AD转换功能需要初始化配置AD转换器。否则无法使用其功能。由于光敏电阻输入信号连接在PA3,所以配置通道3为AD输入。
程序代码:
//初始化ADC
//我们将开启通道3
void Adc_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA3 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
//ADC_ResetCalibration(ADC1); //使能复位校准
//while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
//ADC_StartCalibration(ADC1); //开启AD校准
//while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
// ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
}
AD初始化完成后,就读取AD值并计算信号强度计算光照。图是光敏电阻AD转换和计算流程图。
程序代码:
//获得ADC值
//ch:通道值 3
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}
//取得光照度
u16 lightAD;
void Read_LightAD(void)
{
lightAD = Get_Adc(ADC_Channel_3);
if(lightAD > LIGHT_AD_0)
{
Light = 0;
}
else if(lightAD > LIGHT_AD_25)
{
Light = 25;
}
else if(lightAD > LIGHT_AD_50)
{
Light = 50;
}
else if(lightAD > LIGHT_AD_75)
{
Light = 75;
}
else
{
Light = 100;
}
}
四、系统调试测试与分析
4.1电路仿真
Proteus软件是英国Lab Center Electronics公司出版的EDA工具软件。它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是比较好的仿真单片机及外围器件的工具。所以本设计采用Proteus仿真。由于使用版本没有DHT11温湿度传感器和单片机没有AD转换功能,所以湿度和光照没有仿真。TFT LCD用12864点阵LCD代替。
1.调节18B20温度传感器32度,LCD显示32度,系统功能正常。
2.调节18B20温度传感器39度,LCD显示39度,系统功能正常。
4.2硬件电路焊接
用电烙铁将单片机、DHT11温湿度传感器、光敏电阻、LED灯、液晶显示及电容、蜂鸣器、按键等器件焊接在电路板上,实物如图所示。
4.3系统调试
通过仿真器连接电脑与单片机,将C程序下载到单片机内,上电后,单片机正常工作,如图: