一、硬件
单片机、DS18B20、实时时钟、数码管、独立按键、led
二、功能描述
3.1 初始化
1)关闭蜂鸣器、继电器等无关外设;
2)设备初始化时钟为23 时59 分50 秒,闹钟提醒时间0 时0 分0 秒。
3.2 显示功能
1) 时间显示格式
1 2 - 0 0 - 0 2
12 时间隔0 分间隔2 秒
2) 温度显示格式
8 8 8 8 8 2 1 C
熄灭 温度
3.3 按键功能
1)按键S7 定义为“时钟设置”按键,通过该按键可切换选择待调整的时、分、秒,当前选择的显示单元以1 秒为间隔亮灭,时、分、秒、时钟显示的调整需注意数据边界属性。
2)按键S6 定义为“闹钟设置”按键,通过该按键可进入闹钟时间设置功能,数码管显示当前设定的闹钟时间。
3) 按键S5 定义为“加”按键,在“时钟设置” 或“闹钟设置” 状态下,每次按下该按键当前选择的单元(时、分或秒)增加1 个单位。
4) 按键S4 定义为“减”按键,在“时钟设置” 或“闹钟设置” 状态下,每次按下该按键当前选择的单元(时、分或秒)减少1 个单位。
5) 按键功能说明:按键S4、S5 的“加”、“减”功能只在“时钟设置”或“闹钟设置”状态下有效;在“时钟显示”状态下,按下S4 按键,显示温度数据,松开按键,返回“时钟显示”界面。
3.4 闹钟提示功能
1)指示灯L1 以0.2 秒为间隔闪烁,持续5 秒钟;
2)闹钟提示状态下,按下任意按键,关闭闪烁提示功能。
三、代码
#include
#include
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6; //控制数码管的段选端:当前数码管选中的发光段
sbit wela=P2^7; //控制数码管的位选端:选用什么位置的数码管
sbit led=P1^0;
sbit s4=P3^6; //减少键、显示温度键
sbit s5=P3^7; //增加键
sbit s2=P3^4; //“闹钟设置”按键
sbit s3=P3^5; //“时钟设置”按键
sbit DS=P2^2; //ds温度传感器
sbit buzzer=P2^3; //蜂鸣器
uint temp; //温度参数
unsigned char flag = 0; //判断数码管的闪烁
uchar flag1,shi1,ge1,shi2,ge2,shi3,ge3; //时分秒的个十位
uchar aa,aa1,hour=23,min=59,second=57; //时钟初始化: 23:59:50
uchar nhour=0,nmin=0,nsecond=0; //闹钟初始化: 00:00:00
uchar code table[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00}; //定义对应0~9,最后一个是是熄灭数码管
/***************************************************/
/* *******温度器******* */
/***************************************************/
void delay1(uint count) //延时函数
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
void dsreset(void) //初始化函数,温度传感器复位
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) //读一位数据函数
{
uint i;
bit dat;
DS=0;i++; //i++起到延时作用
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //读一个字节数据函数
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出数据最低位在最前面,这样刚好1字节在dat里
}
return(dat);
}
void tmpwritebyte(uchar dat) //向DS18B20写入一字节数据函数
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //写1
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{ //写0
DS=0;
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //获取温度
{
dsreset();
delay1(1);
tmpwritebyte(0xcc); //写跳过读rom指令
tmpwritebyte(0x44); //写温度转换指令
}
uint tmp() //读取寄存器中存储的温度数据
{
float tt;
uchar a,b;
dsreset();
delay1(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread(); //读低8位
b=tmpread(); //读高8位
temp=b;
temp<<=8; //两个字节组合为一个字
temp=temp|a;
tt=temp*0.0625; //温度在寄存器中为12位,分辨率为0.0625度
temp=tt*10+0.5; //乘以10,表示为小数后面只取一位,加0.5是四舍五入
return temp;
}
void DSdisplay(uint temp) //显示温度函数
{
uchar A1,A2,A2t;
A1=temp/100;
A2t=temp%100;
A2=A2t/10;
dula=1;
P0=table[A1];
dula=0;
wela=1;
P0=0xf7;
wela=0;
delay1(1);
dula=1;
P0=table[A2];
dula=0;
wela=1;
P0=0xef;
wela=0;
delay1(1);
dula=1;
P0=0x58;
dula=0;
wela=1;
P0=0xdf;
wela=0;
delay1(1);
}
void wendu() //按键显示温度主函数
{
if(!s4)
{
delay1(10);
if(!s4)
{
uchar a=25;
tmpchange();
while(a>0)
{
a--;
DSdisplay(tmp());
}
while(!s4);
}
}
}
/***************************************************/
/* *******时钟******* */
/***************************************************/
void inint() //定时器的设置
{ //使用定时器0和1
TMOD=0x11;
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
TH1=(65536-45872)/256;
TL1=(65536-45872)%256;
EA=1;
ET0=1; //打开T0定时器中断
ET1=1; //打开T1定时器中断
TR0=1; //开始启用T0计数器/定时器
TR1=1; //开始启用T1计数器/定时器
}
void delay(uint z) //毫秒延时函数
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void displayhour(uchar h) //显示小时函数
{
if(h==-1)
{
dula=1;
P0=table[10];
dula=0;
wela=1;
P0=0xfe;
wela=0;
delay(2);
dula=1;
P0=table[10];
dula=0;
wela=1;
P0=0xfd;
wela=0;
delay(2);
}
else
{
shi1=h/10;
ge1=h%10;
dula=1;
P0=table[shi1];
dula=0;
wela=1;
P0=0xfe;
wela=0;
delay(2);
dula=1;
P0=table[ge1]|0x80;
dula=0;
wela=1;
P0=0xfd;
wela=0;
delay(2);
}
}
void displaymin(uchar m) //显示分钟函数
{
if(m==-1)
{
dula=1;
P0=table[10];
dula=0;
wela=1;
P0=0xfb;
wela=0;
delay(2);
dula=1;
P0=table[10];
dula=0;
wela=1;
P0=0xf7;
wela=0;
delay(2);
}
else
{
shi2=m/10;
ge2=m%10;
dula=1;
P0=table[shi2];
dula=0;
wela=1;
P0=0xfb;
wela=0;
delay(2);
dula=1;
P0=table[ge2]|0x80;
dula=0;
wela=1;
P0=0xf7;
wela=0;
delay(2);
}
}
void displaysecond(uchar s) //显示秒钟函数
{
if(s==-1)
{
dula=1;
P0=table[10];
dula=0;
wela=1;
P0=0xef;
wela=0;
delay(2);
dula=1;
P0=table[10];
dula=0;
wela=1;
P0=0xdf;
wela=0;
delay(2);
}
else
{
shi3=s/10;
ge3=s%10;
dula=1;
P0=table[shi3];
dula=0;
wela=1;
P0=0xef;
wela=0;
delay(2);
dula=1;
P0=table[ge3];
dula=0;
wela=1;
P0=0xdf;
wela=0;
delay(2);
}
}
void naozhong() //闹钟函数
{
uint n=15;
if(hour==nhour&&min==nmin&&second==nsecond)
while(n--)
{
if(s5==0||s4==0||s2==0||s3==0)
{
delay(10);
if(s5==0||s4==0||s2==0||s3==0)
{
while((!s4)||(!s5)||(!s2)||(!s3));
break;
}
}
displayhour(hour);
displaymin(min);
displaysecond(second);
led=0;
delay(200);
led=1;
delay(200);
}
}
/***************时钟设置键*****************/
void key7()
{
uchar n=1;
ET0=0; //中断定时器0
while(1)
{
if(n==1)
{
while(1)
{
if(s3==0)
{
delay(10);
if(s3==0)
{
while(!s3);
n++;
break;
}
}
if(flag==1)displayhour(hour); //闪烁数码管
else displayhour(-1);
displaymin(min);
displaysecond(second);
if(s5==0)
{
delay(10);
if(s5==0)
{
while(!s5);
hour++;
if(hour==24)hour=0;
}
}
if(s4==0)
{
delay(10);
if(s4==0)
{
while(!s4);
hour--;
if(hour==-1)hour=23;
}
}
}
}
else if(n==2)
{
while(1)
{
if(s3==0)
{
delay(10);
if(s3==0)
{
while(!s3);
n++;
break;
}
}
if(flag==1)displaymin(min);
else displaymin(-1);
displayhour(hour);
displaysecond(second);
if(s5==0)
{
delay(10);
if(s5==0)
{
while(!s5);
min++;
if(min==60)min=0;
}
}
if(s4==0)
{
delay(10);
if(s4==0)
{
while(!s4);
min--;
if(min==-1)min=59;
}
}
}
}
else if(n==3) //?????
{
while(1)
{
if(s3==0)
{
delay(10);
if(s3==0)
{
while(!s3);
n++;
break;
}
}
if(flag==1)displaysecond(second);
else displaysecond(-1);
displayhour(hour);
displaymin(min);
if(s5==0)
{
delay(10);
if(s5==0)
{
while(!s5);
second++;
if(second==60)second=0;
}
}
if(s4==0)
{
delay(10);
if(s4==0)
{
while(!s4);
second--;
if(second==-1)second=59;
}
}
}
}
if(n>=4)break;
}
ET0=1; //开启定时器1
}
/***************闹钟设置键*******************/
void key6()
{ uchar n=1;
while(1)
{
if(n==1)
{
while(1)
{
if(s2==0)
{
delay(10);
if(s2==0)
{
while(!s2);
n++;
break;
}
}
if(flag==1)displayhour(nhour);
else displayhour(-1);
displaymin(nmin);
displaysecond(nsecond);
if(s5==0)
{
delay(10);
if(s5==0)
{
while(!s5);
nhour++;
if(nhour==24)nhour=0;
}
}
if(s4==0)
{
delay(10);
if(s4==0)
{
while(!s4);
nhour--;
if(nhour==-1)nhour=23;
}
}
}
}
else if(n==2)
{
while(1)
{
if(s2==0)
{
delay(10);
if(s2==0)
{
while(!s2);
n++;
break;
}
}
if(flag==1)displaymin(nmin);
else displaymin(-1);
displayhour(nhour);
displaysecond(nsecond);
if(s5==0)
{
delay(10);
if(s5==0)
{
while(!s5);
nmin++;
if(nmin==60)nmin=0;
}
}
if(s4==0)
{
delay(10);
if(s4==0)
{
while(!s4);
nmin--;
if(nmin==-1)nmin=59;
}
}
}
}
else if(n==3) //?????
{
while(1)
{
if(s2==0)
{
delay(10);
if(s2==0)
{
while(!s2);
n++;
break;
}
}
if(flag==1)displaysecond(nsecond);
else displaysecond(-1);
displayhour(nhour);
displaymin(nmin);
if(s5==0)
{
delay(10);
if(s5==0)
{
while(!s5);
nsecond++;
if(nsecond==60)nsecond=0;
}
}
if(s4==0)
{
delay(10);
if(s4==0)
{
while(!s4);
nsecond--;
if(nsecond==-1)nsecond=59;
}
}
}
}
if(n>=4)break;
}
}
void main()
{
inint(); //初始化
buzzer=1; //初始化蜂鸣器
while(1)
{
displayhour(hour);
displaymin(min);
displaysecond(second);
if(0==s2) //闹钟设置
{
delay(10);
if(0==s2)
{
while(!s2);
key6();
}
}
if(0==s3) //时钟设置
{
delay(10);
if(0==s3)
{
while(!s3);
key7();
}
}
naozhong();
wendu();
}
}
void zhongduan1() interrupt 1 //定时器0中断
{
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
aa++;
if(aa==20)
{
aa=0;
second++;
if(second==60)
{
second=0;
min++;
if(min==60)
{
min=0;
hour++;
}
}
if(hour==24 && second==0)
{
hour=0;
min=0;
second=0;
}
}
}
void zhongduan2() interrupt 3 //定时器1中断
{
TH1=(65536-45872)/256;
TL1=(65536-45872)%256;
aa1++;
if(aa1==20)
{
aa1=0;
if(flag==0) flag=1;
else flag=0;
}
}