【单片机】时钟及温度的显示

回头看我所写的文章,基本都是软件方面的,是个典型的“欺软怕硬”的人。然而,在最开始的时候,我学习的是硬件。在前面文章《我的2013–一起从心开始》一文中写道,我在大一暑假的时候开始了单片机的学习,在大二、大三期间做过些小东西。刚进入程序员的领域的时候,显然是单片机带我入了门。下面我将写写用单片机做过的一些东西,权当纪念。


本文介绍我大一暑假学完单片机后,在大二上学期为参加学校星火杯而完成的作品(最终没有参加比赛)。这个电子制作是关于用单片机显示时间的作品,其功能就用单片机控制LCD、LED来显示时间和温度。


功能描述

  • 显示精确度为0.1摄氏度的温度(低于0摄氏度和高于100摄氏度响铃)
  • 液晶时钟,断电后仍然继续走动,每月误差不到一分钟,无电源可工作10年左右,区分平年和闰年;
  • 指针式时钟(黄灯为时针,红色为分针,最小误差5分钟,整点报时)与考试计时器(计时2两小时)

电子元器件

  • 2个单片机最小系统 (单片机型号为STC89C52)
  • 双色发光二级管
  • 液晶显示屏
  • 按键
  • DS12C887时钟芯片
  • DS18b20温度传感器
  • 蜂鸣器(整点报时)
  • LED数码管(显示温度)

作品展示图

  • 由于所有电路都是由杜邦线连接,所以存在接触不良,导致有时不能正常显示,于是就没有参赛,下图为双色二极管的显示。
    这里写图片描述
    这里写图片描述
  • 下图为用1602液晶显示日期和时间
    这里写图片描述
    这里写图片描述
  • 下图为用数码管来显示温度
    这里写图片描述
  • 下图为作品的布线,简直是乱成一团,要是用PCB就好了。
    这里写图片描述

原文:http://blog.csdn.net/tengweitw/article/details/45895989
作者:nineheadedbird

附录:代码实现

对于硬件来说,给代码不给管脚图没啥意义,不过由于年代久远,我已经找不到当初设计的电路图了。但仍然给出代码图,希望能起到一点点的参考作用。

//--------------------------------温度显示程序 第一个芯片------------------------------------------------------------------//

#include<reg52.h>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char 
#define uint unsigned int

sbit ds=P2^2;

unsigned int te;

unsigned char code tabledu[]=
{ 
0x3f0x060x5b0x4f
0x660x6d0x7d0x07 
0x7f0x6f0x770x7c
0x390x5e0x790x71
};
unsigned char code tabledu1[]=
{ 
0xbf0x860xdb0xcf
0xe60xed0xfd0x87 
0xff0xef0xf70xfc
0x390x5e0x790x71
};

unsigned char code tablewe[]=
{
0xfe0xfd0xfb0xf70xef0xdf
};


void delayxms(unsigned int x)
{
unsigned int ij; 
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}



void delayx2us(unsigned char t)
{ 
while(--t);
}


void dsreset() // 复位
{
ds=1;
_nop_();
ds=0;
delayx2us(200);//注意时间
ds=1;
delayx2us(20);

}


void writetemp(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
ds = 0;
ds = dat&0x01;
delayx2us(25);
ds = 1;
dat>>=1;
}
delayx2us(25);
}


unsigned char readtemp(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
ds = 0; // 给脉冲信号
dat>>=1;
ds = 1; // 给脉冲信号
if(ds)
dat|=0x80;
delayx2us(25);
}
return(dat);
}

uint temp()
{
uint ab;
dsreset();
delayxms(1);
writetemp(0xcc);
writetemp(0x44);
delayxms(1);

dsreset();
delayxms(1);
writetemp(0xcc);
writetemp(0xbe);
delayx2us(50);
a=readtemp();
b=readtemp();
a=a*10;
te=b*160+a/16;

return te;
}

void disp(long int num)
{
uchar cde;
c=num/100;
d=num%100/10;
e=num%10;

P0=tabledu[c];
P1=0xfe;
delayxms(6);
P0=tabledu1[d];
P1=0xfd;
delayxms(6);
P0=tabledu[e];
P1=0xfb;
delayxms(6);
P0=0xcc;
P1=0xf7;
delayxms(2);

}


void main()
{

while(1)
{
disp(temp());
if((temp()>=1000)||(temp()<=0))
beep=0;
else
beep=1;


}





//--------------------------------时钟显示程序 第二个芯片------------------------------------------------------------------//
#include<reg52.h>

#define uchar unsigned char 
#define uint unsigned int



//流水灯锁存器
sbit wela1=P2^0;//1
sbit wela2=P2^1;//2
sbit wela3=P2^2;//1
sbit wela4=P2^3;//2

//蜂鸣器
sbit beep=P2^4;

//按键
sbit key1=P2^5;//功能选择键
sbit key2=P2^6;//+(时间、日期加)
sbit key3=P2^7;//-(时间、日期减)
sbit key4=P3^7;//模式键(平时或考试)



//液晶接口
sbit lcden=P3^4;
sbit lcdrs=P3^5;
sbit lcdwr=P3^6;

//ds12c887接口
sbit dscs=P1^6;
sbit dsas=P1^7;
sbit dsrw=P3^0;
sbit dsds=P3^1;
sbit dsirq=P3^3;


//定义变量
uchar hour minseccountriweekyuenianj;
//uchar counthcountmcountycountkloop1;
uchar code table1[]=" - - ";
uchar code table2[]=" : : ";
uchar code table3[]="SUNMONTUEWEDTHUFRISAT";



//延迟函数
void delayxms(unsigned int x) 
{
unsigned int ij; 
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}



//--------------------1602液晶函数----------------------------------




//液晶写命令
void write_com(unsigned char com) 
{
lcdrs=0;
P0=com;
delayxms(5);
lcden=1;
delayxms(5); 
lcden=0;
}

//液晶写数据
void write_data(unsigned char date)
{
lcdrs=1;
P0=date;
delayxms(5); 
lcden=1;
delayxms(5);
lcden=0;
}

//液晶初始化
void lcdinit()
{
lcdwr=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06); 
write_com(0x01);

}

// 液晶显示
void disp() 
{
uchar i;

write_com(0x80);
for(i=0;i<15;i++)
{
write_data(table1[i]);
delayxms(5);
}
write_com(0x80+0x40);
for(i=0;i<12;i++)
{
write_data(table2[i]);
delayxms(5);
}
}


//写时间
void write_sfm(uchar addressuchar shu) 
{
uchar shige;
shi=shu/10;
ge=shu%10;
write_com(0x80+0x40+address);
write_data(0x30+shi);
write_data(0x30+ge);
}


//写日历
void write_calendar(uchar addressuchar shu) 
{
uchar shige;
shi=shu/10;
ge=shu%10;
write_com(0x80+address);
write_data(0x30+shi);
write_data(0x30+ge);
}


//-------------------------DS12C887程序----------------------------
//写时钟
void write_ds(uchar adduchar date)
{
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
dsas=0;
dsrw=0;
P0=date;
dsrw=1;
dsas=1;
dscs=1;
}


//读时钟
uchar read_ds(uchar add)
{
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
dsas=0;
dsds=0;
P0=0xff;
ds_date=P0;
dsds=1;
dsas=1;
dscs=1;
return ds_date;
}

//写星期
void write_week(uchar date)
{

write_com(0x80+12);
write_data(table3[3*date]);
write_data(table3[3*date+1]);
write_data(table3[3*date+2]);
}




//键盘检测
void keyscan() //键盘检测 key1 为功能键 key2为加 key3为减 :时间与日期的改变
{

if(key1==0)
{
delayxms(10);
if(key1==0)
{
while(!key1);
count++;

if(count==1)
{

write_com(0x80+0x40+11);
write_com(0x0f);

}

if(count==2)
{

write_com(0x80+0x40+8);
write_com(0x0f);

}

if(count==3)
{

write_com(0x80+0x40+5);
write_com(0x0f);

}
if(count==4)
{
write_com(0x80+13);
write_com(0x0f);
}
if(count==7)
{
write_com(0x80+10);
write_com(0x0f);
}
if(count==6)
{
write_com(0x80+7);
write_com(0x0f);
}
if(count==5)
{
write_com(0x80+4);
write_com(0x0f);
}

if(count==8)
{

count=0;
write_com(0x0c);
write_ds(0sec);
write_ds(2min);
write_ds(4hour);
}
}
}


if(key2==0)
{
delayxms(10);
if(key2==0)
{
while(!key2);
if(count==1)
{
sec++;
if(sec==60)
sec=0;
write_ds(0sec);
write_sfm(10sec);
write_com(0x80+0x40+11);
}

if(count==2)
{
min++;
if(min==60)
min=0;
write_ds(2min);
write_sfm(7min);
write_com(0x80+0x40+8);
}


if(count==3)
{
hour++;

if(hour==24)
hour=0;
write_ds(4hour);
write_sfm(4hour);
write_com(0x80+0x40+5);
}

if(count==4)
{
week++;
if(week==7)
week=0;
write_week(week);
write_ds(6week);

}


if(count==5)
{
nian++;
if(nian==100)
nian=0;
write_ds(9nian);
write_calendar(3nian);
write_com(0x80+4);
}

if(count==6)
{
yue++;
if(yue==13)
yue=1;
write_ds(8yue);
write_calendar(6yue);
write_com(0x80+7);
}

if(count==7) // 判断闰年
{
ri++;
week++;
if(nian%4==0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==31)
ri=1;
}
else if(yue==2)
{
if(ri==30)
ri=1;
}
else
{
if(ri==32)
ri=1;
}
}

if(nian%4!=0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==31)
ri=1;
}
else if(yue==2)
{
if(ri>=29)
ri=1;
}
else
{
if(ri==32)
ri=1;
}
}
write_ds(7ri);
write_calendar(9ri);
write_com(0x80+10);
delayxms(2);
if(week==7) 
week=0;
write_week(week);
write_ds(6week);


}




}
}

if(key3==0)
{
delayxms(10);
if(key3==0)
{
while(!key3);
if(count==1)
{
if(sec==0)
sec=59;
else
sec--;
write_ds(0sec);
write_sfm(10sec);
write_com(0x80+0x40+11);
}

if(count==2)
{
if(min==0)
min=59;
else
min--;
write_ds(2min);
write_sfm(7min);
write_com(0x80+0x40+8);
}


if(count==3)
{
if(hour==0)
hour=23;
else
hour--;
write_ds(4hour);
write_sfm(4hour);
write_com(0x80+0x40+5);
}
if(count==5)
{

if(nian==0)
nian=99;
else
nian--;
write_ds(9nian);
write_calendar(3nian);
write_com(0x80+4);

}
if(count==6)
{

if(yue==1)
yue=12;
else
yue--;
write_ds(8yue);
write_calendar(6yue);
write_com(0x80+7);
}


if(count==7) // 判断闰年
{
ri--;
week--;
if(nian%4==0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==0)
ri=30;
}
else if(yue==2)
{
if(ri==0)
ri=29;
}
else
{
if(ri==0)
ri=31;
}
}

if(nian%4!=0)
{
if((yue==4)||(yue==6)||(yue==9)||(yue==11))
{
if(ri==0)
ri=30;
}
else if(yue==2)
{
if(ri==0)
ri=28;
}
else
{
if(ri==0)
ri=31;
}
}
write_ds(7ri);
write_calendar(9ri);
write_com(0x80+10);
delayxms(2);
if(week==-1) 
week=7;
write_week(week);
write_ds(6week);


}


}
}
}

//----------------初始化---------------------------------//
void init()
{
lcdinit();

disp();
week=0;
nian=11;
yue=9;
ri=1;

}


//---------------------------流水灯-----------------------------------//
void lampinit()
{
P1=0xff;
wela1=1;
wela2=1;
wela3=1;
wela3=1;
wela1=0;
wela2=0;
wela3=0;
wela4=0;

}
//----------------时钟用黄灯显示程序-------------------------------//
void clock()
{
if((hour==1)&&(hour==13))
{
P1=0xfd;
wela3=1;
wela3=0;
}

if((hour==2)&&(hour==14))
{
P1=0xfb;
wela3=1;
wela3=0;
}

if((hour==3)&&(hour==15))
{
P1=0xf7;
wela3=1;
wela3=0;
}

if((hour==4)&&(hour==16))
{
P1=0xef;
wela3=1;
wela3=0;
}
if((hour==5)&&(hour==17))
{
P1=0xdf;
wela3=1;
wela3=0;
}
if((hour==6)&&(hour==18))
{
P1=0xfe;
wela4=1;
wela4=0;
}
if((hour==7)&&(hour==19))
{
P1=0xfd;
wela4=1;
wela4=0;
}
if((hour==8)&&(hour==20))
{
P1=0xfb;
wela4=1;
wela4=0;
}
if((hour==9)&&(hour=21))
{
P1=0xf7;
wela4=1;
wela4=0;
}
if((hour==10)&&(hour==22))
{
P1=0xef;
wela4=1;
wela4=0;
}
if((hour==11)&&(hour==23))
{
P1=0xdf;
wela4=1;
wela4=0;
}
if((hour==12)&&(hour==0))
{
P1=0xfe;
wela3=1;
wela3=0;
}


if(min<5)
{
if((hour!=12)&&(hour!=24))
{
P1=0xfe;
wela1=1;
wela1=0;
}
}
//----------------分钟用红灯显示------------------------//

if((min>=5)&&(min<10))
{
if((hour!=13)&&(hour!=1))
{
P1=0xfd;
wela1=1;
wela1=0;
}
}

if((min>=10)&&(min<15))
{
if((hour!=14)&&(hour!=2))
{
P1=0xfb;
wela1=1;
wela1=0;
}
}

if((min>=15)&&(min<20))
{
if((hour!=15)&&(hour!=3))
{
P1=0xf7;
wela1=1;
wela1=0;
}
}

if((min>=20)&&(min<25))
{
if((hour!=16)&&(hour!=4))
{
P1=0xef;
wela1=1;
wela1=0;
}
}


if((min>=25)&&(min<30))
{
if((hour!=17)&&(hour!=5))
{
P1=0xdf;
wela1=1;
wela1=0;
}
}

if((min>=30)&&(min<35))
{
if((hour!=18)&&(hour!=6))
{
P1=0xfe;
wela2=1;
wela2=0;
}
}

if((min>=35)&&(min<40))
{
if((hour!=19)&&(hour!=7))
{
P1=0xfd;
wela2=1;
wela2=0;
}
}


if((min>=40)&&(min<45))
{
if((hour!=20)&&(hour!=8))
{
P1=0xfb;
wela2=1;
wela2=0;
}
}

if((min>=45)&&(min<50))
{
if((hour!=21)&&(hour!=9))
{
P1=0xf7;
wela2=1;
wela2=0;
}
}

if((min>=50)&&(min<55))
{
if((hour!=22)&&(hour!=10))
{
P1=0xef;
wela2=1;
wela2=0;
}
}
if(min>=55)
{
if((hour!=23)&&(hour!=11))
{
P1=0xdf;
wela2=1;
wela2=0;
}
}

}
//---------------考试倒计时模式-----------------------//

void test()
{
uchar hour1min1min2shi;
hour1=hour+2;
if(hour==24)
hour1=0;
if(hour==25)
hour1=1;

min1=min+20;
if(min1>=60)
{
min1=min1-60;
hour1=hour1+1;
if(hour1==24)
hour1=0;
}

shi=min1/10;
min1=shi*10;



if((min==min1)&&(sec==0))
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfe;
wela3=1;
wela3=0;

}



if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfc;
wela1=1;
wela1=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf8;
wela1=1;
wela1=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf0;
wela1=1;
wela1=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xe0;
wela1=1;
wela1=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xc0;
wela1=1;
wela1=0;

}
//-------------------------------------------------//
if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfe;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xfc;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf8;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xf0;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xe0;
wela2=1;
wela2=0;

}

if(min==min2)
{
min2=min+5;
if(min2==60)
min2=0;
P1=0xc0;
wela2=1;
wela2=0;

}
//----------------------时间到后开始响铃------------------------------------------//
if(min==min2)
{

P1=0;
wela1=1;
wela1=0;
beep=0;
delayxms(1000);
beep=1;
delayxms(1000);
beep=0;
delayxms(1000);
beep=1;
beep=0;
delayxms(1000);
beep=1;
delayxms(1000);
beep=0;
delayxms(6000);
delayxms(6000);
beep=1;

lampinit();

}
}




//-----------------主函数--------------------------------------//
void main()
{
init();
while(1)
{

keyscan();


if(count==0)
{
sec=read_ds(0);
min=read_ds(2);
hour=read_ds(4);
week=read_ds(6);
nian=read_ds(9);
yue=read_ds(8);
ri=read_ds(7);
write_sfm(10sec);
write_sfm(7min);
write_sfm(4hour);
write_week(week);

write_calendar(3nian);
write_calendar(6yue);
write_calendar(9ri);
write_calendar(120);

}

}

}
相关推荐

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:博客之星2020 设计师:CSDN官方博客 返回首页

打赏作者

nineheaded_bird

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值