#物联网#一个小型的物联网系统——智能窗帘控制系统
程序员文章站
2022-03-13 17:32:36
...
介绍
涉及模块:
1.LCD1602液晶屏
2.DS18B20温度传感器
3.ADC0832数模转换芯片
4.TORCH_LDR光照度控件
5.步进电机
实现功能:
1.在LCD上显示实时温度与窗帘状态。
2.温度在15~25℃范围内开窗帘,范围外关窗帘。
3.光线强时关窗帘,光线弱时开窗帘。
4.可通过按钮手动开关窗帘。
仿真图
窗帘系统Proteus仿真图:
代码
项目由以下6个文件组成 :
main.c
#include <reg52.h>
#include <intrins.h>
#include "define.h"
#include "delay.h"
#include "LCD1602.h"
#include "DS18B20.h"
#include "ADC0832.h"
void main()
{
//开启T0中断
EA = 1;
ET0 = 1;
ET1 = 1;
//设置T0
TMOD = 0X01;
TH0 = 0XFFED;
TL0 = 0XFFFF;
TR0 = 1;
LCD_init();
while(1)
{
DS_read_temperature();
display_temperature();
LightIntensity(ADC0832());
// LCD_write_data(Temp_AD);//在LCD上显示光照强度的数值
if(flag)
{
//关窗
if(status==0||Temp_AD<=Standard)
{
for(;i<sizeof(Run);i++)
{
P2 = Run[i];
delayms(RunSpeed);
}
}
//开窗
else
{
for(;i>0;i--)
{
P2 = Run[i];
delayms(RunSpeed);
}
}
}
}
}
//定时器0中断服务
void InterruptTimer() interrupt 1
{
TH0 = 0XFFED;
TL0 = 0XFFFF;
if (key1==0)
{ //顺时钟
flag=0;
for(;i<sizeof(Run);i++)
{
P2 = Run[i];
delayms(RunSpeed);
}
}
if (key2==0)
{ //逆时钟
flag=0;
for(;i>0;i--)
{
P2 = Run[i];
delayms(RunSpeed);
}
}
}
define.h
#ifndef _DEFINE_H_
#define _DEFINE_H_
#define uchar unsigned char
#define uint unsigned int
sbit RS=P2^6;
sbit RW=P2^5;
sbit EN=P2^7;
sbit DQ=P3^3;
sbit CLK=P3^1;
sbit CS=P3^0;
sbit DO=P3^2;
bit DS_OK=1;
sbit key1 = P1^0; //开关开窗帘
sbit key2 = P1^1; //开关关窗帘
uchar code Run[]={
0x00,0x01,0x03,0x02,0x06,0x04,0x0C,0x08,0x09,0xff};
uchar RunSpeed = 60;
uchar status=0;
uchar i=0;
uchar Temp_AD=0;//现在的光照强度
uchar Standard='F';//光照强弱临界值
bit flag=1; //手动模式/自动模式的标志
uchar CurtainStatu[]={" STATE : "};
uchar buffer_line2[]={" Temp: C "};
uchar code df_tab[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
uchar current=0;
uchar display_digit[]={0,0,0,0};
uchar temp_value[]={0x00,0x00};
uchar back_temp_value[]={0x00,0x00};
char alarm_HL[]={70,-10};
char sign_temp;
bit LO_alarm=0;
bit HI_alarm=0;
#endif
delay.h
#ifndef _DELAY_H_
#define _DELAY_H_
void delay(uint z)
{
uint x;
while(z--)
for(x=50;x>0;x--);
}
void delay0(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=0;y<10;y++);
}
void delay1(uint y)
{
uint x;
while(y--)
for(x=4500;x>0;x--);
}
void delayms(uchar x)
{
int i,j;
for(i=x;i>0;i--)
for(j=0;j<120;j++);
}
void delay_us()
{_nop_();_nop_();
_nop_();_nop_();}
void delay_1us(uint x) //延时
{
while(--x);
}
#endif
DS18B20.h
#ifndef _DS18B20_H_
#define _DS18B20_H_
#include "define.h"
#include "DELAY.H"
#include "LCD1602.h"
#include <string.h>
/*****************************************************/
/************全局都要精确延时************************/
uchar DS_init()
{
uchar state;
DQ=1;
delay_1us(8);
DQ=0;
delay_1us(80); //精确延时大于4800US
DQ=1;
delay_1us(8);
state=DQ;
delay(100); //延时
return state; //返回值为1时,初始化失败
}
void DS_write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
if((dat&0x01)==0) //写一
{
DQ=0;
delay_1us(5);
DQ=1; //精确延时,形成脉冲
}
else //写0
{
DQ=0;
delay_1us(1);
DQ=1;
delay_1us(4);
}
dat>>=1;
}
}
uchar DS_read_byte()
{
uchar i,dat=0;
for(i=0;i<8;i++)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ==1)
dat|=0x80;
else
dat|=0x00;
delay_1us(30);
DQ=1;
}
return dat;
}
void DS_read_temperature()
{
if(DS_init()==1) //返回值为1时
DS_OK=0; //DS_ok=0代表失败
else
{
DS_init();
DS_write_byte(0xcc);//跳过***
DS_write_byte(0x44); //启动温度转换
DS_init();
DS_write_byte(0xcc);
DS_write_byte(0xbe);//启动读取温度
temp_value[1]=DS_read_byte(); //先写低位在写高位
temp_value[0]=DS_read_byte();
DS_OK=1;
}
}
void display_temperature()
{
uchar flag=0;
if((temp_value[0]&0xf8)==0xf8)
{
flag=1;
temp_value[0]=~temp_value[0];
temp_value[1]=~temp_value[1]+1;
if(temp_value[1]==0x00)
temp_value[0]++;
}
display_digit[3]=df_tab[temp_value[1]&0x0f];//取小数
//取整数
current=((temp_value[0]&0x07)<<4)|((temp_value[1]&0xf0)>>4);
if(current<=25&¤t>=15)
status=1;//15~25°C开窗帘
else
status=0;//范围之外关窗帘
//判断正负
sign_temp=flag?-current:current;
LO_alarm=sign_temp<=alarm_HL[1]?1:0;
HI_alarm=sign_temp>=alarm_HL[0]?1:0;
/*********分解整数*************************************/
display_digit[0]=current/100;
display_digit[1]=current%100/10;
display_digit[2]=current%10;
/****装入缓冲*********************************************/
buffer_line2[8]=display_digit[0]+'0';
buffer_line2[9]=display_digit[1]+'0';
buffer_line2[10]=display_digit[2]+'0';
buffer_line2[11]='.';
buffer_line2[12]=display_digit[3]+'0';
/*********屏蔽高位不显示*******************************/
if(display_digit[0]==0)
buffer_line2[8]=' ';
if(display_digit[0]==0&&display_digit[1]==0)
buffer_line2[9]=' ';
if(flag==1)
{
if(buffer_line2[9]==' ')
buffer_line2[9]='-';
else
{
if(buffer_line2[8]==' ')
buffer_line2[8]='-';
else
buffer_line2[7]='-';
}
}
if (i==0)
strcpy(CurtainStatu," STATE : OPEN ");
else if(i==sizeof(Run))
strcpy(CurtainStatu," STATE : CLOSE ");
LCD_write_cmd(0x00);
LCD_display(0x00,CurtainStatu);
LCD_display(0x40,buffer_line2);
LCD_write_cmd(0x80+0x4d);
LCD_write_data(0x00);
LCD_write_cmd(0x80+0x4e);
LCD_write_data('C');
}
#endif
LCD1602.h
#ifndef _LCD1602_H_
#define _LCD1602_H_
uchar LCD_check_busy()
{
uchar state;
RS=0;
RW=1;
delay(2);
EN=1;
state=P0;
delay(2);
EN=0;
delay(2);
return state;
}
void LCD_write_cmd(uchar cmd)
{
while((LCD_check_busy()&0x80)==0x80);
RS=0;
RW=0;
delay(2);
EN=1;
P0=cmd;
delay(2);
EN=0;
delay(2);
}
void LCD_write_data(uchar dat)
{
while((LCD_check_busy()&0x80)==0x80);
RS=1;
RW=0;
delay(2);
EN=1;
P0=dat;
delay(2);
EN=0;
delay(2);
}
void LCD_display(uchar position,uchar *s)
{
uchar i;
LCD_write_cmd(0x80+position);
for(i=0;i<16;i++)
{
LCD_write_data(s[i]);
}
}
void LCD_init()
{
LCD_write_cmd(0x38);
LCD_write_cmd(0x0c);
LCD_write_cmd(0x06);
LCD_write_cmd(0x01);
}
#endif
ADC0832.h
#ifndef _ADC0832_H_
#define _ADC0832_H_
uchar ADC0832()
{
uchar i,temp;
CLK=0;
CS=0;//选中AD芯片
delay0(1);
DO=1;//发送bit1 说明开始转换
CLK=1;//一个上升沿 将开始位输出ADC0832
delay0(1);
CLK=0;
DO=1;
delay0(1);
CLK=1;
delay0(1);
CLK=0;
DO=0;
delay0(1);
CLK=1;
delay0(1);
CLK=0;
DO=1;
for(i=8;i>0;i--)
{
CLK = 1;
delay(1);
CLK=0;
delay(1);
temp|=DO;
if(DO)
temp++;
temp<<1;
}
CS=1;//释放芯片
return temp;//返回读回来的数值
}
void LightIntensity(unsigned char num1)
{
//ad在光度强的时候采集回来的电压是小的数值
//为了方便显示用255将其取反,为光度越强的时候数值越大
//保留实际ad的数值 比如ad50的时候对应80
//转换为更100有关的高度
num1=num1/2.55;
Temp_AD=100-num1;
}
末尾献上可运行资源,需要自取:
上传ing
上一篇: 51单片机第二讲(定时器中断)