/*共阳数码管加了DS1302的,有DS18B20,调好了!可用的程序*/
/*刘老师的---孙玉龙*/
#include
#include
***it key_2=P3^5;
***it key_1=P3^7;
***it SCK=P1^5; //DS1302
***it SDA=P1^6; //DS1302
***it RST = P1^7; // DS1302复位
***it CLKA=P1^2;
***it CLKB=P1^3;
***it DQ20=P1^4; //DS18B20
bit ReadRTC_Flag;
unsigned char l_tmpdate[3]={0,0,0};//秒分时08-05-15 12:00:00
unsigned char l_tmpdisplay[6];
unsigned char DS18B20_ma[6];
code unsigned char write_rtc_address[3]={0x80,0x82,0x84}; //秒分时 最低位读写位
code unsigned char read_rtc_address[3]={0x81,0x83,0x85};
code unsigned char table[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28};
//共阳数码管,码自写
code unsigned char table1[]={0xbf,0xdf,0xf7,0x7f,0xfd,0xfe,};
//显示位码表
unsigned char count_cent,count_sec,count_hour,count; //
unsigned int i,num,key_1i,key_2i,key_2j; //
unsigned char temperature=0; //
void delay(unsigned int us)
{
while(us--);
}
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
ET0=0;
for (i=0;i<8;i++) //循环8次 写入数据
{
SCK=0;
SDA=temp&0x01; //每次传输低字节
temp>>=1; //右移一位
SCK=1;
}
ET0=1;
}
/****************************************************************************/
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_(); //启动
Write_Ds1302_Byte(address); //发送地址
Write_Ds1302_Byte(dat); //发送数据
RST=0; //恢复
}
/****************************************************************************/
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
ET0=0;
for (i=0;i<8;i++) //循环8次 读取数据
{
if(SDA)
temp|=0x80; //每次传输低字节
SCK=0;
temp>>=1; //右移一位
SCK=1;
}
ET0=1;
RST=0;
_nop_(); //以下为DS1302复位的稳定时间
RST=0;
SCK=0;
_nop_();
SCK=1;
_nop_();
SDA=0;
_nop_();
SDA=1;
_nop_();
return (temp); //返回
}
/****************************************************************************/
void Read_RTC(void) //读取 日历
{
unsigned char i,*p;
p=read_rtc_address; //地址传递
for(i=0;i<3;i++) //分3次读取 秒分时日月周年
{
l_tmpdate[i]=Read_Ds1302(*p);
p++;
}
}
/***********************************************************************/
void Set_RTC(void) //设定 日历
{
unsigned char i,*p,tmp;
for(i=0;i<3;i++)
{ //BCD处理
tmp=l_tmpdate[i]/10;
l_tmpdate[i]=l_tmpdate[i]%10;
l_tmpdate[i]=l_tmpdate[i]+tmp*16;
}
Write_Ds1302(0x8E,0X00); //给ds1302写一个数据
p=write_rtc_address; //传地址
for(i=0;i<3;i++) //3次写入 秒分时
{
Write_Ds1302(*p,l_tmpdate[i]);
p++;
}
Write_Ds1302(0x8E,0x80);
}
//------------------------------------------------------------//
//-----------------ds18b20的初始化----------------------------//
//------------------------------------------------------------//
void init_DS18B20()
{
bit X=0;
DQ20=1;
delay(20);
DQ20=0;
delay(480);
DQ20=1;
delay(4);
X=DQ20;
delay(20);
}
//------------------------------------------------------------//
//---------------用于读ds18b20的温度--------------------------//
//------------------------------------------------------------//
read_DS18B20()
{
unsigned char i,dat=0;
ET0=0;
for (i=0;i<8;i++)
{
DQ20=0;
dat>>=1;
DQ20=1;
if(DQ20)
dat|=0x80;
delay(5);
}
ET0=1;
return(dat);
}
//------------------------------------------------------------//
//---------------用于给ds18b20写读温度指令--------------------//
//------------------------------------------------------------//
void write_DS18B20(unsigned char dat)
{
char i;ET0=0;
for (i=0;i<8;i++)
{
DQ20=0;
DQ20=dat&0x01;
delay(5);
DQ20=1;
dat>>=1;
}ET0=1;
delay(4);
}
//------------------------------------------------------------//
//-----------------用于ds18b20读数据与写指令------------------//
//------------------------------------------------------------//
void DS18B20_()
{
unsigned char tempL,tempH;
init_DS18B20();
write_DS18B20(0xcc);
write_DS18B20(0x44);
init_DS18B20();
write_DS18B20(0xcc);
write_DS18B20(0xbe);
tempL=read_DS18B20();
tempH=read_DS18B20();
temperature=(tempL>>4)|(tempH<<4);
}
void tim(void) interrupt 1 using 1//中断,用于数码管扫描
{
unsigned char tmp;
TH0=0xfc;//初始化值
TL0=0x18;
if(key_2j==1&&i==0)
P0=table[l_tmpdisplay[i]]&0xdf; //为显示小数点用
else if(key_2j==2&&i==2)
P0=table[l_tmpdisplay[i]]&0xdf; //为显示小数点用
else if(key_2j==3&&i==4)
P0=table[l_tmpdisplay[i]]&0xdf; //为显示小数点用
else if(i==1&&!key_2j)
P0=table[l_tmpdisplay[i]]&0xdf; //为显示小数点用
else
P0=table[l_tmpdisplay[i]]; //查表法得到要显
示数字的数码段
CLKA=1;
CLKA=0;
P2=table1[i];
CLKB=1;
CLKB=0;
i++;
if(i==6)
{
i=0;
num++;
if(10==num) //隔段时间读取1302的数据。时间间隔可以调整
{
ReadRTC_Flag=1; //使用标志位判断
num=0;
}
}
if(key_1==0) //这if为调时用
{
key_1i++;
if(key_1i==10)
{
if(key_2j==0)
{
l_tmpdisplay[4]=temperature/10; //ds18b20专用
l_tmpdisplay[5]=temperature%10; //ds18b20专用
}
if(key_2j==1)
{
count_hour++;
if(count_hour==24)count_hour=0;
count=count_hour;
tmp=count/10;
count=count%10;
count=count+tmp*16;
Write_Ds1302(0x8E,0X00); //给ds1302写一个数据
Write_Ds1302(0x84,count);//给ds1302写一个小时数
据
Write_Ds1302(0x8E,0x80);
}
if(key_2j==2)
{
count_sec++;
if(count_sec==60)count_sec=0;
count=count_sec;
tmp=count/10;
count=count%10;
count=count+tmp*16;
Write_Ds1302(0x8E,0X00); //给ds1302写一个数据
Write_Ds1302(0x82,count);//给ds1302写一个分钟数
据
Write_Ds1302(0x8E,0x80);
}
if(key_2j==3)
{
count_cent++;
if(count_cent==60)count_cent=0;
count=count_cent;
tmp=count/10;
count=count%10;
count=count+tmp*16;
Write_Ds1302(0x8E,0X00); //给ds1302写一个数据
Write_Ds1302(0x80,count);//给ds1302写一个分钟数
据
Write_Ds1302(0x8E,0x80);
}
}
if(key_1i==60000)key_1i=20001;
}
else
key_1i=0;
if(key_2==0) //这if为调时位选
{
key_2i++;
if(key_2i==10)
{
key_2j++;
if(key_2j==4)key_2j=0;
}
if(key_2i==60000)key_2i=20001;
}
else key_2i=0;
}
void main(void)
{
TMOD=0x01;//定时器设置 16位
TH0=0xfc;//初始化值
TL0=0x18;
EA=1;
ET0=1;
TR0=1;
//Set_RTC();
while(1)
{
DS18B20_();
if(ReadRTC_Flag) //以下为显示哦!
{
ReadRTC_Flag=0;
Read_RTC();
l_tmpdisplay[0]=l_tmpdate[2]/16;
//数据的转换,因我们采用数码管0~9的显示,将数据分开
l_tmpdisplay[1]=l_tmpdate[2]&0x0f;
//l_tmpdisplay[2]=10;
//加入"-"
l_tmpdisplay[2]=l_tmpdate[1]/16;
l_tmpdisplay[3]=l_tmpdate[1]&0x0f;
//l_tmpdisplay[5]=10;
if(key_1)
{
l_tmpdisplay[4]=l_tmpdate[0]/16;
l_tmpdisplay[5]=l_tmpdate[0]&0x0f;
}
count_hour=l_tmpdisplay[0]*10+l_tmpdisplay[1];
//用于掉用显示调时小时数
count_sec =l_tmpdisplay[2]*10+l_tmpdisplay[3];
//用于掉用显示调时分钟数
count_cent=l_tmpdisplay[4]*10+l_tmpdisplay[5];
}
}
}
这个程序在单片机一上电就DS1302的时间就变了,,硬件我是看了的,,没什么问题
0
|
|
|
|