主要功能
红外遥控,开灯关灯,调风扇的速度。
自动调光,自动温度调速。
蜂鸣器报警风速极限。液晶屏显示温度数值与光敏电阻电压数值。
电路
程序
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