基于51单片的光控温控红外控制

基于51单片的光控温控红外控制

主要功能

红外遥控,开灯关灯,调风扇的速度。
自动调光,自动温度调速。
蜂鸣器报警风速极限。液晶屏显示温度数值与光敏电阻电压数值。

电路

在这里插入图片描述
电路设计
在这里插入图片描述

程序

main.c文件

// An highlighted block
/*-------------------------------------------------------------------                                                            
程序名称:   在1602液晶上显示出DS18B20的温度与光敏电阻电压
						自动功能:									|	手动功能:
						根据温度的数值控制风速			|	红外控制风速
						根据光的亮暗控制光线的强弱	|	红外控制灯的亮暗
-------------------------------------------------------------------*/
#include <reg52.h>      
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define P0 P0
sbit ds=P2^2;        //定义DS18B20通信端口
sbit lcd_rs = P3^5;  //定义LCD控制端口
sbit lcd_rw = P3^6;
sbit lcd_en = P3^4;
sbit IN1=P1^0;       //电机
sbit M_pwm=P1^1; 
sbit fm=P2^4;
sbit ir=P3^2;        //红外
sbit led=P1^2;       //台灯

sbit led1=P2^0;      //风扇指示灯
sbit led2=P2^1;			 //台灯指示灯

sbit CS=P2^7;        //AD芯片的定义口
sbit CLK=P2^5;
sbit DIO=P2^6;

uint temp,temp1;          //温度值定义
bit flag;						 //温度中的标志位

uchar code mun_to_char[] = {"0123456789ABCDEF"};  //定义数字跟ASCII码的关系
uchar data lcd1602_line1[]={"MODE:0  LIGHT:0 "};     //LCD1602液晶第一行
uchar data lcd1602_line2[]={"TEMP:00.0 U:0.0 "};  //LCD1602液晶第二行。注意:用空格补位
            
uint AD_val;               //电压值

uchar irtime;										//用于计数时间
uchar ircode[4];								//储存数据码
uchar irdata[33];								//1引导码 8位客户1 8位客户2 8位操作码 8位操作反码 
bit startflag,irok,irprosok;    //设置中断标志位 接收成功标志位 处理成功标志
uchar  bitnum;									//位数值

uchar num,pwm1,n,num2;
uint pwm2;
/*------------------------------------------------------------------------------
                                      延时函数
------------------------------------------------------------------------------*/

void delayus(uint t)   //微秒级的延时函数
{
	while(t--);
}

void delayms(uint ms)    //毫秒级的延时函数
{
	uchar i;
	while(ms--)
	{
		for(i=0;i<120;i++);
	}
}
/*------------------------------------------------------------------------------
																			AD转换
------------------------------------------------------------------------------*/

unsigned char AD(void)
{
	unsigned char i,dat;
	CS=1;                      //一个转换周期开始
	CLK=0;                     //第一个脉冲做准备
	CS=0;                      //CS置0,片选有效
	DIO=1;                     //规定的起始信号
	CLK=1;                     //第一个脉冲
	CLK=0;                     //第一个脉冲下降沿,此前DIO必须是高电平
	DIO=1; 										 //DIO置1,通道选择信号
	CLK=1;									   //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别的输入两位数据用于选则通道
	CLK=0;                     //第二个脉冲下降沿
	DIO=0;										 //DI置0,选择通道0
	CLK=1;										 //第三个脉冲
	CLK=0;										 //第三个脉冲下降沿
	DIO=1;										 //第三个脉冲下沉之后,输入端DIO失去作用,应置1
	CLK=1; 										 //第四个脉冲
	for(i=0;i<8;i++)
	{
		CLK=1;                   //第四个脉冲
    CLK=0;	
		dat<<=1;                 //将下面储存的低位数据向右移
		dat|=(unsigned char)DIO; //将输出数据DIO通过或运算储存在dat最低位
	}
	
	CS=1;                      //片选无效
	return dat;                //将读出的数据返回
}
/*------------------------------------------------------------------------------
                                蜂鸣器
------------------------------------------------------------------------------*/
void bee()                 
{
	fm=0;
	delayms(100);
	fm=1;
	delayms(100);
}

/*------------------------------------------------------------------------------
                               红外遥控
------------------------------------------------------------------------------*/

void timer0init(void)//定时器0初始化 256*(1/12m)*12=0.256ms
{

  TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
  TH0=0x00; //重载值
  TL0=0x00; //初始化值
  ET0=1;    //开中断
  TR0=1;    
}
/
//定时器0中断服务函数
/

void tim0_isr (void) interrupt 1 using 1  //定时器0中断服务函数
{
  irtime++;  //用于计数2个下降沿之间的时间
	num++;
	num2++;
	if(num>62)
	{
		num=0;
	}
	if(num<=pwm1)
	{
		M_pwm=1;
	}
	else
	{
		M_pwm=0;		
	}
}

void int0init(void)  //外部中断0初始化
{
 IT0 = 1;   //指定外部中断0下降沿触发,INT0 (P3.2)
 EX0 = 1;   //使能外部中断
 EA = 1;    //开总中断
}


void int0 () interrupt 0 //外部中断0服务函数
{
if(startflag)
 {
  if(irtime>32&&irtime<63)  //8-16ms
	{
	   bitnum=0;
	}
	irdata[bitnum]=irtime;
	irtime=0;
	bitnum++;
	if(bitnum==33)
	  {
	   bitnum=0;
	   irok=1;
	  }
 }
  else
 {
	 irtime=0;
	 startflag=1;
 }
}

/*------------------------------------------------------------------------------
                                 红外码值处理
------------------------------------------------------------------------------*/

void irpros(void) // 红外码值处理
{
	uchar mun,k,i,j;
	k=1;
	for(j=0;j<4;j++)
	{
		for(i=0;i<8;i++)
		{
			mun=mun>>1;
			if(irdata[k]>6)
			{
				mun=mun | 0x80;
			}
				k++;
		}
		ircode[j]=mun;
	}
	irprosok=1;
}

/*------------------------------------------------------------------------------
                                   PWM控制
------------------------------------------------------------------------------*/
 
void temp_pwm()
{
	
	if(n==1)
	{
		 lcd1602_line1[6] = mun_to_char[1];
			if(pwm1<62)
			{ 
				IN1=1;
				pwm1++;
				delayms(100);
			}
			else
			{
				bee();
			}
		
	}
		if(n==3)    
	 {
		lcd1602_line1[6] =mun_to_char[2] ;
			if(pwm1>1)
			{
				IN1=1;
				pwm1--;
				delayms(100);
			}
			else
			{
				bee();
			}
  	}	
		if(n==5)    //停止 
		{
			
			led1=1;
			IN1=0;
			pwm1=0;
		}
	if(n==2)
	{		
		pwm1=31;
	  delayms(100);		
	}

}
void led_pwm()
{
		if(n==6)
	{
		lcd1602_line1[14] =mun_to_char[1] ;
		if(pwm2<800)
		{
		 pwm2++;
		 delayms(100);
		}
	}
	else
	{
		bee();
	}
	if(n==7)
	{
		lcd1602_line1[14] =mun_to_char[2] ;
		if(pwm2>1)
		{
		 pwm2--;
		delayms(100);
		}
	}
	else
	{
		bee();
	}
}
/*------------------------------------------------------------------------------
																	红外键值处理
------------------------------------------------------------------------------*/
void ir_work(void)    //红外键值处理
{
	switch(ircode[2])   //判断操作码(第三个数码值)
	{
			
			 case 0x19:bee();break;          //      0
			 case 0x45:n=1;temp_pwm();break; //加速  1
			 case 0x47:n=3;temp_pwm();break; //减速  3
			 case 0x46:n=2;temp_pwm();break; //复位  2
			 case 0x1c:n=4;break; 					 //自动模式 ok
			 case 0x44:n=5;break;            //关闭点击     4
			 case 0x07:led=0;break;					 //关灯  8
			 case 0x15:led=1;break;					 //开灯  7
			 case 0x08:n=6;led_pwm();break; //调亮  <
		   case 0x5a:n=7;led_pwm();break; //调亮  >
			 case 0x16:n=8;break;  					//自动      *
             default:break;
		}
		  irprosok=0;                      //处理完成标志
  }

/*------------------------------------------------------------------------------
	                             单总线初始化函数(温度)
------------------------------------------------------------------------------*/

void ds_reset()    //单总线初始化函数
{
	ds=1;           
	delayus(5);     
	ds=0;          
	delayus(80);    
	ds=1;          
	delayus(14);    
	if(ds==0)      
		flag=1;    
	else
		flag=0;    
	delayus(20);
}
/*------------------------------------------------------------------------------
															读时隙(即位读取)函数 (温度)			
------------------------------------------------------------------------------*/
bit ds_read_bit()     //读时隙(即位读取)函数
{
	bit dat;        
	ds=0;        
	_nop_();       
	_nop_();       
	ds=1;        
	_nop_();     
	dat=ds;       
	delayus(10);  
	return dat;    
}

/*------------------------------------------------------------------------------
															 读一个字节函数
------------------------------------------------------------------------------*/
uchar ds_read_byte()   //读一个字节函数
{
	uchar i,j,k;
	for(i=0;i<8;i++)   
	{
		j=ds_read_bit();   
		k=(j<<7)|(k>>1);  
	}
	return k;  
}
/*------------------------------------------------------------------------------
														    写一个字节函数
------------------------------------------------------------------------------*/
void ds_write_byte(uchar dat)   //写一个字节函数
{
	uchar i;
	for(i=0;i<8;i++)      
	{
		ds=0;          
		_nop_();        
		ds=dat&0x01;    
		delayus(6);     
		ds=1;         
		dat=dat>>1;     
	}
		delayus(6);    
}
/*------------------------------------------------------------------------------
														   读取温度函数
------------------------------------------------------------------------------*/

uint read_temperature()   //读取温度函数
{
	
	uchar a,b;
	ds_reset(); 
  EA=0;	
	ds_write_byte(0xcc);   
	ds_write_byte(0xbe);   
	a=ds_read_byte();    
	b=ds_read_byte();   
	temp=b;
	temp=temp<<8;
	temp=temp|a;      
	    temp=temp*0.0625*10+0.5; 
  EA=1;	
	return temp;  

}


/*------------------------------------------------------------------------------
														 1602液晶显示
------------------------------------------------------------------------------*/

void lcd_delay(uchar x) //LCD1602 延时
{
	uint i,j;
    for(i=x;i>0;i--)
	{
		for(j=120;j>0;j--);
	}
}
/*------------------------------------------------------------------------------
														LCD1602 命令字写入
------------------------------------------------------------------------------*/

void write_com(uchar com) //LCD1602 命令字写入
{
    lcd_rs = 0;
    lcd_rw = 0;
    lcd_en = 0;
    P0 = com;
    lcd_en = 1;
	  lcd_delay(5);
    lcd_en = 0;     
}

/*------------------------------------------------------------------------------
														 LCD1602 初始化
------------------------------------------------------------------------------*/

void lcd_init()       //LCD1602 初始化
{
    write_com(0x38);
    write_com(0x08);
    write_com(0x01);
    write_com(0x06);
    write_com(0x0c);  //开显示,不显示光标
}

/*------------------------------------------------------------------------------
														 LCD1602 字符写入
------------------------------------------------------------------------------*/

void lcd_char_write(uchar x_pos,y_pos,lcd_dat) //LCD1602 字符写入
{
    x_pos &= 0x0f; // X位置范围 0~15
    y_pos &= 0x01; // Y位置范围 0~ 1
    if(y_pos==1) x_pos += 0x40;
    x_pos += 0x80;
    write_com(x_pos);
	lcd_delay(5);
    lcd_rs = 1;
    lcd_rw = 0;
    lcd_en = 0;
    P0 = lcd_dat;
    lcd_en = 1;
    lcd_en = 0; 
	P0 = 0xff;                 //释放数据端口
}

void main()
{
	uchar i;
	float adnum;
	lcd_en=0;                  //关闭1602液晶使能,防止1602数据端影响单片机P0口输出
	led=0;	
	P0=0xff;
	int0init();                //外部中断初始化
  timer0init();              //定时器初始化
	pwm2=400;
	num=0;
	pwm1=31;
	lcd_init();                //LCD1602 初始化

	
  while(1)
  {
			ds_reset();            //单总线初始化
			ds_write_byte(0xcc);   //跳线ROM
			ds_write_byte(0x44);   //启动温度传换
		  AD_val=AD();					 //读取电压的数值
			temp1=read_temperature(); //读取当前温度值
			lcd1602_line2[5] = mun_to_char[temp1/100];   //把当前温度分解送到1602显示
			lcd1602_line2[6] = mun_to_char[temp1%100/10];
			lcd1602_line2[8] = mun_to_char[temp1%10]; 
		  lcd1602_line2[12] = mun_to_char[AD_val/51];
			lcd1602_line2[14] = mun_to_char[((AD_val%51)*100/51)/10]; 
			lcd1602_line2[15] = mun_to_char[((AD_val%51)*100/51)%10]; 
			for(i=0;i<16;i++) lcd_char_write(i,0,lcd1602_line1[i]);
	  	for(i=0;i<16;i++) lcd_char_write(i,1,lcd1602_line2[i]);
//			
//			if(temp1>260&&temp1<350) IN1=1;
//			else IN1=0;
		if(n==4)
		{
			lcd1602_line1[5] = mun_to_char[1];
			lcd1602_line1[6] =mun_to_char[0] ;
			led1=0;
				if(temp1>250&&temp1<280) pwm1=31;
				if(temp1>290&&temp1<310) pwm1=40;
				if(temp1>310&&temp1<350) pwm1=50;
				if(temp1>10&&temp1<200)  pwm1=20;
		}
		if(n==5)
		{
			lcd1602_line1[5] = mun_to_char[2];
			lcd1602_line1[6] =mun_to_char[0] ;
			led1=1;
			IN1=0;
			pwm1=2;
		}
		adnum=(AD_val/51);
		if(n==8)
		{
			if(adnum>3&&adnum<5){led=1;led2=0;}
			if(adnum>0&&adnum<2){led=0;led2=1;}	
		}
			
			if(irok==1)             //如果红外编码接收好了,
	    {   
				irpros();             //进行红外码值处理。
				irok=0;
	    }
  
    if(irprosok==1)           //如果红外码值处理好后,
	  {
	   ir_work();               //进行工作处理。
  	}
	}
}




.h文件

/*--------------------------------------------------------------------------
INTRINS.H

Intrinsic functions for C51.
Copyright (c) 1988-2010 Keil Elektronik GmbH and ARM Germany GmbH
All rights reserved.
--------------------------------------------------------------------------*/

#ifndef __INTRINS_H__
#define __INTRINS_H__

#pragma SAVE

#if defined (__CX2__)
#pragma FUNCTIONS(STATIC)
/* intrinsic functions are reentrant, but need static attribute */
#endif

extern void          _nop_     (void);
extern bit           _testbit_ (bit);
extern unsigned char _cror_    (unsigned char, unsigned char);
extern unsigned int  _iror_    (unsigned int,  unsigned char);
extern unsigned long _lror_    (unsigned long, unsigned char);
extern unsigned char _crol_    (unsigned char, unsigned char);
extern unsigned int  _irol_    (unsigned int,  unsigned char);
extern unsigned long _lrol_    (unsigned long, unsigned char);
extern unsigned char _chkfloat_(float);
#if defined (__CX2__)
extern int           abs       (int);
extern void          _illop_   (void);
#endif
#if !defined (__CX2__)
extern void          _push_    (unsigned char _sfr);
extern void          _pop_     (unsigned char _sfr);
#endif

#pragma RESTORE

#endif


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值