#单片机#一个小型的单片机控制系统——智能窗帘控制系统

介绍

涉及模块:

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&&current>=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;
}

末尾献上可运行资源,需要自取

在这里插入图片描述在这里插入图片描述在这里插入图片描述
戳这里

  • 11
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值