所作的仿真图如下:
程序分为五个部分
程序如下:
main.c
#include<reg51.h>
unsigned char cp,cp2,flash,sec,min,hour,day,month,i,t_x1;
int cp1;
unsigned int year = 2021;
#include<lcd1602.c>
#include<ds18b20.c>
#include<display.c>
#include<ds1302.c>
void timer_isr(void) interrupt 1
{
TH0 = (65535 - 2000) / 256;
TL0 = (65535 - 2000) % 256;
cp++;cp2++;
if(cp >= 250)
{
cp = 0;
flash++;
}
if(flash >= 2){flash = 0;sec++;}
if(sec >= 60){min++;sec = 0;}
if(min >= 60){min = 0;hour++;}
if(hour >= 24){hour = 0;day++;}
if(day > 31){day = 1;month++;}
if(month > 12){year++;month = 1;}
if(cp2 >= 250)
{
cp2 = 0;
display0();
display1();
display2();
}
}
void timer_init(void)
{
TMOD = 0x01;
TH0 = (65535 - 2000) / 256;
TL0 = (65535 - 2000) % 256;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void main(void)
{
timer_init();
// write_init_time();
get_ds1302();
lcd1602_init();
lcd1602_clear();
while(1)
{
display3();
cp1++;
if(cp1 >= 1000)
{
cp1 = 0;
get_ds18b20();
if((t_x & 0x80) == 0x80)
{
t_x1 = 0xff - t_x;
t_d = (0x0f - t_d)*0.625 + 1;
if(t_d == 10){t_x1 = t_x1 + 1;t_d = 0;}
}
else {t_x1 = t_x;t_d = t_d*0.625;
}
}
}
}
dispaly.c
void display0()
{
goto_xy(1,0);
display_string("Time:");
display_num(hour / 10);
display_num(hour % 10);
// display_num(hour);
if(flash)display_string("-");
else display_string(" ");
display_num(min / 10);
display_num(min % 10);
// display_num(min);
if(flash)display_string("-");
else display_string(" ");
display_num(sec / 10);
display_num(sec % 10);
// display_num(sec);
goto_xy(2,0);
display_string("Temp:");
// display_num(year / 1000);
// display_num(year / 100 % 10);
display_num(t_x1 / 10 % 10);
display_num(t_x1 % 10);
// if(flash)display_string("-");
// else display_string(" ");
// display_num(mon / 10);
// display_num(mon % 10);
// if(flash)display_string("-");
// else display_string(" ");
// display_num(day / 10);
// display_num(day % 10);
}
unsigned char smg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
char k;
void display1(void)
{
P0 = 0xff;
switch(k)
{
case 0:P1 = 0x01;P0 = smg[sec % 10];break;
case 1:P1 = 0x02;P0 = smg[sec / 10];break;
case 2:P1 = 0x04;P0 = 0xbf | flash;break;
case 3:P1 = 0x08;P0 = smg[min % 10];break;
case 4:P1 = 0x10;P0 = smg[min / 10];break;
case 5:P1 = 0x20;P0 = 0xbf | flash;break;
case 6:P1 = 0x40;P0 = smg[hour % 10];break;
case 7:P1 = 0x80;P0 = smg[hour / 10];break;
}
k++;
if(k>=8)k = 0;
}
void display2(void)
{
P0 = 0xff;
switch(k)
{
case 0:P1 = 0x01;P0 = smg[day % 10];break;
case 1:P1 = 0x02;P0 = smg[day / 10];break;
case 2:P1 = 0x04;P0 = 0xbf;break;
case 3:P1 = 0x08;P0 = smg[month % 10];break;
case 4:P1 = 0x10;P0 = smg[month / 10];break;
case 5:P1 = 0x20;P0 = 0xbf;break;
case 6:P1 = 0x40;P0 = smg[year % 10];break;
case 7:P1 = 0x80;P0 = smg[year / 10];break;
}
k++;
if(k>=8)k = 0;
}
void display3(void)
{
P0 = 0xff;
switch(i)
{
case 0:P2 = 0x01;P0 = 0xff;break;
case 1:P2 = 0x02;if((t_x & 0x80) == 0x80)P0 = 0xbf;else P0 = 0xff;break;
case 2:P2 = 0x04;if(t_x1 < 10)P0 = 0xff;else P0 = smg[t_x1 / 10];break;
case 3:P2 = 0x08;P0 = smg[t_x1 % 10] & 0x7f;break;
case 4:P2 = 0x10;P0 = smg[t_d];break;
case 5:P2 = 0x20;P0 = 0xc6;break;
}
i++;
if(i >= 6)i = 0;
}
LCD1602.C
#define uchar unsigned char
#define uint unsigned int
sbit RS = P2^4;//数据/命令
sbit RW = P2^5;//读/写
sbit E = P2^6;//使能
uchar i;
void delay(unsigned int x)
{
while(x--);
}
void write_command(uchar command)
{
RW = 0;
RS = 0;
P0 = command;
E = 1;
delay(100);
E = 0;
RW = 1;
}
void write_data(uchar date)
{
RW = 0;
RS = 1;
E = 1;
P0 = date;
delay(100);
E = 0;
RW = 1;
}
void lcd1602_init(void)
{
write_command(0x38);
write_command(0x0f);
write_command(0x0c);
write_command(0x06);
}
void lcd1602_clear(void)
{
write_command(0x01);
write_command(0x02);
}
void display_string(uchar *p)
{
while(*p)
{
write_data(*p);
p++;
}
}
void display_num(uchar x)
{
双数字
// write_data((x / 10) + 0x30);
// write_data((x % 10) + 0x30);
//单数字
write_data(x + 0x30);
}
void goto_xy(uchar x,uchar y)
{
if(x == 1)
write_command(0x80 + y);
if(x == 2)
write_command(0x80 + 0x40 + y);
}
DS1302.C
sbit CE = P3^5;
sbit SCLK = P3^6;
sbit IO = P3^7;
unsigned char week;
void ds1302_init()//初始化
{
CE = 0;
SCLK = 0;
CE = 1; //允许读写数据
}
/*对ds1302写一字节数据*/
void write_ds1302_onebyte(unsigned char dat)
{
unsigned char i;
for(i = 0;i < 8;i++)
{
SCLK = 0;
IO = (bit)(dat & 0x01); // 0001 & 0001 //把写入的数据取出来给DS1302
SCLK = 1;
dat = dat >> 1; //每取一次 移一位
}
}
/*从DS1302里面读出一字节数据*/
unsigned char read_ds1302_onebyte()
{
unsigned char i,j;
for(i = 0;i<8;i++)
{
SCLK = 1;
SCLK = 0;
j = j >> 1; //移位
if(IO)j = j | 0X80; //一位一位的读取数据
}
return(j);//8421BCD码
}
///*对DS1302某一地址写数据*/
//void write_ds1302_add_dat(unsigned char add,unsigned char dat)
//{
// ds1302_init();
// write_ds1302_onebyte(add);
// write_ds1302_onebyte(dat);
// CE = 0; //关闭CE不再读写数据 IO SCLK 变为高阻态(断路)
//}
/*从DS1302里面读出数据*/
unsigned char read_ds1302_add(unsigned char add)
{
unsigned char dat_temp;
ds1302_init();
write_ds1302_onebyte(add);
dat_temp = read_ds1302_onebyte();
CE = 0;
return(dat_temp);
}
/*8421BCD码转十进制*/
unsigned char BCD_DEC(unsigned char x)
{
unsigned char dec;
dec = x & 0x0f; //取出低四位
x = x >> 4; //挤出低四位,把高四位放到地位
dec = x*10 + dec;
return(dec);
}
///*十进制转8421BCD码*/
//unsigned char DEC_BCD(unsigned char x)
//{
// unsigned char bcd;
// bcd = x % 10;//取出十进制的个位
// x = x / 10;//取出十进制的十位
// x = x << 4;
// bcd = bcd | x;
// return(bcd);
//}
///*单片机向DS1302里面写数据*/
//void write_init_time()
//{
// write_ds1302_add_dat(0x8e,0x00);//关闭保护
// write_ds1302_add_dat(0x80,DEC_BCD(sec));//写秒
// write_ds1302_add_dat(0x82,DEC_BCD(min));//写分
// write_ds1302_add_dat(0x84,DEC_BCD(hour));//写时
// write_ds1302_add_dat(0x86,DEC_BCD(day));//写日
// write_ds1302_add_dat(0x88,DEC_BCD(month));//写月
// write_ds1302_add_dat(0x8A,DEC_BCD(week));//写周
// write_ds1302_add_dat(0x8C,DEC_BCD(year));//写年
// write_ds1302_add_dat(0x8e,0x10);//打开保护
//}
/*单片机从DS1302里面得到时间数据*/
void get_ds1302()
{
unsigned char R;
R = read_ds1302_add(0x81);//读秒
sec = BCD_DEC(R);
R = read_ds1302_add(0x83);//读分
min = BCD_DEC(R);
R = read_ds1302_add(0x85);//读时
hour = BCD_DEC(R);
R = read_ds1302_add(0x87);//读日
day = BCD_DEC(R);
R = read_ds1302_add(0x89);//读月
month = BCD_DEC(R);
R = read_ds1302_add(0x8B);//读周
week = BCD_DEC(R);
R = read_ds1302_add(0x8D);//读年
year = BCD_DEC(R);
}
DS18B20.C
unsigned char t_x,t_d;
sbit dq = P1^7;
//void delay(unsigned int x){while(x--);} //延迟函数
/*初始化*/
void ds18b20_init(void) //初始化函数
{
unsigned char x = 255;
dq = 1; //先让dq置1
dq = 0; //单片机将dq拉低
delay(80); //延时480~960us
dq = 1; //释放总线
delay(5);
while(dq && x--); //等待返回低电平响应,若无响应,则做适量延时后往下进行
delay(20);
}
/*向DS18B20中写一个字节*/
void write_ds18b20(unsigned char x) //写一个字节函数
{
unsigned char i;
for(i = 0;i < 8;i++)
{
dq = 0; //发送起始信号
dq = (bit)(x & 0x01); //取x最低位
x = x >> 1; //x依次向右移动一位
delay(10); //延迟约45us
dq = 1; //释放总线
}
dq = 1; //将数据线拉高
}
/*从DS18B20中读一个字节*/
unsigned char read_ds18b20(void) //读一个字节函数
{
unsigned char i,j;
for(i = 0;i < 8;i++)
{
dq = 0; //发送启动信号
delay(1); //延时6us
dq = 1; //释放总线
j = j>>1; //j右移一位
if(dq)j |= 0x80; //如果是高电平,则把j的最高位置1,如果不是,默认值0
delay(5); //延时40us
dq = 1; //释放总线
}
dq = 1;
return(j);
}
/*读取温度*/
void get_ds18b20(void) //读取温度函数
{
unsigned char i;
ds18b20_init(); //初始化
write_ds18b20(0xcc); //跳过读序列号操作
write_ds18b20(0x44); //启动温度转换
ds18b20_init(); //初始化
write_ds18b20(0xcc); //跳过读序列号操作
write_ds18b20(0xbe); //读取温度寄存器
t_x = read_ds18b20(); //读取温度低位
i = read_ds18b20(); //读取温度高位
t_d = t_x & 0x0f; //读取小数部分
t_x = (i << 4) | (t_x >> 4); //低位右移四位,高位左移四位
}
实现结果如下: