#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_dat P0
//LCD1602端口
sbit RS = P2^0;
sbit RW = P2^1;
sbit EN = P2^2;
//DS1302端口
sbit RST = P2^3;
sbit IO = P2^4;
sbit SCLK = P2^5;
//DS18B20端口
sbit DQ = P2^6; //DS18B20的数据口位P2.0
//秒 分 时 日 月 星期 年
uchar code Time_init[] = {0x00, 0x00, 0x12, 0x01, 0x01, 0x05, 0x10}; //初始时间
uchar data now[7]; //时间缓存
void delay10us(uchar n) //延时10uS(STC90C52RC/12MHz)
{
while (n--)
{
_nop_();
_nop_();
_nop_();
}
}
void delay1ms(uint t)
{
uint i,j;
for(i=0;i<t;i++)
for(j=0;j<100;j++);
}
void Wr_Com(uchar com) //LCD1602写指令
{
delay1ms(1);
RS=0;
RW=0;
EN=0;
LCD1602_dat=com;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void Wr_Dat(uchar dat) //LCD1602写数据
{
delay1ms(1);
RS=1;
RW=0;
EN=0;
LCD1602_dat=dat;
delay1ms(1);
EN=1;
delay1ms(1);
EN=0;
}
void Lcd1602_Init() //LCD1602初始化设置
{
delay1ms(15);
Wr_Com(0x38);
delay1ms(5);
Wr_Com(0x08);
delay1ms(5);
Wr_Com(0x01);
delay1ms(5);
Wr_Com(0x06);
delay1ms(5);
Wr_Com(0x0c);
delay1ms(5);
}
void display(uchar *p) //LCD1602显示字符串
{
while(*p!='\0')
{
Wr_Dat(*p);
p++;delay1ms(1);
}
}
uchar DS1302_ReadByte() //从DS1302读1字节数据
{
uchar i;
uchar dat=0;
for(i=0;i<8;i++)
{
SCLK = 0;//时钟线拉低
_nop_(); //延时等待
_nop_();
dat >>= 1; //数据右移一位
if (IO) dat |= 0x80; //读取数据
SCLK = 1; //时钟线拉高
_nop_();
_nop_();
}
return dat;
}
void DS1302_WriteByte(uchar dat) //向DS1302写1字节数据
{
uchar i;
for(i=0;i<8;i++)
{
SCLK = 0; //时钟线拉低
_nop_(); //延时等待
_nop_();
dat >>= 1; //移出数据
IO = CY; //送出到端口
SCLK = 1; //时钟线拉高
_nop_(); //延时等待
_nop_();
}
}
uchar DS1302_ReadData(uchar addr) //读DS1302某地址的的数据
{
uchar dat;
RST = 0;
_nop_(); //延时等待
_nop_();
SCLK = 0;
_nop_(); //延时等待
_nop_();
RST = 1;
_nop_(); //延时等待
_nop_();
DS1302_WriteByte(addr); //写地址
dat = DS1302_ReadByte(); //读数据
SCLK = 1;
RST = 0;
return dat;
}
void DS1302_WriteData(uchar addr,uchar dat) //往DS1302的某个地址写入数据
{
RST = 0;
_nop_(); //延时等待
_nop_();
SCLK = 0;
_nop_(); //延时等待
_nop_();
RST = 1;
_nop_(); //延时等待
_nop_();
DS1302_WriteByte(addr); //写地址
DS1302_WriteByte(dat); //写数据
SCLK = 1;
RST = 0;
}
void DS1302_SetTime(uchar *p) //写入初始时间
{
uchar addr = 0x80;
uchar n = 7;
DS1302_WriteData(0x8e,0x00); //允许写操作
while(n--)
{
DS1302_WriteData(addr,*p++);
addr += 2;
}
DS1302_WriteData(0x8e,0x80); //写保护
}
void DS1302_Initial() //初始化DS1302
{
RST = 0;
SCLK = 0;
DS1302_WriteData(0x8e, 0x00); //允许写操作
DS1302_WriteData(0x80, 0x00); //时钟启动
DS1302_WriteData(0x90, 0xa6); //一个二极管+4K电阻充电
DS1302_WriteData(0x8e, 0x80); //写保护
}
void Get_Time(uchar *p) //获取当前时间及显示
{
uchar addr=0x81;
uchar n=7;
uchar SHI_1,SHI_2,FEN_1,FEN_2,MIAO_1,MIAO_2; //时、分、秒
// uchar RI_1,RI_2,YUE_1,YUE_2,NIAN_1,NIQN_2; //日、月、年
while (n--)
{
*p++ = DS1302_ReadData(addr);
addr += 2;
}
// RI_1,RI_2,YUE_1,YUE_2,NIAN_1,NIQN_2;
SHI_1 = now[2] >> 4;
SHI_2 = now[2] & 0x0f;
FEN_1 = now[1] >> 4;
FEN_2 = now[1] & 0x0f;
MIAO_1 = now[0] >> 4;
MIAO_2 = now[0] & 0x0f;
Wr_Com(0x80);
display("Time:");
Wr_Com(0x85);
Wr_Dat(SHI_1+0x30);
Wr_Dat(SHI_2+0x30);
Wr_Dat(':');
Wr_Dat(FEN_1+0x30);
Wr_Dat(FEN_2+0x30);
Wr_Dat(':');
Wr_Dat(MIAO_1+0x30);
Wr_Dat(MIAO_2+0x30);
}
void DS18B20_Reset() //复位DS18B20,并检测设备是否存在
{
CY = 1;
while (CY)
{
DQ = 0; //送出低电平复位信号
delay10us(48); //延时至少480us
DQ = 1; //释放数据线
delay10us(6); //等待60us
CY = DQ; //检测存在脉冲
delay10us(42); //等待设备释放数据线
}
}
uchar DS18B20_ReadByte() //从DS18B20读1字节数据
{
uchar i;
uchar dat = 0;
for(i=0;i<8;i++)
{
dat >>= 1;
DQ = 0; //开始时间片
_nop_(); //延时等待
_nop_();
DQ = 1; //准备接收
_nop_(); //接收延时
_nop_();
if(DQ){dat |= 0x80;} //读取数据
delay10us(6); //等待时间片结束
}
return dat;
}
void DS18B20_WriteByte(uchar dat) //向DS18B20写1字节数据
{
uchar i;
for(i=0;i<8;i++)
{
DQ = 0; //开始时间片
_nop_(); //延时等待
_nop_();
dat >>= 1; //送出数据
DQ = CY;
delay10us(6); //等待时间片结束
DQ = 1; //恢复数据线
}
}
void Get_Temp() //获取温度及显示
{
uchar TPH,TPL; //存放温度值的高低字节
uint dat;
uint x1,x2,x3,x4,x5;
DS18B20_Reset(); //设备复位
DS18B20_WriteByte(0xCC); //跳过ROM命令
DS18B20_WriteByte(0x44); //开始转换命令
while (!DQ); //等待转换完成
DS18B20_Reset(); //设备复位
DS18B20_WriteByte(0xCC); //跳过ROM命令
DS18B20_WriteByte(0xBE); //读暂存存储器命令
TPL = DS18B20_ReadByte(); //读温度低字节
TPH = DS18B20_ReadByte(); //读温度高字节
dat = (TPH<<8)+TPL; //DB18B20测温范围 -55℃~125℃
if(dat<=2000) //显示正温度
{
dat = dat*(10.0/16.0);
Wr_Com(0xC5); //送去LCD1602显示
Wr_Dat('+');
}
else //显示负温度
{
dat = 65537 - dat;
dat = dat*(10.0/16.0);
Wr_Com(0xC5); //送去LCD1602显示
Wr_Dat('-');
}
x1=dat/10000;
dat=dat%10000;
x2=dat/1000;
dat=dat%1000;
x3 =dat/100;
dat=dat%100;
x4=dat/10;
dat=dat%10;
x5=dat;
Wr_Com(0xC0); //送去LCD1602显示
display("Temp:");
Wr_Com(0xC6);
// Wr_Dat(x1 + 0x30);
// Wr_Dat(x2 + 0x30);
Wr_Dat(x3 + 0x30);
Wr_Dat(x4 + 0x30);
Wr_Dat('.');
Wr_Dat(x5 + 0x30);
}
void main()
{
Lcd1602_Init(); //初始化LCD1602
DS1302_Initial(); //初始化DS1302
DS1302_SetTime(Time_init); //设置初始时间
while(1)
{
Get_Time(now); //获取当前时间
Get_Temp(); //获取当前温度
}
}
|