当前位置:文档之家› 基于单片机DS1302的时钟万年历(带闹钟)

基于单片机DS1302的时钟万年历(带闹钟)

基于单片机DS1302的时钟万年历(带闹钟)
基于单片机DS1302的时钟万年历(带闹钟)

#include

#define uchar unsigned char

#define uint unsigned int

sbit lcdws=P2^1; //1602管脚定义

sbit lcden=P2^0;

sbit lcdrs=P2^2;

sbit key1=P2^3; //闹钟设置键

sbit key2=P2^4;

sbit key3=P1^5;//功能键定义

sbit key4=P1^6;//增大键定义

sbit key5=P1^7;//减小键定义

uchar shi,fen,miao,ashi,afen,amiao,year,month,day,week; uchar s1num=0,s1num2=0,temp;

bit flag;

float f_temp;

uint i,d;

uchar code table2[]={0x20,0x20,0x2e,0x20,0xdf,0x43};

uchar code table[]="20 - - ";

uchar code table1[]=" : : ";

sbit ds=P1^0;//ds18b20信号线

sbit beep=P1^4; //蜂鸣器管脚定义

sbit ACC_7 = ACC^7; //位寻址寄存器定义

sbit SCLK = P1^2; // DS1302时钟信号sbit DIO= P1^1; // DS1302数据信号sbit CE = P1^3;

//地址、数据发送子程序

//void delay2(uint ms)

// {

// uchar t;

// while(ms--); for(t=0;t<120;t++);

//}

// void playmusic()

// {

// uint i2=0,j2,k2;

// while(jiepai[i2]!=0||song[i2]!=0)

// {

// for(j2=0;j2

// {

// beep=~beep;

// for(k2=0;k2

// }

// delay2(10);

// i2++;

// }

// }

void write_1302( uchar addr,uchar dat )

{

uchar i,temp;

CE=0; //CE 引脚为低,数据传送中止

SCLK=0; //清零时钟总线

CE = 1; //CE 引脚为高,逻辑控制有效

//发送地址

for ( i=8; i>0; i-- ) //循环8次移位

{

SCLK = 0;

temp = addr;

DIO = (bit)(temp&0x01); //每次传输低字节

addr >>= 1; //右移一位

SCLK = 1;

}

//发送数据

for ( i=8; i>0; i-- )

{

SCLK = 0;

temp = dat;

DIO = (bit)(temp&0x01);

dat >>= 1;

SCLK = 1;

}

CE = 0;

}

//数据读取子程序

uchar Read1302 ( uchar addr )

{

unsigned char i,temp,dat1,dat2;

CE=0;

SCLK=0;

CE = 1;

//发送地址

for ( i=8; i>0; i-- ) //循环8次移位

{

SCLK = 0;

temp = addr;

DIO = (bit)(temp&0x01); //每次传输低字节

addr >>= 1; //右移一位

SCLK = 1;

//读取数据

for ( i=8; i>0; i-- )

{

ACC_7=DIO;

SCLK = 1;

ACC>>=1;

SCLK = 0;

}

CE=0;

dat1=ACC;

dat2=dat1/16; //数据进制转换

//十六进制转十进制

dat1=dat1%16;

dat1=dat1+dat2*10;

return (dat1);

}

//初始化DS1302

void Initial(void) //初始化1302 2010年09月30日23点58分56秒星期一{

write_1302 (0x8e,0x00); //允许写保护

write_1302 (0x80,0x56); //秒位初始化

write_1302 (0x82,0x58); //分钟初始化

write_1302 (0x84,0x23); //小时初始化

write_1302 (0x86,0x30); //日初始化

write_1302 (0x88,0x09); //月初始化

write_1302 (0x8c,0x10); //年初始化

write_1302 (0x8a,0x01); //日期始化

write_1302 (0x8e,0x80); //禁止写保护

}

void delay(uint z)//延时1ms

{

uint x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}

void write_com(uchar com)//1602写命令

{

lcdrs=0;

lcden=0;

P0=com;

delay(5);

lcden=1;

lcden=0;

}

void write_data(uchar date)//1602写数据

{

lcdrs=1;

lcden=0;

P0=date;

delay(5);

lcden=1;

delay(5);

lcden=0;

}

void dsreset(void) //DS18B20,初始化函数{

uint i;

ds=0;

i=103;

while(i>0)i--;

ds=1;

i=4;

while(i>0)i--;

}

bit tempreadbit(void)//读1位数据函数

{

uint i;

bit dat;

ds=0;i++;

ds=1;i++;i++;//i++起到延时作用

dat=ds;

i=8;while(i>0)i--;

return(dat);

}

uchar tempread(void) //读一个字节数据函数{

uchar i,j,dat;

dat=0;

for(i=1;i<=8;i++)

{

j=tempreadbit();

dat=(j<<7)|(dat>>1);

}

return(dat);

}

void tempwritebyte(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

{

ds=0; //写0

i=8;while(i>0)i--;

ds=1;

i++;i++;

}

}

}

void tempchange(void) //DS18B20开始获取温度并转换

{

dsreset();

delay(1);

tempwritebyte(0xcc);

tempwritebyte(0x44);

}

uint get_temp() //获取温度

{

uchar a,b;

dsreset();

delay(1);

tempwritebyte(0xcc);

tempwritebyte(0xbe);

a=tempread(); //读高8位

b=tempread(); //读低8位

temp=b;

temp<<=8; //两个字节组合成1个字节

temp=temp|a;

f_temp=temp*0.0625;

temp=f_temp*10+0.5;

f_temp=f_temp+0.05; //温度在寄存器中为12位,分辨率为0.0625^ return temp;

}

void display(uchar addr,uchar dat)

{

write_com(0x80+0x40+addr);

write_data(0x30+dat);

delay(5);

}

void dis_temp(uint t)

{

uchar i;

i=t/100;

display(10,i);

i=t%100/10;

display(11,i);

i=t%100%10;

display(13,i);

}

void init()//初始化程序

{

uchar num;

flag=1;

lcden=0;

write_com(0x38);

write_com(0x0c);

write_com(0x06);

write_com(0x01);

write_com(0x80);

for(num=0;num<15;num++)

{

write_data(table[num]);

delay(5);

}

write_com(0x80+0x40);

for(num=0;num<8;num++)

{

write_data(table1[num]);

delay(5);

}

write_com(0x80+0x40+10);

for(num=0;num<6;num++)

{

write_data(table2[num]);

delay(10);

}

}

void di()//蜂鸣器响函数

{

beep=0;

delay(100);

beep=1;

}

void write_sfm(uchar add,uchar date)

{

uchar shi,ge;

shi=date/10;

ge=date%10;

write_com(0x80+0x40+add);

write_data(0x30+shi);

write_data(0x30+ge);

}

void write_nyrz(uchar add,uchar date)//显示年,月,日,周{

uchar shi,ge;

shi=date/10;

ge=date%10;

write_com(0x80+add);

write_data(0x30+shi);

write_data(0x30+ge);

}

void display_week(uchar we)

{

write_com(0x80+12);

switch(we)

{

case 1: write_data('M');delay(5);

write_data('O');delay(5);

write_data('N');

break;

case 2: write_data('T');delay(5);

write_data('U');delay(5);

write_data('E');

break;

case 3: write_data('W');delay(5);

write_data('E');delay(5);

write_data('D');

break;

case 4: write_data('T');delay(5);

write_data('H');delay(5);

write_data('U');

break;

case 5: write_data('F');delay(5);

write_data('R');delay(5);

write_data('T');

break;

case 6: write_data('S');delay(5);

write_data('A');delay(5);

write_data('T');

break;

case 7: write_data('S');delay(5);

write_data('U');delay(5);

write_data('N');

break;

}

}

void keyscan()//按键设置

{

if(key3==0)//功能键按下

{

flag=0;

delay(5);

if(key3==0)

{

s1num++;

while(!key3);

di();

switch(s1num)//光标闪烁定位

{

case 1:write_com(0x80+0x40+7);//定位到秒的位置

write_com(0x0f);

break;

case 2:write_com(0x80+0x40+4);//定位到分的位置

write_com(0x0f);

break;

case 3:write_com(0x80+0x40+1);//定位到小时的位置

write_com(0x0f);

break;

case 4:write_com(0x80+0x0e);//定位到星期的位置

write_com(0x0f);

break;

case 5:write_com(0x80+0x9);//定位到日的位置

write_com(0x0f);

break;

case 6:write_com(0x80+0x6);//定位到月的位置

write_com(0x0f);

break;

case 7:write_com(0x80+0x3);//定位到年的位置

write_com(0x0f);

break;

case 8: s1num=0;//复位,时钟走

write_com(0x0c);

flag=1;

write_1302 (0x8e,0x00); //允许写保护

write_1302 (0x80,miao); //秒位初始化

write_1302 (0x82,fen); //分钟初始化

write_1302 (0x84,shi); //小时初始化

write_1302 (0x86,day); //日初始化

write_1302 (0x88,month); //月初始化

write_1302 (0x8c,year); //年初始化

write_1302 (0x8a,week); //日期始化

write_1302 (0x8e,0x80); //禁止写¥

break;

}

}

}

if(s1num!=0)//只有功能键按下后,增大,增小建才有效

{

if(key4==0)//增大建

{

delay(5);

if(key4==0)

{

while(!key4);

di();

switch(s1num)

{

case 1: miao++;

if(miao==60)

miao=0;

write_sfm(6,miao);

//write_1302(write_second,miao);

write_com(0x80+0x40+7);

break;

case 2: fen++;

if(fen==60)

fen=0;

write_sfm(3,fen);

//write_1302(write_minute,fen);

write_com(0x80+0x40+4);

break;

case 3: shi++;

if(shi==24)

shi=0;

write_sfm(0,shi);

write_com(0x80+0x40+1);

break;

case 4: week++;

if(week==8)

week=1;

display_week(week);

write_com(0x80+14);

break;

case 5: day++;

if(day==31)

day=1;

write_nyrz(8,day);

write_com(0x80+9);

break;

case 6: month++;

if(month==13)

month=1;

write_nyrz(5,month);

write_com(0x80+6);

break;

case 7: year++;

if(year==99)

year=0;

write_nyrz(2,year);

write_com(0x80+3);

break;

}

}

}

if(key5==0)//减小键

{

delay(5);

if(key5==0)

{

while(!key5);

di();

switch(s1num)

{

case 1: miao--;

if(miao==-1)

miao=59;

write_sfm(6,miao);

write_com(0x80+0x40+7);

break;

case 2: fen--;

if(fen==-1)

fen=59;

write_sfm(3,fen);

write_com(0x80+0x40+4);

break;

case 3: shi--;

if(shi==-1)

shi=23;

write_sfm(0,shi);

write_com(0x80+0x40+1);

break;

case 4: week--;

if(week==-1)

week=7;

display_week(week);

write_com(0x80+14);

break;

case 5: day--;

if(day==0)

day=31;

write_nyrz(8,day);

write_com(0x80+9);

break;

case 6: month--;

if(month==0)

month=12;

write_nyrz(5,month);

write_com(0x80+6);

break;

case 7: year--;

if(year==-1)

year=99;

write_nyrz(2,year);

write_com(0x80+3);

break;

}

}

}

}

}

void set_alarm()

{

if(key1==0)//功能键按下

{

delay(5);

if(key1==0)

{

while(!key1);

flag=0;

s1num2++;

write_sfm(6,amiao);

write_com(0x80+0x40+7);

write_sfm(3,afen);

write_com(0x80+0x40+4);

write_sfm(0,ashi);

write_com(0x80+0x40+1);

di();

switch(s1num2)//光标闪烁定位

{

case 1:write_com(0x80+0x40+7);//定位到秒的位置

write_com(0x0f);

break;

case 2:write_com(0x80+0x40+4);//定位到分的位置

write_com(0x0f);

break;

case 3:write_com(0x80+0x40+1);//定位到小时的位置

write_com(0x0f);

break;

case 4: s1num2=0;//复位,时钟走

write_com(0x0c);

flag=1;

// write_1302(0x8e,0x00);//允许写保护

write_1302 (0x8e,0x80);

break;

}

}

}

if(s1num2!=0)//只有功能键按下后,增大,增小建才有效

{

if(key2==0)//增大建

{

delay(5);

if(key2==0)

{

while(!key2);

di();

switch(s1num2)

{

case 1: amiao++;

if(amiao==60)

amiao=0;

write_sfm(6,amiao);

write_com(0x80+0x40+7);

break;

case 2: afen++;

if(afen==60)

afen=0;

write_sfm(3,afen);

write_com(0x80+0x40+4);

break;

case 3: ashi++;

if(ashi==24)

ashi=0;

write_sfm(0,ashi);

write_com(0x80+0x40+1);

break;

}

}

}

}

}

void main()//主函数

{

Initial();

lcdws=0;

init();

// IntConfiguration();

tempchange();

for(i=10;i>0;i--)

{

dis_temp(get_temp());

}

while(1)

{

keyscan();//按键扫描

// while((key1&&key2&&key3&&key4&&key5)&&((fen==afen)&&(shi==ashi))) // {

// beep=0;

// delay(500);

// beep=1;

// }

if(flag==1)

{

miao=Read1302(0x81);//显示秒

write_sfm(6,miao);

fen=Read1302(0x83);//显示分

write_sfm(3,fen);

shi=Read1302(0x85);//显示小时

write_sfm(0,shi);

day=Read1302(0x87);//显示日

write_nyrz(8,day);

month=Read1302(0x89);//显示月

write_nyrz(5,month);

year=Read1302(0x8d);//显示年

write_nyrz(2,year);

week=Read1302(0x8b);//显示日期

display_week(week);

}

else

{

write_1302(0x80,0x80);//时钟振荡器停止}

set_alarm();

}

}

相关主题
文本预览
相关文档 最新文档