#include<reg51.h>
#include<intrins.h>
#include<absacc.h>
#define INPUT P1
#define PORT P0
#define uint unsigned int
#define uchar unsigned char
uint STATE; //温度计存在记录,为加快速度下面给出位
sbit bflag=PORT^7;
sbit RS=P2^0;
sbit RW=P2^1;
sbit E=P2^2;
uchar code L1[]={" www.xl-scan.cn "};
uchar code L2[]={"Wellcome 8*18b20"};
uchar data L3[3];
uchar code L4[]={" = ."};
int data TTT[]={0x12,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88}; //18b20温度的10倍
uint x,cp=0,ge,shi,bai,cop;
int zijie=0;
int data wdjc[2]={55,55}; //18b20
uint data zf[]={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88}; //18b20温度符号
int wd=0x20;
int n;
//////////////////////延时50us
void delay(uint t)
{
uchar j;
for(;t>0;t--)
for(j=19;j>0;j--)
;
}
//////////////2的n次方算法
int POWER2(int nn)
{
int r = 1,i;
for(i=1;i<=nn;i++)
r *= 2;
return r;
}
/////////////初始化寻找温度计,按位保存于STATE
void INT()
{
uint x,y,nn;
STATE=0X00;
for(x=0;x<=8;x++)
{
nn=POWER2(x);
INPUT=0XFF-nn; //拉低检测脚
delay(10); //延时足够时间
INPUT=0XFF; //恢复状态
delay(2); //等待温度计脉冲
for(y=20;y>0;y--)
{if(!(INPUT&nn)) //如果本引脚给出反应
{STATE=STATE|nn; //状态标记
// RENEWTEMP(x); //更新温度
y=1; //立即退出
}
else
;
}
}
// P2=STATE; //测试
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////温度部分
void yanshi_18B20(unsigned int ys) //18b20延时子程序
{
for(;ys>0;ys--);
}
void reset() //18b20复位子程序
{
INPUT=0XFF-n;
yanshi_18B20(44);
INPUT=0XFF;
yanshi_18B20(15);
}
void xie(char xzj) //写18b20子程序
{
unsigned char i,j;
for (i=8;i>0;i--)
{
INPUT=0XFF-n;
j++;
if(xzj&0x01)
INPUT=0XFF;
else
INPUT=0XFF-n;
yanshi_18B20(8); //8是否更改
INPUT=0XFF;
j++;
xzj>>=1;
}
}
void chushihua(void) //初始化子程序
{
reset(); //复位
xie(0xCC); //跳过序列号
xie(0x44); //温度转换命令
}
unsigned int du() //读18b20子程序
{
unsigned char i;
for (i=8;i>0;i--)
{
zijie>>=1;
INPUT=0XFF-n;
_nop_();_nop_();_nop_();_nop_();
INPUT=0XFF;
if(INPUT&n)
{
zijie|=0x80;
}
yanshi_18B20(4); //4是否修改
}
return(zijie);
}
void duquwendu(void) //读取温度子程序
{
int k,L;
reset(); //复位
k++; //延时4us
xie(0xCC); //跳过序列号
k++; //延时4us
xie(0xBE); //发出读指令
k++;k++; //延时8us
wdjc[0]=du(); //读取低字节
wdjc[1]=du(); //读取高字节
L=wdjc[1]; //把第二个字节先存至低8位
L<<=8; //把第二个字节移到高八位上去
L|=wdjc[0]; //把第一个字节放到底八位上去
if( (wdjc[1]&0x08)) //去除的到数据的数据位,得到符号位
{
wd=0xffff-L+1; //如果为负温则去除其补码
zf[x]=0; //表示温度为负数
}
else
{
wd=L; //如果为正温度则只直接赋予wd
zf[x]=1; //表示温度为正数
}
TTT[x]=wd*10/16; //获取的温度转换成十进制温度数值的10倍
}
////////////更新温度
void RENEWTEMP(void)
{
uint NUM;
for(x=0;x<=8;x++)
{NUM=POWER2(x);
n=NUM;
if(STATE&NUM) //x号存在
{chushihua();
duquwendu();
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////温度部分
////////////////////////////////////////////////////////////////////////////////////////////display1602
void busy() //判断1602是否忙状态,忙则等待到忙碌结束
{
do
{
PORT=0xff;
RS=0;
RW=1;
E=0;
_nop_();
E=1;
}
while(bflag);
}
void writemaster(uchar master,uchar busyc) //写命令,master为命令内容,busyc 0不用判断忙1需
{
if(busyc) busy();
RS=0;
RW=0;
E=1;
PORT=master;
E=0;
}
void writedata(uchar ddata) //写入数据字节,一定判断忙否
{
busy();
RS=1;
RW=0;
E=1;
PORT=ddata;
E=0;
}
void first1602() //初始化
{
writemaster(0x3c,1);
writemaster(0x0e,1);
writemaster(0x06,1);
writemaster(0x01,1);
writemaster(0x0c,1);
writemaster(0x3b,1);
writemaster(0x13,1);
}
void displayonechar(uchar x,uchar y,uchar DATA) //在指定x列,y行位置写入一个字符
{
y&=0x1; //奇数为第二行,偶数为第一行
x&=0xf; //限制x为15以内,代表列
if(y) x|=0x40; //若为第二列,显示地址+40h到达第二列
x|=0x80; //d7置1转换为地址指令
writemaster(x,0); //不测忙,发送地址
writedata(DATA); //写如内容
}
void displayoverchar(uchar a,uchar b,uchar code *DATA) //在指定x列,y行开始写入字符串,z=0不自动换行,z=1自动换行
{
uchar cp=0; //cp字符计数器
b&=0x1;
while(*(DATA+cp))
{
displayonechar(a,b,DATA[cp]);
a++;
cp++;
}
}
void change(int x)
{
bai=x/100;
shi=x%100/10;
ge=x%10;
L3[0]=bai+0x30;
L3[1]=shi+0x30;
L3[2]=ge+0x30;
}
/////////////////////////////////////////////////////////////////////////////////////////////display1602
main()
{
INPUT=0xff;
cop=0;
INT(); //查找温度ji
first1602();
displayoverchar(0,0,L1);
displayoverchar(0,1,L2);
delay(255);
while(1)
{
cop++;
if(cop>=100)
{cop=1; INT();}
PORT=STATE; //显示有空的温度计
RENEWTEMP();
if((cop==1)&&(STATE&0X0f))
{
writemaster(0x01,1);
if(STATE&1)
{
change(TTT[0]);
displayoverchar(0,0,"A");
displayonechar(1,0,0X7E);
displayonechar(2,0,L3[0]);
displayonechar(3,0,L3[1]);
displayonechar(4,0,0X2E);
displayonechar(5,0,L3[2]);
}
if(STATE&2)
{
change(TTT[1]);
// writedata(0X18);
displayoverchar(9,0,"B");
displayonechar(10,0,0X7E);
displayonechar(11,0,L3[0]);
displayonechar(12,0,L3[1]);
displayonechar(13,0,0X2E);
displayonechar(14,0,L3[2]);
}
if(STATE&4)
{
change(TTT[2]);
displayoverchar(0,1,"C");
displayonechar(1,1,0X7E);
displayonechar(2,1,L3[0]);
displayonechar(3,1,L3[1]);
displayonechar(4,1,0X2E);
displayonechar(5,1,L3[2]);
}
if(STATE&8)
{
change(TTT[3]);
// writedata(0XC8);
displayoverchar(9,1,"D");
displayonechar(10,1,0X7E);
displayonechar(11,1,L3[0]);
displayonechar(12,1,L3[1]);
displayonechar(13,1,0X2E);
displayonechar(14,1,L3[2]);
}
}
if((cop==50)&&(STATE&0Xf0))
{
writemaster(0x01,1);
if(STATE&16)
{
change(TTT[4]);
displayoverchar(0,0,"E");
displayonechar(1,0,0X7E);
displayonechar(2,0,L3[0]);
displayonechar(3,0,L3[1]);
displayonechar(4,0,0X2E);
displayonechar(5,0,L3[2]);
}
if(STATE&32)
{
change(TTT[5]);
// writedata(0X18);
displayoverchar(9,0,"F");
displayonechar(10,0,0X7E);
displayonechar(11,0,L3[0]);
displayonechar(12,0,L3[1]);
displayonechar(13,0,0X2E);
displayonechar(14,0,L3[2]);
}
if(STATE&64)
{
change(TTT[6]);
displayoverchar(0,1,"G");
displayonechar(1,1,0X7E);
displayonechar(2,1,L3[0]);
displayonechar(3,1,L3[1]);
displayonechar(4,1,0X2E);
displayonechar(5,1,L3[2]);
}
if(STATE&128)
{
change(TTT[7]);
// writedata(0X