#include<reg51.h>
#include<stdlib.h>
#include<stdio.h>//头文件
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P2^6;//ds18b20与单片机连接口
sbit PWM=P2^5;//控制信号的输出
unsigned char code str[]={"my name is zhb "};
unsigned char code str_[]={"MADE IN NUPT... "};
unsigned char code str1[]={"temper:"};
unsigned char code str2[]={" "};
unsigned char code nul[]={" "};
unsigned char code str3[]={"target: "};
unsigned char str4[6];//设定温度的存储
uchar data disdata[5];
uchar a[4]={0,0,0,0},j,i,k,num=0; //定义变量
sbit js=P3^2; //红外接收端
uchar zhb_flag=0;//保证一次解码,只执行一次代码
uint tvalue;//温度值
uchar tflag;//温度正负标志
uint count=0;//按键次数初始化为0
uint number=4;//暂时规定输入的温度为xx.x的形式
uchar j,key;
uint time_flag=0;
bit enterflag=0;// 确认键按下与否标志
uint new_t; //转化后的十进制实时温度
uint target=0;//转化后的十进制的目标温度---有键盘输入
//------------定义接口-------------//
sbit RS=P2^2 ;
sbit RW=P2^3 ;
sbit E=P2^4;
sbit PSB= P2^5; //H=并口; L="串口";
#define Lcd_Bus P0
// P0 接 LCM
#define uchar unsigned char
#define FIRST_ADDR 0
//定义字符/汉字显示起始位置
/*------------------检查忙位-----------------------------*/
void chk_busy()
{
RS=0 ;
RW=1 ;
E=1 ;
Lcd_Bus=0xff ;
while((Lcd_Bus&0x80)==0x80);
E=0 ;
}
/*------------------延时子程序-----------------------------*/
void lcd_delay(unsigned int t)
{
unsigned int i,j ;
for(i=0;i<t;i++)
for(j=0;j<10;j++);
}
/*------------------写命令到LCD------------------------------*/
void write_com(unsigned char cmdcode)
{
chk_busy();
RS=0 ;
RW=0 ;
E=1 ;
Lcd_Bus=cmdcode ;
lcd_delay(5);
//------------------在数据写入的时候加入适当的延时
E=0 ;
lcd_delay(5);
}
/*-------------------写数据到LCD----------------------------*/
void write_data(unsigned char Dispdata)
{
chk_busy();
RS=1 ;
RW=0 ;
E=1 ;
Lcd_Bus=Dispdata ;
lcd_delay(5);
//------------------在数据写入的时候加入适当的延时
E=0 ;
lcd_delay(5);
}
/*------------------初始化LCD屏--------------------------*/
void lcdreset()
{
PSB = 1;
lcd_delay(2000);
write_com(0x30);
lcd_delay(10);
//选择基本指令集
write_com(0x30);
//选择8bit数据流
lcd_delay(5);
write_com(0x0c);
//开显示(无游标、不反白)
lcd_delay(10);
write_com(0x01);
//清除显示,并且设定地址指针为00H
lcd_delay(500);
write_com(0x06);
//指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位
lcd_delay(0);
}
/*------------------显示字符串--------------------------*/
void hzkdis(unsigned char code*s)
{
while(*s>0)
{
write_data(*s);
s++;
lcd_delay(50);
}
}
/*------------------首屏显示--------------------------*/
void ceshi()
{
write_com(0x01);
//清除显示,并且设定地址指针为00H
lcd_delay(5);
write_com(0x80);
//第一行(如果是地址是:80H,即LCD的第一行的第一个位置显示)
hzkdis("南京邮电大学");
write_com(0x90);
//第二行(如果是地址是:90H,即LCD的第二行的第一个位置显示)
hzkdis(str);
write_com(0x88);
//第三行(如果是地址是:88H,即LCD的第二行的第一个位置显示)
hzkdis("电子信息工程");
write_com(0x98);
//第四行(如果是地址是:98H,即LCD的第二行的第一个位置显示)
hzkdis("郑海波测试程序");
}
//------------------清整个GDRAM空间----------------------------
void clrgdram()
{
unsigned char x,y ;
for(y=0;y<64;y++)
for(x=0;x<16;x++)
{
write_com(0x34);
write_com(y+0x80);
//行地址
write_com(x+0x80);
//列地址
write_com(0x30);
write_data(0x00);
write_data(0x00);
}
}
//------------------------------------------------------------
void clrscreen()
{
write_com(0x01);
lcd_delay(10);
}
unsigned char ReadByte(void)
{
unsigned char byReturnValue ;
chk_busy();
Lcd_Bus=0xff ;
RS=1 ;
RW=1 ;
E=0 ;
E=1 ;
byReturnValue=Lcd_Bus ;
E=0 ;
return byReturnValue ;
}
/*增加画点子程序
函数功能:在坐标为(x,y)点画一个点
参数意义
X:12864屏幕的横坐标,范围是0到128(从左到右)
Y:12864的纵坐标,范围是0到64(从上到下)
Color:为1的时候表示为黑点
*/
void DrawPoint(unsigned char X,unsigned char Y,unsigned char Color)
{
unsigned char Row,Tier,Tier_bit ;
unsigned char ReadOldH,ReadOldL ;
write_com(0x34);
write_com(0x36);
Tier=X>>4 ;
Tier_bit=X&0x0f ;
if(Y<32)
{
Row=Y ;
}
else
{
Row=Y-32 ;
Tier+=8 ;
}
write_com(Row+0x80);
write_com(Tier+0x80);
ReadByte();
ReadOldH=ReadByte();
ReadOldL=ReadByte();
write_com(Row+0x80);
write_com(Tier+0x80);
if(Tier_bit<8)
{
switch(Color)
{
case 0 :
ReadOldH&=(~(0x01<<(7-Tier_bit)));
break ;
case 1 :
ReadOldH|=(0x01<<(7-Tier_bit));
break ;
case 2 :
ReadOldH^=(0x01<<(7-Tier_bit));
break ;
default :
break ;
}
write_data(ReadOldH);
write_data(ReadOldL);
}
else
{
switch(Color)
{
case 0 :
ReadOldL&=(~(0x01<<(15-Tier_bit)));
break ;
case 1 :
ReadOldL|=(0x01<<(15-Tier_bit));
break ;
case 2 :
ReadOldL^=(0x01<<(15-Tier_bit));
break ;
default :
break ;
}
write_data(ReadOldH);
write_data(ReadOldL);
}
write_com(0x30);
}
void send_to_pc(void)
{
uint pc_flag=0;
SCON=0x50;//串口方式1,允许接收
TMOD=0x20;//定时器1,定时方式2
TCON=0x40;//设定时器1开始计数
TH1=0xE8;//11.0592MHz, 1200波特率
TL1=0xE8;
TI=1;
TR1=1;
while(1)
{
if(pc_flag==1)
{
TMOD=1;
}
else
{
printf("Now temperture is ");
printf(disdata);
printf("*0.1 C");
pc_flag++;
}
}
}
void delay_18B20(unsigned int i)//延时1微秒
{
while(i--);
}
void ds1820rst()/*ds1820复位*/
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(4); //延时
DQ = 0; //DQ拉低
delay_18B20(100); //精确延时大于480us
DQ = 1; //拉高
delay_18B20(40);
}
uchar ds1820rd()/*读数据*/
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; //给脉冲信号
dat>>=1;
DQ = 1; //给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
void ds1820wr(uchar wdata)/*写数据*/
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = wdata&0x01;
delay_18B20(10);
DQ = 1;
wdata>>=1;
}
}
read_temp1()/*读取温度值并转换*/
{
ds1820rst();
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0x44);//*启动温度转换*/
ds1820rst();
}
read_temp2()
{
uchar a,b;
ds1820wr(0xcc);//*跳过读序列号*/
ds1820wr(0xbe);//*读取温度*/
a=ds1820rd();
b=ds1820rd();
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
if(tvalue<0x0fff)
tflag=0;
else
{
tvalue=~tvalue+1;
tflag=1;
}
tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数
return(tvalue);
}
/*******************************************************************/
void ds1820disp1()//温度值显示
{
uchar flagdat;
disdata[0]=tvalue/1000+0x30;//百位数
disdata[1]=tvalue%1000/100+0x30;//十位数
disdata[2]=tvalue%100/10+0x30;//个位数
disdata[3]=tvalue%10+0x30;//小数位
if(tflag==0)
flagdat=0x20;//正温度不显示符号
else
flagdat=0x2d;//负温度显示负号:-
if(disdata[0]==0x30)
{
disdata[0]=0x20;//如果百位为0,不显示
if(disdata[1]==0x30)
{
disdata[1]=0x20;//如果百位为0,十位为0也不显示
}
}
}
void ds1820disp2()
{
lcd_delay(5);
write_com(0x80);
hzkdis("温度为:");
lcd_delay(50);
write_com(0x84);
write_data(disdata[1]);
write_com(0x85);
write_data(disdata[2]);
write_com(0x86);
write_data(0x2e);
write_com(0x87);
write_data(disdata[3]);
lcd_delay(50);
new_t=disdata[1]*10+disdata[2];
}
void delay(uint us) //delay time
{
while(us--);
}
void HW_key(void)
{
if(zhb_flag==1)
{
if((a[2]+a[3])==0xff) //判断接收到数据是否正确
{
switch(a[2]) //将接受到的数据与所建表一一对应
{
case 0x00:
{
num=0;
if (count<number)
{
str4[count]='0';
count++;
}break;//数字键0
}
case 0x01:
{
num=1;
if (count<number)
{
str4[count]='1';
count++;
}break;//数字键1
}
case 0x02:
{
num=2;
if (count<number)
{
str4[count]='2';
count++;
}break;//数字键2
}
case 0x03:
{
num=3;
if (count<number)
{
str4[count]='3';
count++;
}break;//数字键3
}
case 0x04:
{
num=4;
if (count<number)
{
str4[count]='4';
count++;
}break;//数字键4
}
case 0x05:
{
num=5;
if (count<number)
{
str4[count]='5';
count++;
}break;//数字键5
}
case 0x06:
{
num=6;
if (count<number)
{
str4[count]='6';
count++;
}break;//数字键6
}
case 0x07:
{
num=7;
if (count<number)
{
str4[count]='7';
count++;
}break;//数字键7
}
case 0x08:
{
num=8;
if (count<number)
{
str4[count]='8';
count++;
}break;//数字键8
}
case 0x09:
{
num=9;
if (count<number)
{
str4[count]='9';
count++;
}break;//数字键9
}
case 0x0a:
{
num=10;
if (count<number)
{
str4[count]='.';
count++;
}break;//键"--/-"
}
case 0x0b:
{
num=11;
break;//键LG
}
case 0x0f:
{
num=12;break;//AV键
}
case 0x10:
{
num=13;
send_to_pc();break;//静音键
}
case 0x15:
{
num=14;
break;//开关键
}
case 0x16:
{
num=15;break;//选台键
}
case 0x17:
{
/*num=16;count = 0;//清零
for (j=0;j<number;j++)
{
str4[j]=' ';
}
str4[j]='/0';
PWM=1;
time_flag=0;
wr_com(0xcd);
display(nul);
target=0;
enterflag = 0;break;//睡眠键*/
}
case 0x1a:
{
num=17;break;//音量+
}
case 0x1b:
{
num=18;break;//频道+
}
case 0x1c:
{
num=19;break;//屏显
}
case 0x1e:
{
num=20;break;//音量-
}
case 0x1f:
{
num=21;break;//频道-
}
case 0x30:
{
num=22;break;//小键'-'
}
case 0x4e:
{
num=23;break;//小键'+'
}
case 0x51:
{
num=24;break;//画中画
}
case 0x56:
{
num=25;break;//图像,菜单
}
case 0x57:
{
num=26;break;//声音
}
case 0x5a:
{
num=27;break;//方向上
}
case 0x5b:
{
num=28;break;//方向右
}
case 0x5c:
{
num=29;
enterflag = 1;// 确认键按下
str4[count]='/0';break;//完成
}
case 0x5e:
{
num=30;break;//方向下
}
case 0x5f:
{
num=31;break;//方向左
}
default:break;
}
if (enterflag==1)// 如果按下确认键
{
//enterflag = 0; // 标志位置回0
/*wr_com(0xcd);
wr_dat(0xdf);
wr_dat(0x43);
target=str4[0]*10+str4[1];
time_flag=1;*/
}
/*wr_com(0xc0);
display(str3);
wr_com(0xc8);
display(str4);
zhb_flag=0;*/
}
}
}
/*void pitu_wave(void)
{
uchar i,a;
uchar colour=1;
for(i=0;i<128;i+=2)
{
a=64-new_t;
DrawPoint(i,a,colour);
}
}*/
/********************主程序***********************************/
void main()
{
uchar wave=0;
uchar i=0,a;
uchar colour=1;
RW=0 ;
lcdreset();
ceshi();
clrgdram();
delay(2000);
clrscreen();
EA=1; //初始化
ET0=1; //开计数中断0
EX0=1; //开外部中断0
TMOD=1; //设置工作方式
IT0=1; //启动计时器
while(1)
{
read_temp1();//读取温度
read_temp2();//读取温度
ds1820disp1();//显示
ds1820disp2();//显示
wave++;
if(wave>=10)
{
a=64-new_t;
if(i>=128)
{
i=0;
clrgdram();
delay(2000);
clrscreen();
}
DrawPoint(i++,a,colour);
wave=0;
}
HW_key();
}
}
void zhb(void) interrupt 0 // 外部中断子程序(译码过程)
{
zhb_flag=1;
TH0=0; //计数器清零
TL0=0;
TR0=1; //启动计数器
while(!js) //等待低电平结束
{
delay(5);
if(TH0>45) //判断低电平是否高于11.52ms如果高于则跳出等待和中断
return;
}
TR0=0;
if(TH0<30) //判断低电平是否低于7.68ms如果低于跳出中断
return;
TH0=0;
TR0=1;
while(js) //等待高电平结束
{
delay(5);
if(TH0>28) //判断高电平是否高于7.168ms如果高于则跳出等待和中断
return;
}
//至此为起始信号检测
TR0=0;
TH0=0;
for(i=0;i<4;i++) //一次锁存红外接收的四个十六进制数到a[4]中
{
for(j=0;j<8;j++)
{
TR0=1;
while(!js) //判断低电平宽度是否大于3..40ms
{
delay(5);
if(TH0>15)
return;
}
TH0=0;
while(js) //判断高电平是否大于1.012ms如果高于则为接受到1,否则为0
{
delay(5);
if(TH0>15)
return;
}
TR0=0;
CY=0;
k=(k>>1);
if(TH0>4)
k=k+0x80;
TH0=0;
}
a[i]=k;
}
}