这是我写的单片机小程序,将单片机开发板上的ds1302,ds18b20和1602综合起来,在1602上显示年月日周时分秒和温度;望各位好友指点,此程序仅适用于我的开发板,用在其他开发板上应该改下端口就可以。
#include <reg52.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
typedef long int uint32;
//****************************************************************************************************
sbit DQ=P2^2;//********************供18b20使用的变量
float T;
//****************************************************************************************************
uint8 counter_0,counter_1;//*******供1302使用的变量
uint8 second=0,minute=0,hour=0,year=0,month=0,day=0,week;
uint32 sh;
uint8 D[]="wek";
uint16 i=0;
//****************************************************************************************************
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ds18b20>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//****************************************************************************************************
void delay_10us(uint8 x)//*********10微秒级别延时
{
while(x>0)x--;
}
//****************************************************************************************************
void ds18b20_init()//**************ds18b20的初始化
{
uint16 i;
DQ=0;
i=103;
while(i>0)i--;
DQ=1;
i=4;
while(i>0)i--;;
}
//****************************************************************************************************
bit readbit()//********************读取一位数据
{
uint16 i;
bit dat;
DQ=0;i++;
DQ=1;i++;i++;
dat=DQ;
i=8;while(i>0)i--;
return(dat);
}
//****************************************************************************************************
uint8 r_ds18b20()//****************从ds18b20读取一字节数据
{
uint8 dat=0,i,j;
for(i=1;i<=8;i++)
{
j=readbit();
dat=(j<<7)|(dat>>1);
}
return(dat);
}
//****************************************************************************************************
void w_ds18b20(uint8 dat)//********向ds18b20写入一字节数据
{
uint8 j;
uint8 i;
bit testb;
for(i=1;i<=8;i++)
{
testb=dat&0x01;
dat>>=1;
if(testb)
{
DQ=0;
j++;j++;j++;
DQ=1;
j=14;while(j>0)j--;
}
else
{
DQ=0;
j=14;while(j>0)j--;
DQ=1;
j++;j++;j++;
}
}
}
//****************************************************************************************************
void beginchange()//***************开始转换温度
{
ds18b20_init();
delay_10us(200);
w_ds18b20(0xcc);
w_ds18b20(0x44);
}
//****************************************************************************************************
void get_temp()//*****************从ds18b20读取数据并转换成十进制
{
uint8 H,L;
uint16 temp;
ds18b20_init();
delay_10us(200);
w_ds18b20(0xcc);
w_ds18b20(0xbe);
L=r_ds18b20();
H=r_ds18b20();
temp=H;
temp<<=8;
temp|=L;
T=temp*(0.0625);
}
//****************************************************************************************************
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ds1302>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//****************************************************************************************************
#define WRITE_SECOND 0x80//*****写**秒寄存器地址
#define WRITE_MINUTE 0x82//*****写**分寄存器地址
#define WRITE_HOUR 0x84//*******写**时寄存器地址
#define WRITE_DAY 0x86//********写**天寄存器地址
#define WRITE_MONTH 0x88//******写**月寄存器地址
#define WRITE_YEAR 0x8c//*******写**年寄存器地址
#define WRITE_WEEK 0x8A//*******写**周寄存器地址
#define READ_SECOND 0x81//******读**秒寄存器地址
#define READ_MINUTE 0x83//******读**分寄存器地址
#define READ_HOUR 0x85//********读**时寄存器地址
#define READ_DAY 0x87//*********读**天寄存器地址
#define READ_MONTH 0x89//*******读**月寄存器地址
#define READ_YEAR 0x8d//********读**年寄存器地址
#define READ_WEEK 0x8b//********读**周寄存器地址
#define WRITE_PROTECT 0x8E//****写保护寄存器
sbit ACC_7=ACC^7;
sbit CLCK=P2^1;
sbit RST=P2^4;
sbit IO=P2^0;
//****************************************************************************************************
void write_1302(uint8 addr,uint8 dat)//向1302写入地址和数据
{
uint8 i=0;
RST=0;
CLCK=0;
RST=1;
for(i=8;i>0;i--)
{
CLCK=0;
if((addr&0x01)==1)IO=1;
else IO=0;
addr>>=1;
CLCK=1;
}
for(i=8;i>0;i--)
{
CLCK=0;
if((dat&0x01)==1)IO=1;
else IO=0;
dat>>=1;
CLCK=1;
}
RST=0;
}
//****************************************************************************************************
uint8 read_1302(uint8 addr)//先向1302写地址,再读数据
{
uint8 i=0,dat;
RST=0;
CLCK=0;
RST=1;
for(i=8;i>0;i--)
{
CLCK=0;
if((addr&0x01)==1)IO=1;
else IO=0;
addr>>=1;
CLCK=1;
}
for(i=8;i>0;i--)
{
ACC_7=IO;
CLCK=1;
ACC>>=1;
CLCK=0;
}
dat=ACC;
dat=(dat>>4)*10+(dat&0x0f);//有BCD码转换成十进制数
return(dat);
RST=0;
}
//*****************************************************************************************************
void ds1302_init()//1302初始化
{
write_1302(WRITE_PROTECT,0x00);//*******取消写保护
write_1302(WRITE_SECOND,0x00);//********00秒//NUM_BCD(0)
write_1302(WRITE_MINUTE,0x00);//********00分钟//NUM_BCD(0)
write_1302(WRITE_HOUR,0x16);//**********16小时//NUM_BCD(0)
write_1302(WRITE_DAY,0x21);//***********21天
write_1302(WRITE_MONTH,0x11);//*********11月
write_1302(WRITE_YEAR,0x12);//**********2012年
write_1302(WRITE_WEEK,0x03);//**********星期三
write_1302(WRITE_PROTECT,0x80);//*******打开写保护
}
//****************************************************************************************************
void timer0_init()//几十毫秒的延时
{
TMOD|=0x01;
TMOD&=0xfd;
TH0=0x3c;
TL0=0xaf;
TR0=1;
}
//****************************************************************************************************
void dushu()//从1302读取数据并将其转换成显示函数直接用到的数字
{
second=read_1302(READ_SECOND);
minute=read_1302(READ_MINUTE);
hour=read_1302(READ_HOUR);
day=read_1302(READ_DAY);
month=read_1302(READ_MONTH);
year=read_1302(READ_YEAR);
week=read_1302(READ_WEEK);
}
//******************************************************************************************************
void jishi0()//每一段时间会进行一次读取数字
{
if(TF0==1)
{
TF0=0;
TH0=0x3c;
TL0=0xaf;
counter_1++;
}
dushu();
if(counter_1==2)
{
counter_1=0;
get_temp();
beginchange();
}
}
//****************************************************************************************************
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<1602>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//****************************************************************************************************
sbit RS=P1^0;//**************数据命令选择端
sbit RW=P1^1;//**************读写选择端
sbit ENLCD=P2^5;//***********使能端
sbit shang=P2^6;//***********数码管数据输入控制端
sbit xia=P2^7;//*************数码管共阴极控制端
sbit busy=P0^7;//************判断忙标志
//****************************************************************************************************
void delay(uint32 x)
{
while(x--);
}
//****************************************************************************************************
bit check_1602()//***********判断1602是否处于忙状态
{
P0=0xff;
RS=0;
RW=1;
ENLCD=0;
delay(50);
ENLCD=1;
return((bit)(P0&0x80));
}
//****************************************************************************************************
void write_com(uint8 com)//向1602写入一命令
{
while(check_1602());//***首先判断1602是否在忙 忙则等待
RS=0;
RW=0;
ENLCD=1;
P0=com;
delay(50);
ENLCD=0;
}
//****************************************************************************************************
void write_dat(uint8 dat)//**向1602写入一字节数据
{
while(check_1602());//**首先判断1602是否在忙 忙则等待
RS=1;
RW=0;
ENLCD=1;
P0=dat;
delay(50);
ENLCD=0;
}
//****************************************************************************************************
void init_1602()//**********1602初始化
{
write_com(0x38);
delay(1000);
write_com(0x38);
delay(1000);
write_com(0x38);
write_com(0x08);
write_com(0x01);
write_com(0x06);
write_com(0x0c);
}
//****************************************************************************************************
void w_string(uint8 string[],uint8 x,uint8 y)//写入字符型数组 x代表从第一行的第几个方格开始显示
{
uint8 i=0; //y 代表在第几行
if(y==1)
{
while(string[i]!=0)
{
write_com(0x80+i+x);
write_dat(string[i]);
i++;
};
i=0;
}
if(y==2)
{
while(string[i]!=0)
{
write_com(0xc0+i+x);
write_dat(string[i]);
i++;
};
i=0;
}
}
//****************************************************************************************************
void w_char(uint8 c,x,y)//*********向1602写入一个字符
{
if(y==1)
{
write_com(0x80+x);
write_dat(c);
}
if(y==2)
{
write_com(0xc0+x);
write_dat(c);
}
}
//****************************************************************************************************
void H_1602()//********************1602要显示的内容
{
w_char(2+48,0,1);
w_char(48,1,1);
w_char(year/10%10+48,2,1);
w_char(year%10+48,3,1);
w_char(':',4,1);
w_char(month/10+48,5,1);
w_char(month%10+48,6,1);
w_char(':',7,1);
w_char(day/10+48,8,1);
w_char(day%10+48,9,1);
w_string(D,11,1);
w_char(':',14,1);
w_char(week%10+48,15,1);
w_char(hour/10+48,0,2);
w_char(hour%10+48,1,2);
w_char(':',2,2);
w_char(minute/10+48,3,2);
w_char(minute%10+48,4,2);
w_char(':',5,2);
w_char(second/10+48,6,2);
w_char(second%10+48,7,2);
w_char((uint8)T/10%10+48,9,2);
w_char((uint8)T%10+48,10,2);
w_char('.',11,2);
w_char((uint16)(T*10)%10+48,12,2);
w_char(0xdf,13,2);//显示圆点
w_char(67,14,2);//显示大写字母C
}
void closeLED()//******************关闭数码管函数
{
shang=0x00;
xia=0x00;
}
//****************************************************************************************************
void init()
{
timer0_init();
ds1302_init();
init_1602();
closeLED();
}
//****************************************************************************************************
main()
{
init();
beginchange();
while(1)
{
jishi0();
H_1602();
}
}

