#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/*12864A 端口定义*/
#define LCD_data P0 //数据口
sbit LCD_RS = P3^5; //寄存器选择输入
sbit LCD_RW = P3^6; //液晶读/写控制
sbit LCD_EN = P3^4; //液晶使能控制
sbit LCD_PSB = P3^7; //串/并方式控制
uchar dis1[] = {"当前温度:"}; //9
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
//void lcd_pos(uchar X,uchar Y); //确定显示位置
sbit ds=P3^3; //温度传感器信号线
//sbit dula=P2^6; //数码管段选线
//sbit wela=P2^7; //数码管位选线
sbit beep=P2^3; //蜂鸣器
uint temp;
float f_temp;
/*延时函数*/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/*18B20复位,初始化函数*/
void dsreset(void)
{
uint i;
ds=0;
i=103;
while(i>0)i--;//提供480-950us延时
ds=1;
i=4;
while(i>0)i--;//提供60-240us的延时;单片机检测到低电平复位成功
}
/*读1位函数*/
bit tempreadbit(void)
{
uint i;
bit dat;
ds=0;i++; //i++ 起延时作用
ds=1;i++;i++;
dat=ds; //ds为低电平则读0反之则为1
i=8;while(i>0)i--; //提供延时
return (dat);
}
/*读1个字节*/
uchar tempread(void)
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tempreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
/*向18B20写一个字节数据,实际就是写命令*/
void tempwritebyte(uchar dat)
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //写 1
{
ds=0;
i++;i++;
ds=1;
i=8;while(i>0)i--;
}
else
{
ds=0; //写 0
i=8;while(i>0)i--;
ds=1;
i++;i++;
}
}
}
/* DS18B20 开始获取温度并转换*/
void tempchange(void) {
dsreset();
delay(1);
tempwritebyte(0xcc); // 写跳过读ROM指令
tempwritebyte(0x44); // 写温度转换指令
}
/*读取寄存器中存储的温度数据*/
uint get_temp()
{
uchar a,b;
dsreset();
delay(1);
tempwritebyte(0xcc);
tempwritebyte(0xbe); //读取RAM
a=tempread(); //读低8位
b=tempread(); //读高8位
temp=b;
temp<<=8; //两个字节组合为1个字
temp=temp|a;
f_temp=temp*0.0625; //温度在寄存器中为12位 分辨率位0.0625°
temp=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5是四舍五入
// f_temp=f_temp+0.05;
return temp; //temp是整型
}
/*检查LCD忙状态 */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 */
void lcd_busy()
{
uchar result;
LCD_RS = 0;
LCD_RW = 1;
while(1)
{
P0=0xff;
LCD_EN = 1;
result =P0;
LCD_EN = 0;
if((result&0x80)==0)
break;
}
}
/*写指令数据到LCD */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */
void lcd_wcmd(uchar cmd)
{
lcd_busy();
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
LCD_data = cmd;
delay(5);
LCD_EN = 1;
delay(5);
LCD_EN = 0;
}
/*写显示数据到LCD */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。*/
void lcd_wdat(uchar dat)
{
lcd_busy();
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
LCD_data = dat;
delay(5);
LCD_EN = 1;
delay(5);
LCD_EN = 0;
delay(5);
}
/* LCD初始化设定*/
void lcd_init()
{
LCD_PSB = 1; //并口方式
lcd_wcmd(0x34); //扩充指令操作
delay(5);
lcd_wcmd(0x30); //基本指令操作
delay(5);
lcd_wcmd(0x0C); //显示开,关光标
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
}
void lcd_pos(uchar X,uchar Y)
{
uchar pos;
if (X==0)
{X=0x80;}
else if (X==1)
{X=0x90;}
else if (X==2)
{X=0x88;}
else if (X==3)
{X=0x98;}
pos = X+Y ;
lcd_wcmd(pos); //显示地址
}
/* 主程序*/
main()
{
uchar i;
uint mm;
//dula=0;
//wela=0;
delay(10);
lcd_init(); //初始化LCD
while(1)
{
tempchange();
mm=get_temp(); //26.5,mm=265
dis1[9]=mm%1000/100+'0'; //或者 dis1[9]=mm/100+'0';
dis1[10]=mm%100/10+'0';
dis1[11]='.';
dis1[12]=mm%10+'0';
lcd_pos(0,0); //设置显示位置为第1行的第1个字符
i = 0;
while(i<=12)
{
lcd_wdat(dis1[i++]); //显示字符
}
delay(100);
}
}