本程序借鉴了小蜜蜂老师的代码风格。
记录下自己学习过程中的代码。
由于本人水平有限,这也是我做的第一套真题,所以代码可能显得有点蠢,部分地方也比较繁琐,好在功能大体上是实现了(不过在时间和闹钟相同的那一秒里按什么按键都无法停止闪烁,这一点我也懒得改了,其他的地方问题不大)
代码
main.c
#include "reg52.h"
#include "ds1302.h"
#include "onewire.h"
sfr AUXR=0x8e;
unsigned char write[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char read[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char time[7]={0x55,0x59,0x23,0x15,0x02,0x03,0x24};
unsigned char temp[3]={0x50,0x59,0x23}; //时间初始化
unsigned char temp2[3]={0x00,0x00,0x00}; //闹钟初始化
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
void HC573(unsigned char a,unsigned char b)
{
P0=b;
switch(a)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
case 0:
P2=(P2&0x1f)|0x00;
break;
}
P2=(P2&0x1f)|0x00;
}
void Delay(unsigned int t) //延时
{
while(t--);
}
void DisplaySMG(unsigned char pos,unsigned char dat) //单个数码管显示
{
HC573(6,(0x01<<pos));
HC573(7,dat);
Delay(500);
HC573(6,(0x01<<pos));
HC573(7,0xff);
}
void Init1() //时钟初始化
{
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_Ds1302_Byte(write[i],time[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
void Read1() //读取时间
{
unsigned char i;
for(i=0;i<7;i++)
{
time[i]=Read_Ds1302_Byte(read[i]);
}
}
unsigned char temperature=0;
void Read_Tem() //读取温度
{
unsigned char MSB,LSB;
unsigned int tem=0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay(1000);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
tem=MSB;
tem=(tem<<8)|LSB;
if((tem&0xf800)==0x0000)
temperature=tem*0.0625;
}
unsigned char mode=1; //显示状态
unsigned char n1=0; //时钟选择位
unsigned char smg=0; //数码管闪烁
unsigned char led=0xff; //led状态
unsigned char n2=0; //闹钟选择位
unsigned char shan=0; //led闪烁控制
void Display()
{
switch(mode)
{
case 1: //时间显示
Read1();
DisplaySMG(0,SMG_NoDot[(time[2]/16)]);
DisplaySMG(1,SMG_NoDot[(time[2]%16)]);
DisplaySMG(2,SMG_NoDot[16]);
DisplaySMG(3,SMG_NoDot[(time[1]/16)]);
DisplaySMG(4,SMG_NoDot[(time[1]%16)]);
DisplaySMG(5,SMG_NoDot[16]);
DisplaySMG(6,SMG_NoDot[(time[0]/16)]);
DisplaySMG(7,SMG_NoDot[(time[0]%16)]);
break;
case 2: //时间设置
if(n1==1) //选中小时
{
if(smg)
{
DisplaySMG(0,SMG_NoDot[(temp[2]/16)]);
DisplaySMG(1,SMG_NoDot[(temp[2]%16)]);
}
else
{
DisplaySMG(0,0xff);
DisplaySMG(1,0xff);
}
}
else
{
DisplaySMG(0,SMG_NoDot[(temp[2]/16)]);
DisplaySMG(1,SMG_NoDot[(temp[2]%16)]);
}
DisplaySMG(2,SMG_NoDot[16]);
if(n1==2) //选中分钟
{
if(smg)
{
DisplaySMG(3,SMG_NoDot[(temp[1]/16)]);
DisplaySMG(4,SMG_NoDot[(temp[1]%16)]);
}
else
{
DisplaySMG(3,0xff);
DisplaySMG(4,0xff);
}
}
else
{
DisplaySMG(3,SMG_NoDot[(temp[1]/16)]);
DisplaySMG(4,SMG_NoDot[(temp[1]%16)]);
}
DisplaySMG(5,SMG_NoDot[16]);
if(n1==3) //选中秒钟
{
if(smg)
{
DisplaySMG(6,SMG_NoDot[(temp[0]/16)]);
DisplaySMG(7,SMG_NoDot[(temp[0]%16)]);
}
else
{
DisplaySMG(6,0xff);
DisplaySMG(7,0xff);
}
}
else
{
DisplaySMG(6,SMG_NoDot[(temp[0]/16)]);
DisplaySMG(7,SMG_NoDot[(temp[0]%16)]);
}
break;
case 3: //闹钟设置
if(n2==1) //选中小时
{
if(smg)
{
DisplaySMG(0,SMG_NoDot[(temp2[2]/16)]);
DisplaySMG(1,SMG_NoDot[(temp2[2]%16)]);
}
else
{
DisplaySMG(0,0xff);
DisplaySMG(1,0xff);
}
}
else
{
DisplaySMG(0,SMG_NoDot[(temp2[2]/16)]);
DisplaySMG(1,SMG_NoDot[(temp2[2]%16)]);
}
DisplaySMG(2,SMG_NoDot[16]);
if(n2==2) //选中分钟
{
if(smg)
{
DisplaySMG(3,SMG_NoDot[(temp2[1]/16)]);
DisplaySMG(4,SMG_NoDot[(temp2[1]%16)]);
}
else
{
DisplaySMG(3,0xff);
DisplaySMG(4,0xff);
}
}
else
{
DisplaySMG(3,SMG_NoDot[(temp2[1]/16)]);
DisplaySMG(4,SMG_NoDot[(temp2[1]%16)]);
}
DisplaySMG(5,SMG_NoDot[16]);
if(n2==3) //选中秒钟
{
if(smg)
{
DisplaySMG(6,SMG_NoDot[(temp2[0]/16)]);
DisplaySMG(7,SMG_NoDot[(temp2[0]%16)]);
}
else
{
DisplaySMG(6,0xff);
DisplaySMG(7,0xff);
}
}
else
{
DisplaySMG(6,SMG_NoDot[(temp2[0]/16)]);
DisplaySMG(7,SMG_NoDot[(temp2[0]%16)]);
}
break;
case 4: //显示温度
Read_Tem();
DisplaySMG(5,SMG_NoDot[temperature/10]);
DisplaySMG(6,SMG_NoDot[temperature%10]);
DisplaySMG(7,SMG_NoDot[12]);
break;
}
}
void Init2(void) //50毫秒@11.0592MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x4C; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA=1;
ET0=1;
}
unsigned char t1=0,t2=0,t3=0;
void Service() interrupt 1
{
if(shan==1)
{
t1++;
if(t1==4) //0.2s
{
if((led&0x01)==0x01)
led&=~0x01;
else
led|=0x01;
t1=0;
}
t2++;
if(t2==100) //5s
{
shan=0;
t2=0;
}
}
if((mode==2)||(mode==3))
{
t3++;
if(t3==20) //1s
{
smg=~smg;
t3=0;
}
}
}
void Add() //加法
{
if(mode==2)
{
switch(n1)
{
case 1:
temp[2] = (temp[2]/16)*10 + temp[2]%16; //BCD码转十进制
temp[2]++;
if(temp[2]>23)
temp[2]=0;
temp[2]=(temp[2]/10)*16+temp[2]%10; //十进制转BCD码
break;
case 2:
temp[1] = (temp[1]/16)*10 + temp[1]%16;
temp[1]++;
if(temp[1]>59)
temp[1]=0;
temp[1]=(temp[1]/10)*16+temp[1]%10;
break;
case 3:
temp[0] = (temp[0]/16)*10 + temp[0]%16;
temp[0]++;
if(temp[0]>59)
temp[0]=0;
temp[0]=(temp[0]/10)*16+temp[0]%10;
break;
}
}
if(mode==3)
{
switch(n2)
{
case 1:
temp2[2] = (temp2[2]/16)*10 + temp2[2]%16;
temp2[2]++;
if(temp2[2]>23)
temp2[2]=0;
temp2[2]=(temp2[2]/10)*16+temp2[2]%10;
break;
case 2:
temp2[1] = (temp2[1]/16)*10 + temp2[1]%16;
temp2[1]++;
if(temp2[1]>59)
temp2[1]=0;
temp2[1]=(temp2[1]/10)*16+temp2[1]%10;
break;
case 3:
temp2[0] = (temp2[0]/16)*10 + temp2[0]%16;
temp2[0]++;
if(temp2[0]>59)
temp2[0]=0;
temp2[0]=(temp2[0]/10)*16+temp2[0]%10;
break;
}
}
}
void Sub() //减法
{
if(mode==2)
{
switch(n1)
{
case 1:
temp[2] = (temp[2]/16)*10 + temp[2]%16;
temp[2]--;
if(temp[2]==255)
temp[2]=23;
temp[2]=(temp[2]/10)*16+temp[2]%10;
break;
case 2:
temp[1] = (temp[1]/16)*10 + temp[1]%16;
temp[1]--;
if(temp[1]==255)
temp[1]=59;
temp[1]=(temp[1]/10)*16+temp[1]%10;
break;
case 3:
temp[0] = (temp[0]/16)*10 + temp[0]%16;
temp[0]--;
if(temp[0]==255)
temp[0]=59;
temp[0]=(temp[0]/10)*16+temp[0]%10;
break;
}
}
if(mode==3)
{
switch(n2)
{
case 1:
temp2[2] = (temp2[2]/16)*10 + temp2[2]%16;
temp2[2]--;
if(temp2[2]==255)
temp2[2]=23;
temp2[2]=(temp2[2]/10)*16+temp2[2]%10;
break;
case 2:
temp2[1] = (temp2[1]/16)*10 + temp2[1]%16;
temp2[1]--;
if(temp2[1]==255)
temp2[1]=59;
temp2[1]=(temp2[1]/10)*16+temp2[1]%10;
break;
case 3:
temp2[0] = (temp2[0]/16)*10 + temp2[0]%16;
temp2[0]--;
if(temp2[0]==255)
temp2[0]=59;
temp2[0]=(temp2[0]/10)*16+temp2[0]%10;
break;
}
}
}
void LED_Shan() //led闪烁
{
if(shan==1)
{
HC573(4,led);
}
else
HC573(4,0xff);
}
void Alarm() //闹钟判断
{
if((temp[2]==temp2[2])&&(temp[1]==temp2[1])&&(temp[0]==temp2[0])) //闹钟与时间相同
{
shan=1;
}
LED_Shan();
}
sbit S4=P3^3;
sbit S5=P3^2;
sbit S6=P3^1;
sbit S7=P3^0;
void Scan() //按键检测
{
int i=0;
if(S7==0)
{
Delay(100);
if(S7==0)
{
shan=0;
if(shan==0)
{
if(mode==1)
mode=2; //时钟设置
if(mode==2)
{
n1++;
if(n1==4)
{
n1=0;
mode=1;
Write_Ds1302_Byte(0x8e,0x00);
for(i=0;i<3;i++)
{
Write_Ds1302_Byte(write[i],temp[i]); //将设置的时间写入
}
Write_Ds1302_Byte(0x8e,0x80);
}
}
}
while(S7==0)
Display();
}
}
if(S6==0)
{
Delay(100);
if(S6==0)
{
shan=0;
if(shan==0)
{
if(mode==1)
mode=3;
if(mode==3) //闹钟设置
{
n2++;
if(n2==4)
{
mode=1;
n2=0;
Write_Ds1302_Byte(0x8e,0x00);
for(i=0;i<3;i++)
{
Write_Ds1302_Byte(write[i],temp[i]); //将设置闹钟前的时间写入
}
Write_Ds1302_Byte(0x8e,0x80);
}
}
}
while(S6==0)
Display();
}
}
if(S5==0)
{
Delay(100);
if(S5==0)
{
shan=0;
if(shan==0)
Add(); //加一
while(S5==0)
{
Display();
}
}
}
if(S4==0)
{
Delay(100);
if(S4==0)
{
shan=0;
if(shan==0)
Sub(); //减一
while(S4==0)
{
if(mode==1)
{
mode=4; //显示温度
}
Display();
}
if(mode==4)
mode=1;
}
}
}
void Init()
{
HC573(0,0x00);
HC573(5,0x00);
HC573(4,0xff);
HC573(6,0xff);
HC573(7,0xff);
Init1();
Init2();
}
void App()
{
Read1();
if(mode==1) //实时更新状态2下需要设置的时间
{
temp[0]=time[0];
temp[1]=time[1];
temp[2]=time[2];
}
Alarm();
}
void main()
{
Init();
while(1)
{
Scan();
App();
Display();
}
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include "reg52.h"
sbit DQ = P1^4;
unsigned char rd_temperature(void);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
onewire.c
记得修改延时函数
#include "onewire.h"
//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{
t*=12;
while(t--);
}
//单总线写操作
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//单总线读操作
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
#include <reg52.h>
#include <intrins.h>
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
#endif
ds1302.c
include "ds1302.h"
//写字节
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//向DS1302寄存器写入数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//从DS1302寄存器读出数据
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}