数码管万年历ds1302
- 格式:doc
- 大小:69.00 KB
- 文档页数:12
STC51电子钟制作最近做了一件DIY 电子钟,自我感觉效果还不错,所以传到网上 与大家分享一下,大家如果喜欢可以尝试做一下,也可以用作毕业设 计。
这款电子钟可以显示年,月,日,小时,分,秒,星期,还有温 度,可以调节时间。
1,电路原理图:我的原理不是很清楚,大家可以看我的 PCB 图,我把每部分都截图 了,效果挺好的。
2,PCB板图:ntiiTRrSfT丄PPf DSL2Q2DSlflB2O \ 11;1M a a n H Z(1)蜂鸣器部分(2) DS1302部分和复位电路部分10pF10pFk5(3) 18B20部分,和单片机晶振部分-7k・DS18B20(4)调时按键部分Array(5) 1602 部分(6)电源部分4,源程序清单:#include<reg52 ・h>#include<stdi o.h>#define uint unsigned int #define uchar unsigned char sbit LCD_RS=P2A4;//1602知识改变命运,word精品文档! sbit LCD_RW=P2A5;sbit LCD_EN=P2A6;sbit rst=P1A7; //DS1302sbit io=P1A6;sbit sclk=P1A5;sbit ACC_7=ACCA7;sbit K1=P2A3;〃按键sbit K2=P2A2;sbit K3=P2A1;sbit K4=P2A0;sbit BEEP=P1A0;〃蜂鸣器sbit DQ=P3A1;〃温度传感器bit flag=0;bit flag1=0;ucharyes;//uchar code table2[|=" SONG you ";//uchar code table3[]=" zhan peng "; uchar code table4[|="0123456789"; char table5[7];uchar table6[2];char table7[2];char leap;〃延时函数部分void Delay_ms(uint xms)/延时{uint i,j;for(i=xms;i>0;i--)for(j=110;j>0;j--);}void Delayus(uchar t)/延时1 用于18b20{while(--t);}void Delayms(uchar t)/延时2 用于18b20while(t--){//大致延时1mSDelayus(245);Delayus(245);}}//18b20 部分bit init18b20(void)〃初始化18b20 {bit dat=0;DQ = 1;Delayus(5);DQ = 0;Delayus(200);Delayus(200);知识改变命运,word精品文档!}DQ = 1; Delayus(50); dat=DQ; Delayus(25); return dat;}uchar read18b20(void)/读卖18b20 函数{uchar i=0,dat=0;for (i=8;i>0;i--){DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;Delayus(25);}return(dat);void write18b20(uchar dat)/写18b20 函数{uchar i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;Delayus(25);DQ = 1;dat>>=1;}Delayus(25);}uint get_18b20(void)/读卖取温度函数{uchar a=0;uint b=0,t=0;init18b20();write18b20(0xCC); //跳过读序号列号的操作write18b20(0x44); // 启动温度转换Delayms(10);init18b20();write18b20(0xCC); //跳过读序号列号的操作前两write18b20(0xBE); //读取温度寄存器等(共可读9个寄存器)个就是温度a=read18b20(); 〃低位b=read18b20(); // 高位b<<=8;t=a+b;return(t);}〃蜂鸣器部分void beep(){BEEP=0;Delay_ms(100);BEEP=1;}//LCD1602 部分void write1602(uchar dat)//1602 写数据函数{ LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=dat;LCD_EN=1;Delay_ms(1);LCD_EN=0;} void write1602c(uchar com)//1602写指令函数{LCD_RS=0;LCD_RW=0;LCD_EN=0;P0=com;LCD_EN=1;Delay_ms(1);}LCD_EN=0;void init1602()//1602 初始化{write1602c(0x38); //16*2 显示write1602c(0x0f); // 显示光标write1602c(0x06); 〃光标右移write1602c(0x01);//清屏write1602c(0x80); }//DS1302 部分void write1302(uchar addr,dat)//1302 写数据函数{ uchar i,temp;rst=0;sclk=0;rst=1;for(i=0;i<8;i++) // 写地址,写数据{sclk=0;temp=addr;io=(bit)(temp&0x01);addr>>=1;sclk=1;}for(i=0;i<8;i++) // 写地址,写数据{sclk=0;temp=dat;io=(bit)(temp&0x01);dat>>=1;sclk=1;}rst=0;}uchar read1302(uchar addr)//1302读数据函数{uchar i,temp,dat1,dat2;rst=0;sclk=0;rst=1;for(i=0;i<8;i++){sclk=0;temp=addr;io=(bit)(temp&0x01);addr>>=1;sclk=1;}for(i=0;i<8;i++){ACC_7=io;sclk=1;ACC>>=1;sclk=0;}rst=0;dat 仁ACC;dat2=dat1%16;dat 1= dat1/16;dat 1=dat1*10+dat2;return(dat1);void init1302()//1302 初始化函数{write1302(0x8e,0x00);write1302(0x80,0x00);//秒初始化write1302(0x8e,0x80); }/*void init1602B(){uchar i=0;write1602c(0x80+16);write1602(0xef);while(table2[i]!='\0'){write1602(table2[i]);i++;}write1602(0xef); write1602c(0x80+0x40+20); i=0;while(table3[i]!='\0')write1602(table3[i]);i++;} for(i=0;i<16;i++){write1602c(0x18);Delay_ms(800);}Delay_ms(2000); write1602c(0x01); write1602c(0x06); }*/〃显示部分void get_time()/获取时间函数{table5[5]=read1302(0x8d);table5[4]=read1302(0x89);table5[3]=read1302(0x87);table5[2]=read1302(0x85);table5[1]=read1302(0x83);table5[0]=read1302(0x81);table5[6]=read1302(0x8b);}void Display_time(uchar year,yue,day,hour,min,sec,xc显示函数{write1602c(0x80);write1602('2');write1602('0');write1602(table4[year/10]);write1602(table4[year%10]);write1602('-');write1602(table4[yue/10]);write1602(table4[yue%10]);write1602('-');write1602(table4[day/10]);write1602(table4[day%10]);write1602('');write1602('w');write1602('e');write1602('e'); write1602('k'); write1602(table4[xq]);write1602c(0x80+0x40); write1602(table4[hour/10]);write1602(table4[hour%10]); write1602(':');write1602(table4[min/10]); write1602(table4[min%10]);write1602(':'); write1602(table4[sec/10]);write1602(table4[sec%10]); write1602('');write1602(''); write1602('T');write1602(''); write1602(table7[0]); write1602(table7[1]);write1602(0xdf); write1602('c');}〃调时部分void Keyprocess(){static uchar num=0;uchar year1,yue1,day1,hour1,min1,xq1;write1302(0x8e,0x00);write1302(0x80,0x80);if(K3==0){Delay_ms(5);if(K3==0){while(!K3);beep();num++;}}if(num>6){num=0;} if(num){if(K1==0){Delay_ms(5);if(K1==0){while(!K1);beep();if(num==1){table5[1]++;if(table5[1]==60)table5[1]=0;min 仁table5[1]/10*16+table5[1]%10;write1302(0x82,min1);}if(num==2){table5[2]=0;hour 1= table5[2]/10*16+table5[2]%10;table5[2]++;if(table5[2]==24)table5[2]=0;hour 1= table5[2]/10*16+table5[2]%10;write1302(0x84,hour1);}if(num==3){table5[6]++;if(table5[6]==8)table5[6]=1;xq仁table5[6]/10*16+table5[6]%10;write1302(0x8a,xq1);}if(num==4){if(table5[5]==0){switch(table5[4]){case 1table5[3]++;if(table5[3]==32) table5[3]=1;break;case 2table5[3]++;if(table5[3]==30) table5[3]=1;break;table5[3]++;if(table5[3]==32) table5[3]=1;break;case 3 table5[3]++;if(table5[3]==33) table5[3]=1;break;知识改变命运,word精品文档!case 4table5[3]++;if(table5[3]==31) table5[3]=1;break;case 5table5[3]++;if(table5[3]==32) table5[3]=1;break;case 6table5[3]++;if(table5[3]==31) table5[3]=1;break;case 7table5[3]++;if(table5[3]==32)table5[3]=1;break; case 8 : table5[3]++;if(table5[3]==32) table5[3]=1;break; case 9 table5[3]++;if(table5[3]==31) table5[3]=1;break;case 10table5[3]++;if(table5[3]==32) table5[3]=1;break;case 11table5[3]++;if(table5[3]==31) table5[3]=1;break;case 12table5[3]++;if(table5[3]==32) table5[3]=1;break;}}else if(leap&&table5[4]==2)table5[3]++;知识改变命运,word精品文档!if(table5[3]==30) table5[3]=1;}else if(leap==0&&table5[4]==2) {table5[3]++; if(table5[3]==29)table5[3]=1;}elseswitch(table5[4]){case 1table5[3]++;if(table5[3]==32) table5[3]=1;break;case 3table5[3]++;if(table5[3]==32) table5[3]=1;break;case 4table5[3]++;if(table5[3]==31) table5[3]=1;break;case 5table5[3]++;if(table5[3]==32) table5[3]=1;break;case 6table5[3]++;if(table5[3]==31) table5[3]=1;break;case 7table5[3]++;if(table5[3]==32) table5[3]=1;break; case 8 : table5[3]++;if(table5[3]==32) table5[3]=1;break;case 9 : table5[3]++;if(table5[3]==31) table5[3]=1;break;case 10 : table5[3]++;if(table5[3]==32) table5[3]=1;break;case 11table5[3]++;if(table5[3]==31) table5[3]=1;break;case 12 : table5[3]++;if(table5[3]==32) table5[3]=1;break;}day仁table5[3]/10*16+table5[3]%10;write1302(0x86,day1);}if(num==5){table5[4]++;if(table5[4]==13)table5[4]=1;yue1=table5[4]/10*16+table5[4]%10;write1302(0x88,yue1);}if(num==6){table5[5]++;if(table5[5]==100)table5[5]=0;leap=table5[5]%4==0&&table5[5]%100!=0;year1=table5[5]/10*16+table5[5]%10;write1302(0x8c,year1);}}}if(K2==0){Delay_ms(5);if(K2==0){while(!K2);beep();if(num==1){table5[1]--;if(table5[1]==-1)table5[1]=59;min 仁table5[1]/10*16+table5[1]%10;write1302(0x82,min1);}if(num==2){table5[2]--;if(table5[2]==-1)table5[2]=23;hour 1= table5[2]/10*16+table5[2]%10;write1302(0x84,hour1);}if(num==3){table5[6]--;if(table5[6]==0)table5[6]=7;xq1=table5[6]/10*16+table5[6]%10;write1302(0x8a,xq1);xq1=table5[6]/10*16+table5[6]%10;}if(num==4) {if(table5[5]==0){switch(table5[4]){case 1 : table5[3]--;if(table5[3]==0) table5[3]=31;break;case 2 : table5[3]--;if(table5[3]==0) table5[3]=29;break;case 3 : table5[3]--;if(table5[3]==0) table5[3]=31;break;case 4 : table5[3]--;if(table5[3]==0) table5[3]=30;break;case 5 : table5[3]--;if(table5[3]==0) table5[3]=31;break;case 6 : table5[3]--;if(table5[3]==0) table5[3]=30;break;case 7 : table5[3]--;if(table5[3]==0)table5[3]=31;break;case 8 : table5[3]--;if(table5[3]==0) table5[3]=31;break;知识改变命运,word精品文档!case 9 : table5[3]--;if(table5[3]==0) table5[3]=30;break;case 10 : table5[3]--;if(table5[3]==0) table5[3]=31;break;case 11 : table5[3]--;if(table5[3]==0) table5[3]=30;break;case 12 : table5[3]--;if(table5[3]==0) table5[3]=31;break;}}else if(leap&&table5[4]==2){table5[3]--;if(table5[3]==0)table5[3]=29;}else if(leap==0&&table5[4]==2){table5[3]--;if(table5[3]==0)table5[3]=28;知识改变命运,word精品文档!elseswitch(table5[4]){case 1 : table5[3]--; if(table5[3]==0) table5[3]=31;break;case 3 : table5[3]--;if(table5[3]==0) table5[3]=31;break;case 4 : table5[3]--;if(table5[3]==0) table5[3]=30;break;case 5 : table5[3]--;if(table5[3]==0) table5[3]=31;break;case 6 : table5[3]--;if(table5[3]==0) table5[3]=30;break;case 7 : table5[3]--;if(table5[3]==0) table5[3]=31;break;case 8 : table5[3]--;if(table5[3]==0) table5[3]=31;break;table5[3]=30;break; case 9 : table5[3]--;if(table5[3]==0)table5[3]=31;break;case 11 : table5[3]--;if(table5[3]==0) table5[3]=30;break;知识改变命运,word精品文档!case 12 : table5[3]--;if(table5[3]==0)table5[3]=31;break;}day仁table5[3]/10*16+table5[3]%10; write1302(0x86,day1);}if(num==5){table5[4]--;if(table5[4]==0)table5[4]=12;yue 仁table5[4]/10*16+table5[4]%10;write1302(0x88,yue1);}if(num==6){table5[5]--;if(table5[5]==-1)table5[5]=79;知识改变命运,word精品文档! Ieap=(table5[5]%4==0&&table5[5]%100!=0);year1=table5[5]/10*16+table5[5]%10;write1302(0x8c,year1);}}}}if(K4==0){Delay_ms(5);if(K4==0);{whiIe(!K4);beep();write1302(0x80,0x00);write1302(0x8e,0x80); flag=0;}}}void init_timer0(void)〃定时器初始化{ TMOD |= 0x01;TH0=(65536-2000)/256;TL0=(65536-2000)%256;EA=1;ET0=1;TR0=1;}void main(){float temp;init1602();//init1602B();init1302();init_timer0();while(1)if(K3==0){Delay_ms(10); if(K3==0){while(!K3);beep();flag=1;}}get_time();Display_time(table5[5],table5[4],table5[3],table5[2],table5[1],tabl e5[0],table5[6]);if(flag) Keyprocess();if(flag 仁=1){flag 1=0;temp=get_18b20();temp=temp*0.0625;sprintf(table7,"%2.0 f",temp);}void timer0() interrupt 1〃定时器函数{ static uint num2=0;TH0=(65536-2000)/256;TL0=(65536-2000)%256;num2++;if(num2==300){num2=0;flag 1=1;}}5,作品效果图知识改变命运,word精品文档!知识改变命运,word精品文档!知识改变命运,word精品文档!。
#include <reg52.h>#define uchar unsigned char#define uint unsigned int#define year 11#define month 2#define day 28#define week 4#define second 0#define minute 59#define hour 23sbit lcden=P3^6;sbit lcdrs=P3^5;sbit anj1=P2^1;sbit anj2=P2^2;sbit anj3=P2^3;sbit anj4=P2^4;sbit DS1302_RST=P2^5;sbit DS1302_SCLK=P2^6;sbit DS1302_IO=P2^7;uint a,b,c,d,e,f,g,i,anxia,flag,second1,minute1,hour1,week1,day1,month1,year1; uchar code table[]=" 00-00-00 0 "; //初始化液晶显示uchar code table1[]=" 00:00:00 ";void delay(uint z) //延时函数{uint x,y;for(x=0;x<z;x++){ for(y=0;y<121;y++){;};};}void write_com(uint com) //写命令函数{lcdrs=0;P1=com;delay(1);lcden=1;delay(1);lcden=0;}void write_data(uint date) //写数据函数{lcdrs=1;P1=date;delay(1);lcden=1;delay(1);lcden=0;}void write_sfm(uint add,uint date) //写时分秒{uint shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_data(0x30+shi);write_data(0x30+ge);}void write_xq(uint xqj) //写星期{uchar xxqj;xxqj=xqj%10;write_com(0x80+13);write_data(0x30+xxqj);}void write_yri(uint add,uint date) //写月日{uint shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_data(0x30+shi);write_data(0x30+ge);}void init() //初始化{lcden=0;write_com(0x38); //8位数据转移双行显示write_com(0x0c); //显示屏开光标不出现不闪write_com(0x06); //光标右移一格,AC加1,字符全部不动write_com(0x01); //清屏for (a=0;a<16;a++) //显示数组table{write_data(table[a]);delay(1);};write_com(0x80+0x40);//写地址液晶第2行首位for (a=0;a<11;a++) //显示数组table1{write_data(table1[a]);delay (1);};}void DS1302_Write(uint D){uchar i;DS1302_SCLK=0;delay (1);for(i=0;i<8;i++){DS1302_IO=D&0x01;delay (1);DS1302_SCLK=1;delay (1);DS1302_SCLK=0;D=D>>1;}}uint DS1302_Read(){uchar TempDat=0,i;delay (1);for(i=0;i<8;i++){TempDat>>=1;if(DS1302_IO==1)TempDat=TempDat|0x80;DS1302_SCLK=1;delay(1);DS1302_SCLK=0;delay(1);}return TempDat;}void WDS1302(uint ucAddr, uint ucDat){DS1302_RST = 0;DS1302_SCLK = 0;DS1302_RST = 1;delay(1);DS1302_Write(ucAddr); // 地址,命令DS1302_Write(ucDat); // 写1Byte数据DS1302_SCLK = 1;DS1302_RST = 0;}uint RDS1302(uint ucAddr){uint ucDat;DS1302_RST = 0;DS1302_SCLK = 0;DS1302_RST = 1;DS1302_Write(ucAddr); // 地址,命令ucDat=DS1302_Read();DS1302_SCLK = 1;DS1302_RST = 0;return ucDat;}void anjian() //按键判断{if(anj1==0){delay(100);if(anj1==0){ anxia++;if(anxia==1){while(!anj1);flag=0;write_com(0x0f); //显示开光标现并闪write_com(0x80+0x40+10); //光标位置秒钟}if(anxia==2){while(!anj1);write_com(0x80+0x40+7); //光标位置}if(anxia==3){while(!anj1);write_com(0x80+0x40+4); //光标位置}if (anxia==4){while(!anj1)write_com(0x80+13);}if (anxia==5){while(!anj1) ;write_com(0x80+10);}if (anxia==6){while(!anj1) ;write_com(0x80+7);}if (anxia==7){while(!anj1) ;write_com(0x80+4);}if (anxia==8){while(!anj1) ;anxia=0;flag=1;write_com(0x0c);}}}if(anxia!=0){if(anj2==0){delay(100);if(anj2==0){while(!anj2);if(anxia==1){second1++;if(second1==60)second1=0;write_sfm(9,second1);write_com(0x80+0x40+10);WDS1302(0x80,((second1/10)<<4|(second1%10)));}if(anxia==2){minute1++;if(minute1==60)minute1=0;write_sfm(6,minute1);write_com(0x80+0x40+7);WDS1302(0x82,((minute1/10)<<4|(minute1%10)));}if(anxia==3){hour1++;if(hour1==24)hour1=0;write_sfm(3,hour1);write_com(0x80+0x40+4);WDS1302(0x84,((hour1/10)<<4|(hour1%10)));}if(anxia==4){week1++;if(week1==8)week1=1;write_xq(week1);write_com(0x80+13);WDS1302(0x8a,((week1/10)<<4|(week1%10)));}if(anxia==5){day1++;day1=1;write_yri(9,day1);write_com(0x80+10);WDS1302(0x86,((day1/10)<<4|(day1%10)));}if(anxia==6){month1++;if(month1==13)month1=1;write_yri(6,month1);write_com(0x80+7);WDS1302(0x88,((month1/10)<<4|(month1%10)));}if(anxia==7){year1++;if(year1==100)year1=0;write_yri(3,year1);write_com(0x80+4);}}}}if(anxia!=0){if(anj3==0){delay(100);if(anj3==0){ while(!anj3);if(anxia==1){if(second1==0)second1=60;second1--;write_sfm(9,second1);write_com(0x80+0x40+10);WDS1302(0x80,((second1/10)<<4|(second1%10)));if(anxia==2){minute1=60;minute1--;write_sfm(6,minute1);write_com(0x80+0x40+7);WDS1302(0x82,((minute1/10)<<4|(minute1%10)));}if(anxia==3){if(hour1==0)hour1=24;hour1--;write_sfm(3,hour1);write_com(0x80+0x40+4);WDS1302(0x84,((hour1/10)<<4|(hour1%10)));}if(anxia==4){if(week1==0)week1=8;week1--;write_xq(week1);write_com(0x80+13);WDS1302(0x8a,((week1/10)<<4|(week1%10)));}if(anxia==5){if(day1==0)day1=31;day1--;write_yri(9,day1);write_com(0x80+10);WDS1302(0x86,((day1/10)<<4|(day1%10)));}if(anxia==6){if(month1==0)month1=12;month1--;write_yri(6,month1);write_com(0x80+7);WDS1302(0x88,((month1/10)<<4|(month1%10)));}if(anxia==7){if(year1==0)year1=100;year1--;write_yri(3,year1);write_com(0x80+4);WDS1302(0x8c,((year1/10)<<4|(year1%10)));}}}}}}void init_1302(){WDS1302(0x8e,0x00);WDS1302(0x80,((second/10)<<4|(second%10)));WDS1302(0x82,((minute/10)<<4|(minute%10)));WDS1302(0x84,((hour/10)<<4|(hour%10)));WDS1302(0x86,((day/10)<<4|(day%10)));WDS1302(0x88,((month/10)<<4|(month%10)));WDS1302(0x8a,((week/10)<<4|(week%10)));WDS1302(0x8c,(year/10)<<4|(year%10));WDS1302(0x8e,0x80);}void main(){flag=1;init();while(1){if(anj4==0){delay(100);if(anj4==0)while(!anj4);init_1302();}anjian();if(flag==1){a=RDS1302(0x81); i= a&0x0f; a >>= 4; a&= 0x0f; a*= 10; i+= a;write_sfm(9,i);b=RDS1302(0x83); i= b&0x0f; b >>= 4; b&= 0x0f; b*= 10; i+= b;write_sfm(6,i);c=RDS1302(0x85); i= c&0x0f; c >>= 4; c&= 0x0f; c*= 10; i+= c;write_sfm(3,i);d=RDS1302(0x87); i= d&0x0f; d >>= 4; d&= 0x0f; d*= 10; i+= d;write_yri(9,i );e=RDS1302(0x89); i= e&0x0f; e >>= 4; e&= 0x0f; e*= 10; i+= e;write_yri(6,i ) ;f=RDS1302(0x8b); i = f&0x0f;f >>= 4; f &= 0x0f;f *= 10; i += f; write_xq(i);g=RDS1302(0x8d); i = g&0x0f;g >>= 4; g &= 0x0f;g *= 10; i += g;write_yri(3,i);}}}。
/***************************************************************系统名称:电子万年历日期:2008,7,18功能描述:LCD12864串行模式显示,DS1302读取时间年月份,18B20 读取温度****************************************************************/#include <reg51.h>#include <intrins.h>#include <stdio.h>#define uchar unsigned char#define uint unsigned int/*------------LCD12864相关声明-----------------------------*/#define com 0#define dat 1sbit cs =P1^6;sbit sid=P1^4;sbit sck=P1^2;uchar code TAB1[]={"电字钟w418781840"};//第一行初始化.uchar code TAB2[]={"20 年月日"}; //第二行uchar code TAB3[]={"星期: : "}; //第三行uchar code TAB4[]={"室温: ℃"}; //第四行/*----------------------DS1302相关声明-------------------------*/char TAB_1302[]={ 0x00,0x29,0x02, //秒:分:时.0x18,0x06,0x06,0x08}; //日:月:星期:年.uchar code TAB_XQ[]={"一二三四五六日"};//把DS1302数字日期转换为中文字符. sbit T_CLK=P2^4; /* 实时时钟的时钟线引脚*/sbit T_IO=P2^5; /* 实时时钟的数据线*/sbit T_RST=P2^6; /* 实时时钟的复位线引脚*/uchar bdata datbyte;sbit datbyte0=datbyte^0;sbit datbyte7=datbyte^7;/*--------------18B20相关声明-------------------------------*/uchar dis1[16];sbit DQ=P1^0; /*DS18B20温度检测*//*----------键盘相关声明-------------------------------------*/sbit key=P3^2; //功能键sbit key1=P3^3; //只有加1键uchar sum,keyflag=0; //调用时,分,秒,标志,调用键盘处理标志./*--------------以下为LCD12864相关函数--------------------------*//**************************************************************函数名称:void delay1ms(uint x)函数功能: 延时1MS***************************************************************/void delay1ms(uint x){uint i,j;for(i=0;i<x;i++)for(j=0;j<120;j++);}/************************************************************** 函数名称:void w_12864byte(uchar byte)函数功能: 写字节**************************************************************/ void w_12864byte(uchar byte){uchar i;for(i=0;i<8;i++){sck=0;byte<<=1;sid=CY;sck=1;}}/************************************************************** 函数名称:uchar r_12864byte(void)函数功能: 读字节***************************************************************/ uchar r_12864byte(void){uchar i,temp1,temp2;temp1 = 0;temp2 = 0;for(i=0;i<8;i++){temp1=temp1<<1;sck = 0;sck = 1;sck = 0;if(sid) temp1++;}for(i=0;i<8;i++){temp2=temp2<<1;sck = 0;sck = 1;sck = 0;if(sid) temp2++;}return ((0xf0&temp1)+(0x0f&temp2));}/************************************************************** 函数名称:void c_12864busy( void )函数功能: 检测忙函数**************************************************************/ void c_12864busy( void ){dow_12864byte(0xfc); //11111,RW(1),RS(0),0while(0x80&r_12864byte());}/************************************************************** 函数名称:void w_12864(bit dat_com,uchar byt)函数功能: 写入函数***************************************************************/ void w_12864(bit dat_com,uchar byt){uchar temp;if(dat_com==0) //为零,写入指令temp=0xf8; //11111,RS(0),RW(0),0else //否则,写入数据temp=0xfa; //11111,RS(1),RW(0),0cs=1;c_12864busy();w_12864byte(temp);w_12864byte(byt&0xf0); //写入高四位w_12864byte(byt<<4); //写入低四位cs=0;}/************************************************************** 函数名称:void init_12864(void)函数功能:初始化12864***************************************************************/ void init_12864(void){w_12864(com,0x30); //基本指令功能.w_12864(com,0x0c); //显示打开,关光标,反白关.w_12864(com,0x01); //清屏指令.w_12864(com,0x06); //AC自动加一}/*----------------以下为DS1302相关函数-------------------------*//************************************************************** 函数名称:void w_1302byte(uchar date)函数功能:写一个字节(上升沿)***************************************************************/ void w_1302byte(uchar date){ uchar i;datbyte=date;for(i=0;i<8;i++){ T_IO=datbyte0; //写最低位T_CLK=0;T_CLK=1;datbyte>>=1;}}/************************************************************** 函数名称:uchar r_1302byte(void)函数功能:读一个字节(下降沿)***************************************************************/ uchar r_1302byte(void){ uchar i;datbyte=0;for(i=0;i<8;i++){ datbyte7=T_IO; //读最低位T_CLK=1;T_CLK=0;datbyte>>=1;}return(datbyte);}/*************************************************************** 函数名称:void write_1302(uchar addr,uchar date)函数功能: 指定位置写数据****************************************************************/ void write_1302(uchar addr,uchar date){ T_RST=0;T_CLK=0;T_RST=1;w_1302byte(addr);w_1302byte(date);T_CLK=0;T_RST=0;}/************************************************************** 函数名称:uchar read_1302(uchar addr)函数功能: 指定位置读数据****************************************************************/ uchar read_1302(uchar addr){ uchar dat1,dat2,temp;T_RST=0;T_CLK=0;T_RST=1;w_1302byte(addr);temp=r_1302byte();T_RST=0;T_CLK=0;dat1=temp/16;dat2=temp%16;temp=dat1*10+dat2;return(temp);}/***************************************************************函数名称:void init_1302(void)函数功能: 初始化*****************************************************************/ void init_1302(void){ uchar i;uchar addr=0x80;write_1302(0x8e,0x00);for(i=0;i<7;i++){write_1302(addr,TAB_1302[i]);addr+=2;}write_1302(0x8e,0x80);}/**************************************************************** 函数名称:void get_1302(void)功能说明:读取DS1302时钟信息.*****************************************************************/ void get_1302(void){ uchar i,addr=0x81;for(i=0;i<7;i++){ TAB_1302[i]=read_1302(addr);addr+=2;}}/*---------------以下为18B20相关函数-----------------------------*//******************************************************************函数名称:void delay (uint x)功能说明:若机器周期为1us,则本延时程序为延时4*x(us)******************************************************************/ void delay (uint x) //本板延时8us{while (--x);}/***************************************************************** 函数名称:uchar bus_rest(void)功能说明:产生单总线系统信号的总线复位信号,并返回总线上是否存在单总线器件信息******************************************************************/ uchar bus_rest(void){uchar presence;DQ=0; //将DQ信号线拉低delay(29); //持续48USDQ=1; //释放总线delay(3); //等待从设备将总线拉低presence=DQ; //保存当前总线状态delay(25); //等待总线初始化过程结束return presence;//返回是否有从设备将总线拉低}/**************************************************************** 函数名称:uchar r_1820BYTE(void)功能说明:向单总线读取一个数据字节*****************************************************************/ uchar r_1820BYTE(void){uchar i=0;uchar date = 0;for (i=8;i>0;i--){DQ = 0; // 将DQ信号线拉低启动读时隙DQ=1;// 释放总线,等待从机动车辆返回数据位delay(1); //越接近15us越好; 准备采样总线上的信号date>>=1 ;if (DQ)date=date|0x80;delay(6);}return(date);}/***************************************************************** 函数名称:void w_1280Byte(uchar bytevalue)功能说明:向单总线写一个数据字节******************************************************************/ void w_1280Byte(uchar bytevalue){uchar i;for(i=0;i<8;i++){DQ=0; // 将DQ信号线拉低启动读时隙DQ=bytevalue&0x01; //delay(5);//等待写时隙结束DQ=1; //释放bytevalue>>=1;}delay(5); ////等待写时隙结束}/***************************************************************** 函数名称:uint read_T(void)功能说明:读取1820温度*******************************************************************/ uint read_T(void){uchar a=0;uchar b=0;uint t=0;bus_rest();w_1280Byte(0xCC); // 跳过读序号列号的操作;w_1280Byte(0x44); // 启动温度转换,模数转化;bus_rest();w_1280Byte(0xCC); //跳过读序号列号的操作;a=r_1820BYTE();// 低8位b=r_1820BYTE();// 高8位t=(b*256)+a;return(t);}/**************************************************************函数名称:void show_T(uint temp)函数功能:显示温度**************************************************************/void show_T(uint temp){int i;float ftemp;ftemp = temp* 0.0625;w_12864(com,0x98+3);for(i=0;i<5;i++)w_12864(dat,dis1[i]); //写入温度}/*---------------以下为显示相关函数--------------------------*//******************************函数名称: void fenli(uchar x,uchar y,uchar val)功能描述: 指定位置写入数据********************************/void fenli(uchar x,uchar y,uchar val){ uchar ge,shi,addr,i=0;if(val==5)//星期数字显示的转换为中文{w_12864(com,0x88+2);for(i=0;i<2;i++){if(TAB_1302[5]==0)w_12864(dat,TAB_XQ[i]);if(TAB_1302[5]==1)w_12864(dat,TAB_XQ[2+i]);if(TAB_1302[5]==2)w_12864(dat,TAB_XQ[3+i]);if(TAB_1302[5]==3)w_12864(dat,TAB_XQ[5+i]);if(TAB_1302[5]==4)w_12864(dat,TAB_XQ[7+i]);if(TAB_1302[5]==5)w_12864(dat,TAB_XQ[9+i]);if(TAB_1302[5]==6)w_12864(dat,TAB_XQ[11+i]);}}else{shi=TAB_1302[val]/10;//分离十位ge=TAB_1302[val]%10;if(x==1)x=0x80;if(x==2)x=0x90;if(x==3)x=0x88;if(x==4)x=0x98;addr=x+y;w_12864(com,addr);//指定位置w_12864(dat,0x30+shi);//写入w_12864(dat,0x30+ge);}}/*************************************************************函数名称:void display(void)功能描述: 显示函数**************************************************************/ void display(void){ get_1302(); //读1302fenli(3,7,0); //读秒fenli(3,5,1); //读分fenli(3,3,2); //读时fenli(2,5,3); //读日fenli(2,3,4); //读月fenli(3,2,5); //读星期fenli(2,1,6); //读年}/*---------------按键处理相关函数--------------------------*//************************************************************ 函数名称:void scanner()功能描述: 按键函数*************************************************************/ void scanner(){ uchar i,j;if(!key) //功能键按下{ delay1ms(500); //延时500MSif(!key) //还按下,退出时间调整{ keyflag=0; //标志位为0sum=0; //清0w_12864(com,0x0c);//清闪烁for(i=0;i<7;i++)//十进制转十六进制{ j=TAB_1302[i]/10;TAB_1302[i]=TAB_1302[i]%10;TAB_1302[i]=TAB_1302[i]+16*j;}init_1302(); //写入1302while(!key); //等待释放delay1ms(10); //延时消抖}else //500MS内放开{ keyflag=1; //标志为1,进行时间调整sum++; //功能键加1if(sum==8)sum=0;switch(sum){ case 1: //{ w_12864(com,0x98+7);w_12864(com,0x0f);break;}case 2: //为2,年闪烁w_12864(com,0x90+1);break;case 3: //月闪烁w_12864(com,0x90+3);break;case 4: //日闪烁w_12864(com,0x90+5);break;case 5: //星期闪烁w_12864(com,0x88+2);break;case 6: //分闪烁w_12864(com,0x88+5);break;case 7: //时闪烁w_12864(com,0x88+3);break;}}}if(sum) //功能键按下{if(!key1){ delay1ms(10);if(!key1){ while(!key1);//等待加1键释放delay1ms(10);if(sum==1){ //备用}if(sum==2){ TAB_1302[6]++;if(TAB_1302[6]==100)TAB_1302[6]=0;fenli(2,1,6);w_12864(com,0x90+1);//闪烁归位}if(sum==3){ TAB_1302[4]++;if(TAB_1302[4]==13)TAB_1302[4]=1;fenli(2,3,4);w_12864(com,0x90+3);}if(sum==4){ TAB_1302[3]++;if(TAB_1302[3]==32)TAB_1302[3]=1;fenli(2,5,3);w_12864(com,0x90+5);}if(sum==5){ TAB_1302[5]++;if(TAB_1302[5]==7)TAB_1302[5]=0;fenli(3,2,5);w_12864(com,0x88+2);}if(sum==6){ TAB_1302[1]++;if(TAB_1302[1]==60)TAB_1302[1]=0;fenli(3,5,1);w_12864(com,0x88+5);}if(sum==7){ TAB_1302[2]++;if(TAB_1302[2]==24)TAB_1302[2]=0;fenli(3,3,2);w_12864(com,0x88+3);}}}}}//============================================================= void init(void){uchar i;init_12864();init_1302();while(TAB1[i]!='\0'){w_12864(dat,TAB1[i]);i++;}i=0;w_12864(com,0x90);while(TAB2[i]!='\0'){w_12864(dat,TAB2[i]);i++;}i=0;w_12864(com,0x88);while(TAB3[i]!='\0'){w_12864(dat,TAB3[i]);i++;}i=0;w_12864(com,0x98);while(TAB4[i]!='\0'){w_12864(dat,TAB4[i]);i++;}}/************************************************************* 函数名称:主函数函数功能:**************************************************************/ main(){init();while(1){scanner(); //检测键盘if(!keyflag) //标志为0{ display(); //调用显示show_T(read_T()); //显示温度delay1ms(500);}}}。
#include<>#define uchar unsigned char#define uint unsigned intsbit 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<jiepai[i2]*20;j2++)// {// beep=~beep;// for(k2=0;k2<song[i2]/3;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);}//初始化 DS1302void 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;delay(5);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; //写0i=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*;temp=f_temp*10+;f_temp=f_temp+; //温度在寄存器中为12位,分辨率为^ 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();}}。
DS1302设计的可调万年历(实测正常,附有程序)ds1302设计的可调万年历(本制作所用数码管全为共阳数码管)我刚开始想要搞万年历的时候就是玩游戏打听别人的程序,可是辨认出打听了很多都不理想,必须不就没有日历和时间一起表明,必须不就无法阳入时间的,后来我研究了两天,自己终于把程序编成了出。
不好了,废话我就不多说道,本制作我已经把实物搞了出,确保没问题!下面附有仿真图和实物图。
拍摄的效果不够好,但实物是不错的,本人实物中用三级管代替了仿真图的74hc04非门,用哪个都是可以的……请注意:本程序分后两个c文件的,如果不能编成,可以q我:1107588997我轻易播发程序过去给你……软件源程序:(初始化程序只在已经开始时用一次,之后必须把它屏蔽掉)#include#include#includeuchartime_data[7]={0,0,0,0,0,0,0};ucharwrite_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};ucharread_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};voidwrite_ds1302_byte(uchardat){uchari;for(i=0;i<8;i++){sck=0;io=dat&0x01;dat=dat>>1;sck=1;}}voidwrite_ds1302(ucharadd,uchardat){rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);write_ds1302_byte(dat);rst=0;_nop_();io=1;sck=1;}ucharread_ds1302(ucharadd){uchari,value;rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);for(i=0;i<8;i++){value=value>>1;sck=0;if(io)value=value|0x80;sck=1;}rst=0;_nop_();sck=0;_nop_();sck=1;io=1;returnvalue;}voidread_rtc(void){uchari;for(i=0;i<7;i++){time_data[i]=read_ds1302(read_add[i]);}}voidtime_pros(void){nian=time_data[0]/16*10+time_data[0];yue=time_data[2]/16*10+time_data[2];ri=ti me_data[3]/16*10+time_data[3];xi=time_data[1]/16*10+time_data[1];shi=time_data [4]/16*10+time_data[4];fen=time_data[5]/16*10+time_data[5];miao=time_data[6]/1 6*10+time_data[6];}voidmain(){//init_ds1302();//初始化while(1){read_rtc();time_pros();display();button();}}//----------------------------zichengxu.c----------------------------------------------#defineduan1p2#defineduan2p3#defineweip0#defineuintunsignedint#defineucharunsignedcharsbitsck=p1^1;sbitio=p1^0;sbitrst =p1^2;sbitk1=p1^4;sbitk2=p1^5;sbitk3=p1^6;sbitk4=p1^7;ucharshi,fen,miao,nian,yue,ri,xi,menu,y;unsignedcharcodequan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; voidwrite_ds1302_byte(uchardat);voidwrite_ds1302(ucharadd,uchardat);ucharread_ds1302(ucharadd);//voidinit_ds1302(void);//初始化voidread_rtc(void);voidtime_pros(void);voiddisplay(void);voidbutton(void);voiddelay(uintz){ucharx,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/*(voidinit_ds1302(void)//初始化{write_ds1302(0x8e,0x00);write_ds1302(0x80,0x00);write_ds1302(0x82,0x20);write_ ds1302(0x84,0x09);write_ds1302(0x86,0x25);write_ds1302(0x88,0x12);write_ds1302 (0x8a,0x06);write_ds1302(0x8c,0x10);write_ds1302(0x90,0x01);write_ds1302(0xc0, 0xf0);write_ds1302(0x8e,0x80);}*/voiddisplay(void){wei=0;duan1=quan[2];if(menu==3&&y<80&&k1!=0&&k2!=0&&k3!=0&&k4!=0){duan2=0xff;}elseduan2=quan[shi/10];delay(2);duan1=0xff;duan2=0xff;wei=1;duan1=quan[0];if(menu==3&&y<80&&k1!=0&&k2!=0&&k3!=0&&k4!=0){duan2=0xff;}elseduan2=quan[shi];delay(2);duan1=0xff;duan2=0xff;。
#include<reg52.h>#include<intrins.h> //为了使用这个头文件中的_nop_()延时函数sbitsda=P2^0; //定义1302的数据线sbitscl=P2^1; //定义1302的时钟线sbitrst=P2^4; //定义1302的复位控制端,高电平时启动1302,低电平时关闭1302 sbit hc573_sg_le=P2^6; //对用于锁存段数据的573锁存LE端进行定义sbit hc573_bit_le=P2^7; //对用于锁存位选通数据的573锁存LE端进行定义sbitlcd_rs=P1^0; //1602数据/命令选择端,高电平执行数据操作,低电平执行命令操作sbitlcd_rw=P1^1; //1602读/写控制端高电平读,低电平写sbitlcd_en=P2^5; //1602读写控制使能信号,它为高脉冲信号才可执行读写操作sbit sta7=P0^7; //1602忙信号检测位,为1则忙,需等待,为0表示空闲unsigned char write_dat[8]={0x12,0x36,0x17,0x23,0x8,0x5,0x13,0x80}; //秒分时日月星期年和保护寄存器的初值unsigned char read_dat[8]; //用于接收从1302读到的寄存器当前值unsigned char code lcd_line1[]={" 20 - -"}; //定义第一行液晶显示的格式字符数组unsigned char code lcd_line2[]={"Week: : :"}; //定义第二行液晶显示的格式字符数组void lcd_busy_check(void) //1602忙信号检测,忙则等待{P0=0xff;do{lcd_rs=0; //读状态操作,为0lcd_rw=1; //读操作为1lcd_en=0;lcd_en=1; //读状态,需为高电平}while (sta7==1); //如果为1则忙,等待...直到为0lcd_en=0;}void lcd_write_cmd(unsigned char cmd) //液晶写命令函数{lcd_busy_check(); //每次操作之前都要进行忙信号检测lcd_rs=0; //执行命令操作,为0lcd_rw=0; //写操作,为0P0=cmd; //送指令到液晶数据端口P0,准备执行命令_nop_(); //这是一个延时函数,可延时一个机器周期,它在“intrins.h”中lcd_en=1; //高电平,指令送入液晶控制器_nop_(); //保持一会儿,使指令可靠地送入液晶控制器lcd_en=0; //低电平,执行命令}void lcd_write_data(unsigned char dat) //液晶写数据函数{lcd_busy_check(); //每次操作之前都要进行忙信号检测lcd_rs=1; //执行数据操作,为1lcd_rw=0; //写操作,为0P0=dat; //送数据到液晶数据端口P0,准备执行数据操作_nop_();lcd_en=1; //高电平,数据送入液晶液晶数据RAM_nop_(); //保持一会儿,使显示数据可靠地送入液晶数据RAM lcd_en=0; //低电平,显示数据}void lcd1602_init() //液晶显示初始化操作{P0=0x00;hc573_bit_le=0;hc573_sg_le=0; //关闭HC573使数码管不显示lcd_en=0; //为0,为实现高脉冲作准备lcd_write_cmd(0x38); //设置为5x7显示lcd_write_cmd(0x0c); // 打开显示-显示光标-光标闪烁lcd_write_cmd(0x6); //地址加一,光标右移,整屏显示不移动lcd_write_cmd(0x01); //清屏}/*--对1302进行写一个字节的函数--*/voidwrite_byte(unsigned char dat){unsigned char i;for(i=8;i>0;i--){sda=(bit)(dat&0x01);scl=0;scl=1;dat=dat>>1;}}/*--对1302进行读一个字节的函数--*/unsigned char read_byte(){unsigned char dat,i;for(i=8;i>0;i--){dat=dat>>1;scl=1;scl=0;if(sda==1)dat=(dat|0x80);}returndat;}/*--1302的初始化函数。
基于DS1302的电子万年历设计摘要:本文介绍了一种智能一体化的电子万年历系统,该设计采用DS1302时钟芯片,主控芯片STC89C52型单片机,显示器件NOKIA 5110 LCD,外部手动设置模块键盘组成了电子万年历小系统,NOKIA 5110 LCD能一目了然地显示出年月日星期小时分秒,满足了人们在读取时更加直接的需要。
电子万年历集时间,日期,温度,闹钟于一体,且电路简洁,成本低廉,显示准确,符合了人们对时间的各种需求,使人们生活更加方便快捷。
关键词:万年历 STC89C52 DS1302 NOKIA 5110The Design of Electronic Calendar Based on DS1302 Name:Zhang qianqian Student Id:2 Advisor:Wang zhongxinAbstract: This paper introduces a kind of intelligent electronic calendar system, this calendar small system is made up of the DS1302 clock chip, main control chip microcontroller STC89C52 , NOKIA 5110 LCD display device, external manual setup module keyboard. NOKIA 5110 LCD can clearly show whole time to meet people every need for time request. Electronic calendar include time, date, temperature, the alarm clock module in one system, the system circuit is simple, the cost is low but it can display accurate time, it can meet the different needs of people to time and help people’ life become more convenient and efficient..Keywords: calendar STC89C52 DS1302 NOKIA 5110目录1.论序 (1)1.1课题背景 (1)1.2基于DS1302的电子万年历设计的目的和意义 (1)1.2.1设计目的 (1)1.2.2设计意义 (1)1.3现代电子万年历系统设计的发展状况 (1)1.4课题容 (1)1.5本章小结 (1)2.基于DS1302的电子万年历系统总体设计方案 (2)2.1总体设计框图 (2)2.2系统设计的功能要求 (2)2.3系统设计的方案论证 (2)2.3.1单片机控制模块的选择 (2)2.3.2时钟芯片的选择 (3)2.3.3键盘电路的选择 (3)2.3.4 显示电路的选择 (3)2.4本章小结 (3)3.基于DS1302的电子万年历设计系统硬件电路设计 (4)3.1系统硬件电路设计 (4)3.2系统核心电路——单片机STC89C52 (4)3.2.1 STC89C52主要功能 (4)3.2.2 STC89C52主要引脚及其功能 (5)3.3时钟电路设计 (6)3.3.1 DS1302的性能特征 (6)3.3.2 DS1302的工作原理及数据操作 (7)3.4键盘和显示电路的设计 (9)3.4.1键盘接口设计 (9)3.4.2显示电路设计 (9)3.5本章小结 (11)4. 基于DS1302的电子万年历软件设计 (11)4.1基于DS1302的电子万年历设计系统程序设计要求 (11)4.2基于DS1302的电子万年历设计系统主程序设计 (11)4.2.1液晶模块初始化程序 (11)4.2.2DS1302时钟控制模块初始化程序 (11)4.2.3定时器T0初始化程序 (11)4.2.4时钟程序和中断程序 (11)4.3N OKIA5110液晶显示模块的程序设计 (11)4.4DS1302时间控制模块的程序设计 (11)4.5闹钟程序设计 (13)4.6本章小结 (14)5.总结 (14)1.1课题背景随着科技的发展社会的进步,人类从观太阳、摆钟到现在电子钟得知时间,不断的研发新的计时产品。
1 引言随着微电子技术和超大规模集成电路技术的不断发展,家用电子产品不但种类日益丰富,而且变得更加经济实用,单片微型计算机体积小、性价比高、功能强、可靠性高等独有的特点,在各个领域得到了广泛的应用。
电子万年历是一种应用非常广泛的日常计时工具,数字显示的日历钟已经越来越流行,特别是适合在家庭居室、办公室、大厅、会议室、车站和广场等使用。
LED数字显示的日历钟显示清晰直观、走时准确、可以进行夜视,并且还可以扩展出多种功能。
功能也越来越齐全,除了公历年月日、时分秒、星期显示及闹铃。
但通过我们对各种电子钟表、历的不断观察总结发现目前市场的钟、历都存在一些不足之处,比如:时钟不精确、产品成本太高、无环境温度显示等,这都给人们的使用带来了某些不便。
为此设计了一种功能全面、计时准确、成本低廉的基于51单片机的万年历。
2 功能要求1. 万年历能用数码管显示阳历年、月、日、星期、[小]时、分、秒并设置指定时间的闹铃。
2. 数字式温度计要求测温范围-50~100°C,LED数码管直读显示。
3 方案论证与设计3.1 控制部分的方案选择1. 用可编程逻辑器件设计。
可采用ALTERA公司的FLEX10K系列PLD器件。
设计起来结构清晰,各个模块,从硬件上设计起来相对简单,控制与显示的模块间的连接也会比较方便。
但是考虑到本设计的特点,EDA在功能扩展上比较受局限,而且EDA占用的资源也相对多一些。
从成本上来讲,用可编程逻辑器件来设计也没有什么优势。
2. 用凌阳16位单片机设计。
凌阳16位单片机有丰富的中断源和时基,方便本实验的设计。
它的准确度相当高,并且C语言和汇编兼容的编程环境也很方便来实现一些递归调用。
I/O口功能也比较强大,方便使用。
用凌阳16位单片机做控制器最有特色的就是它的可编程音频处理,可完成语音的录制播放和识别。
这些都方便对设计进行扩展,使设计更加完善。
成本也相对低一些。
但是,在控制与显示的结合上有些复杂,显示模组资源相对有限,而且单片机的稳定性不是很高。
1 引言随着科技的不断进步和发展,单片机的使用已经渗透到我们日常生活当中的各个领域,几乎很难找到有哪个领域没有使用单片机的踪迹。
导弹的导航装置,飞机上各种仪表的控制,计算机的网络通讯与数据传输,工业自动化过程的实时控制和数据处理,广泛使用的各种智能IC卡,民用豪华轿车的安全保障系统,录相机、摄像机、全自动洗衣机的控制,以及程控玩具、电子宠物等等,这些都离不开单片机。
更不用说自动控制领域的机器人、智能仪表、医疗器械了。
本文设计的电子万年历属于小型智能家用电子产品。
利用单片机进行控制,实时时钟芯片进行记时,外加掉电存储电路和显示电路,可实现时间的调整和显示。
电子万年历既可广泛应用于家庭,也可应用于银行、邮电、宾馆、饭店、医院、学校、企业、商店等相关行业的大厅,以及单位会议室、门卫等场所。
因而,此设计具有相当重要的现实意义和实用价值。
1.2方案选择由于现在市面上的电子万年历的种类比较多,因此到底选择什么样的方案在设计中是至关重要的。
正确地选择方案就可以使产品更加人性化,并且可以减小开发的难度,缩短开发的周期,降低产品的成本等等,因此就会被人们普遍接受,并且能够更快地将产品推向市场实现其自身的价值。
下面我们就拟订了两种方案,希望能够选择一种性价比高的方案。
1.2.1 方案1——基于AT89S52单片机的电子万年历设计不使用时钟芯片,而直接用AT89S52单片机来实现电子万年历设计。
AT89S52是一种带8K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS 8位微处理器,俗称单片机。
单片机的可擦除只读存储器可以反复擦写1000余次。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89S52是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
若采用单片机计时,利用它的一个16位定时器/计数器每50ms产生一个中断信号,中断20次后产生一个秒信号,然后根据时间进制关系依次向分、时、日、星期、月、年进位。
摘要随着科技的快速发展,时间的流逝,至从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS1302。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和还具有时间校准等功能。
该电路采用AT89S52单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。
综上所述此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。
关键词:时钟电钟;DS1302;动态扫描;单片机AbstractAlong with the rapid development of technology, the passage of time, from concept to thesun,until now electric clock, human pendulum clocks are continuously research and constant innovation of records. American DALLAS company launched with Juan fine current charge oflow-power real-time clock circuit DS1302. It can to year, month, day, Sunday, when, minutes and seconds on the clock and also has a leap year compensation and other functions, and DS1302 of long service life and small error. For digital electronic calendar by using object digital display, can also shows that year, month, day, Sunday, when, minutes and seconds and still have timecalibration, and other functions.This circuit adopts AT89S52 SCM as the core, low consumption, can in the low voltage 3V work, voltage can choose 3 ~ 5V voltage power supply .To sum up the calendar has read convenient, direct display, functional diversity, simple circuit, low cost, and many other advantages, conform to the trend of the development of electronic instruments, and has a broad market prospect.Key words:Clock actuated;DS1302;Dynamic scanning;MCU目录引言 (4)1设计要求与方案论证 (4)1.1 设计要求 (4)1.2系统基本方案选择和论证 (4)1.2.1单片机芯片的选择方案和论证 (4)1.2.2 显示模块选择方案和论证 (4)1.2.3 时钟芯片的选择方案和论证 (5)1.3 电路设计最终方案决定 (5)2 系统的硬件设计与实现 (5)2.1 电路设计框图 (5)2.2 系统硬件概述 (5)2.3 主要单元电路的设计 (6)2.3.1单片机主控制模块的设计 (6)2.3.2 时钟电路模块的设计 (6)2.3.3 电路原理及说明 (7)2.3.4 显示模块的设 (9)3 系统的软件设计 (9)3.1 程序流程框图 (10)3.2 程序的设计 (11)4 指标测 (11)4.1 测试仪器 (22)4.2 硬件测试 (22)4.3 软件测试 (22)4.4 测试结果分析与结论 (22)4.4.1 测试结果分析 (23)4.4.2 测试结论 (23)5作品总结 (23)致谢词 (24)参考文献 (25)附录一:系统电路图 (26)引言随着当今世界经济的快速发展和信息化时代的来临,各种各样的小型智能家电产品陆续出现在我们的生活当中。
DS1302中文资料DS1302是一款数字时钟芯片,具有时钟/日历芯片的功能。
它采用3线串行接口与主控器连接,可提供同步的时钟输出、电池供电的实时时钟、完整的日历功能以及一系列的控制和管理功能。
它广泛应用于各种电子设备和系统中。
1.低功耗:DS1302在备份供电模式下工作时的功耗非常低,可使电池的使用寿命更长。
2.时钟功能:DS1302能够提供年、月、日、小时、分钟和秒的时钟信息,精确到秒。
它还可以设置闹钟功能,方便用户设定定时提醒。
3.电压监测:DS1302可以监测电池电压,当电池电压低于一些阈值时,会产生中断信号,以便提醒用户更换电池。
4.温度监测:DS1302内置温度传感器,可以监测环境温度,并提供相应的温度值。
5.数据存储:DS1302具有非易失性存储器,可以保存时钟和日历信息,即使在断电情况下也能保持数据稳定。
使用DS1302的步骤如下:1.硬件连接:将DS1302芯片与主控器连接。
DS1302需要连接VCC(3.3V或5V电源)、GND(地)以及主控器的数据线(DIO)、时钟线(SCLK)和复位线(RST)。
2.时钟设置:在正常工作模式下,向DS1302写入相应的年、月、日、小时、分钟和秒的数据,即可设置时钟。
DS1302支持24小时制和12小时制,可以根据需要选择。
3.读取时钟:通过读取DS1302的相应寄存器,可以获取当前的时钟信息。
可以先读取秒寄存器,再读取分、时、日、月和年的寄存器,以获得完整的时钟信息。
5.闹钟设置:DS1302支持设置闹钟功能。
通过读取和写入相应的寄存器,可以设置闹钟的小时和分钟,并可以选择是否启用闹钟功能。
6.温度监测:DS1302可以读取内置温度传感器的数值,并将其转换为摄氏温度。
通过读取相应的寄存器,可以获取当前的温度值。
7.电压监测:DS1302可以监测电池电压,并在电池电压低于设定阈值时产生中断信号。
通过读取相应的寄存器,可以获取当前的电池电压值。
#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int//sbit ACC7=ACC^7; //累加器位寻址寄存器定义//sbit ACC0=ACC^0;sbit dula=P1^0; //数码管段选位sbit wela=P1^1; //数码管位选位sbit line=P1^3;//点阵行控制端sbit led=P1^2;//流水灯锁存器锁存端sbit clk=P2^3; //DS1302时钟管脚定义sbit tda=P2^2; //数据输入输出7脚sbit rst=P2^1; //片选(复位)5脚sbit lcdrs=P1^5; //液晶位定义sbit lcdrw=P1^6; //液晶读写控制端sbit lcden=P1^7; //液晶始能端(复位端)sbit dht11=P2^0; //湿度传感器端口定义sbit been=P3^7; //蜂鸣器//时钟按键定义sbit s1=P2^4; //功能选择键sbit s2=P2^5; //增加键sbit s3=P2^6; //减小键uchar code riqi[]=" 20 - - "; //定义液晶初始上电时的默认显示状态uchar code shijian[]=" : : "; //定义液晶上电时间显示格式uchar value_array[5];//全局变量部分uchar flag,s1num,status;uchar status;char miao,fen,shi,ri,yue,nian,week;int humi_value,wedu_value;//延时函数单位:毫秒void delay(uint z){uint i,j;for(i=z;i>0;i--)for(j=110;j>0;j--);}//湿度延时函数void delay_10us(void) //延迟10微妙{uchar i;i--;i--;i--;i--;i--;}//蜂鸣器发声函数void di(){been=0;delay(40);been=1;}//液晶1602显示模块void write_com(char com) //液晶写命令{lcdrw=0;lcdrs=0;lcden=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;lcdrw=1;}void write_date(char date) //液晶写数据lcdrw=0;lcdrs=1;lcden=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;lcdrw=1;}/******************DS1302:写入一字节(上升沿写入)*****************/ /*void write_byte(char da){uchar i;ACC=da;for(i=8;i>0;i--){tda=ACC0;clk=0;clk=1;ACC=ACC>>1;}}*/void write_byte(char da){uchar i;for(i=8;i>0;i--){tda=(bit)(da&0x01);_nop_();clk=0;_nop_();clk=1;_nop_();da>>=1;}}/******************DS1302:读取一字节(下降沿读出)*****************/ /*uchar read_byte(void){uchar i;for(i=0;i<8;i++){ACC=ACC>>1;clk = 1;clk = 0;ACC7 = tda;}return(ACC);}*/uchar read_byte(void){uchar i,j,AC;for(i=0;i<8;i++){clk = 1;_nop_();clk = 0;_nop_();j=tda; //之所以这样做是因为tda为位变量,不能直接使用移位运算,故先将其值存入为0的j中_nop_();AC =(j<<7)|(AC>>1);}return(AC);}/******************DS1302:写入操作(上升沿)*********************/void write1302(char addr,char da){rst=0; //停止工作clk=0;rst=1; //重新工作write_byte(addr); //写入地址write_byte(da);rst=0;clk=1;/******************DS1302:读取操作(下降沿)*****************/char read1302(char addr){char temp;rst=0; //停止工作clk=0;rst=1; //重新工作write_byte(addr); //写入地址temp=read_byte();rst=0;clk=1; //停止工作return(temp);}//初始化DS1302void init1302(void) //DS1302只识别BCD码{write1302(0x8e,0X00);//首先禁止写保护,否则写不进去数据//以下所写均为BCD码形式write1302(0x80,0X00);//秒位初始化00//以下所写均为BCD码形式write1302(0x82,0X00);//分钟初始化00write1302(0x84,0X00);//小时初始化(设为24小时制)write1302(0X8a,0X06); //向DS1302内写周寄存器8aH写入初始周数据周六write1302(0X86,0X22); //向DS1302内写日期寄存器86H写入初始日期数据07write1302(0X88,0X06); //向DS1302内写月份寄存器88H写入初始月份数据01write1302(0X8C,0X12); //向DS1302内写年份寄存器8cH写入初始年份数据12write1302(0xc0,0x05); //设立初始化查询标志位,使其只首次上电才初始化(标志为向0xc0写入0x05);write1302(0x8e,0X80); //打开写保护,防止误写数据;}//写时,分,秒的函数void write_sfm(uchar add,char date){uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi); //注意:1602液晶的字库中的数字以0x30+偏移量而形成得到数字write_date(0x30+ge);}//写年,月,日的函数void write_nyr(uchar add,char date){char shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_date(0x30+shi); //数字加上30即为其在液晶1602中对应的字形码write_date(0x30+ge);}//写星期几的函数void write_week(uchar we){write_com(0x80+12);switch(we){case 1: write_date('M');delay(5);write_date('O');delay(5);write_date('N');break;case 2: write_date('T');delay(5);write_date('U');delay(5);write_date('E');break;case 3: write_date('W');delay(5);write_date('E');delay(5);write_date('D');break;case 4: write_date('T');delay(5);write_date('H');delay(5);write_date('U');break;case 5: write_date('F');delay(5);write_date('R');delay(5);write_date('I');break;case 6: write_date('S');delay(5);write_date('A');delay(5);write_date('T');break;case 7: write_date('S');delay(5);write_date('U');delay(5);write_date('N');break;}}//十进制码转BCD码转换函数char bcd(char a){uchar b,c;b=a/10;c=a%10;b=b&0x0f;c=c&0x0f;b<<=4;a=b|c;return(a);}//BCD码转十进制的函数;char deci(char c){char d,e;d=c/16;e=c%16;c=d*10+e;return(c);}//整体初始化函数void init(){uchar num;P0=0X00;dula=0; //关闭数码管段选锁存器line=0;P0=0XFF;led=0;lcden=0;wela=1;P0=0XFF;wela=0;s1num=0; //s1按键计数定义if(deci((read1302(0xc1)))!=0x05){init1302(); //第一次上电初始化DS1302(读取0xc1中的数值,看其是否为0x05;若是,则不初始化)。
/ZPF(新)//2012//4/29#include <REGX55.H>#include<intrins.h>#define uint unsigned int#define uchar unsigned charuchar k,s,aa,Nshi,Nfen;//,miao,nian,yue,ri,zhou;uchar number[8];uchar dif_flag;//测温度定义uint temp;float f_temp; //温度值variable of temperature bit flag;sbit w1=P1^2;sbit w2=P1^3;sbit w3=P1^4;sbit w4=P1^5;sbit DQ=P1^7;sbit dula=P1^0;sbit wela=P1^1;sbit DS1302_CLK = P3^7; //实时时钟时钟线引脚sbit DS1302_IO = P3^6; //实时时钟数据线引脚sbit DS1302_RST = P3^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;sbit key=P1^6;sbit key1=P3^0;sbit key2=P3^1;sbit key3=P3^2;sbit key4=P3^3;sbit key5=P3^4;uchar read[7];uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x00};//共阴数码管0-9uchar week_value[2];//void dis_delay(void);void delay(uint x);void display(unsigned char a,unsigned char b,unsigned char c);void show_time(); //显示程序void Write1302(unsigned char ucAddr, unsigned char ucDa);void keyscan();void Display_18b20(uint temp);/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;}SYSTEMTIME; //定义的时间类型SYSTEMTIME CurrentTime;#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)(4) {unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)(5) {unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;//在下降沿数据从移位寄存器输出}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;//只有在clk为低时,才能将rst置高DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;//上升沿将数据写入DS1302内部移位寄存器DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据(3){unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;//启动数据传送DS1302InputByte(ucAddr|0x01); // 地址,命令,读操作(4)ucData = DS1302OutputByte(); // 读1Byte数据,应在上升沿前读取(5)DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void naozhong(uchar x){uchar c = 0;c = 4 * x;Nfen = 0xc1 + c;Nshi = 0xc3 + c;}/***********DS1302按键部分子程序******************/void jia(uchar p, uchar max, uchar com)//p读取时间单位的值,max进制,com地址{p = ((p & 0x70) >>4 ) * 10 + (p & 0x0f);p ++;if(p / max)p =0 ;p = (p / 10) * 16 + p % 10;Write1302(com, p);}void jian(uchar p, uchar max, uchar com)//p读取秒的值,max进制,com地址{p = ((p & 0x70) >>4 ) * 10 + (p & 0x0f);p --;if(p == 255)p = max ;p = (p / 10) * 16 + p % 10;Write1302(com,p);}void keyscan(){if(!key1){delay(5);if(!key1 ){k++;Write1302(0x8e,0x00);if(k==4)k=0, Write1302(0x8e,0x80);while(!key1);}}if(!key2){delay(5);if(!key2){if(dif_flag == 0){switch(k){case 1:jia(Read1302(DS1302_SECOND), 60, 0x80); break;case 2:jia(Read1302(DS1302_MINUTE), 60, 0x82); break;case 3:jia(Read1302(DS1302_HOUR), 24, 0x84); break;}}if(dif_flag == 1){switch(k){case 1:jia(Read1302(DS1302_DAY), 32, 0x86); break;case 2:jia(Read1302(DS1302_MONTH), 13, 0x88); break;case 3:jia(Read1302(DS1302_YEAR), 100, 0x8c); break;}}if(dif_flag == 2){if(k == 1)jia(Read1302(DS1302_WEEK), 8, 0x8a);}while(!key2);}}if(!key3){delay(5);if(!key3){if(dif_flag == 0){switch(k){case 1:jian(Read1302(DS1302_SECOND), 60, 0x80); break;case 2:jian(Read1302(DS1302_MINUTE), 60, 0x82); break;case 3:jian(Read1302(DS1302_HOUR), 24, 0x84); break;}}if(dif_flag == 1){switch(k){case 1:jian(Read1302(DS1302_DAY), 32, 0x86); break;case 2:jian(Read1302(DS1302_MONTH), 13, 0x88); break;case 3:jian(Read1302(DS1302_YEAR), 100, 0x8c); break;}}if(dif_flag == 2){if(k == 1)jian(Read1302(DS1302_WEEK), 8, 0x8a);}while(!key3);}if(key5 ==0);//key5 = 1;}void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组(2){unsigned char ReadV alue;ReadValue = Read1302(DS1302_SECOND);//(3)Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//16进制转为10进制ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadV alue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadV alue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadV alue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadV alue&0x0F);}void show_time() //液晶显示程序(1){uchar f=2;DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据(2)read[0]=CurrentTime.Second;read[1]=CurrentTime.Minute;read[2]=CurrentTime.Hour;read[3]=CurrentTime.Week;read[4]=CurrentTime.Day;read[5]=CurrentTime.Month;read[6]=CurrentTime.Year;read[7]=0x00;if(!key){delay(5);if(!key)dif_flag++;while(!key)if(!key5){Write1302(0x8e,0x00);//写写保护寄存器禁止写保护Write1302(0x80,0x00);//写秒Write1302(0x90,0xab);//写充电寄存器Write1302(0x82,0x00);//分Write1302(0x84,0x12);//时Write1302(0x86,0x01);//日Write1302(0x88,0x05);//月Write1302(0x8a,0x02);//周Write1302(0x8c,0x12);//年Write1302(0x8e,0x80);//写保护}}}if(dif_flag==3)dif_flag=0;for(f=2;f>0;f--){if(dif_flag==0)display(read[0],read[1],read[2]);else if(dif_flag==1)display(read[4],read[5],read[6]);else if(dif_flag==2)display(read[3],read[7],read[7]);}}//显示延时函数void dis_delay(uchar x){uchar i;for(i=0;i<x;i++);}void delay(uint x){uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}/*****************DS18B20******************/void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command {uint i;DQ = 0; //单片机拉低总线i=70;while(i>0)i--;DQ = 1; //释放总线,即拉高了总线i=4;while(i>0)i--;}bit Read_One_bit() //读取一个字节的数据read a byte date//读数据时,数据以字节的最低有效位先从总线移出{uint i;bit dat;DQ=0;i++;DQ=1;i++;i++;dat=DQ;i=5;while(i>0)i--;return (dat);}uchar Read_One_Byte(void){uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=Read_One_bit();dat=(j<<7)|(dat>>1);}return (dat);}void Write_One_Byte(uchar dat){uint i;uchar j;bit testb;show_time();for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){DQ=0;i++;i++;DQ=1;i=5;while(i>0)i--;}else{DQ=0;i=5;while(i>0)i--;DQ=1;i++;i++;}}}void tmpchange(void){uchar f;Init_Ds18b20();f=70;while(f>0)f--;Write_One_Byte(0xcc); //忽略ROM指令Write_One_Byte(0x44); //温度转换指令}uint Get_Tmp() //获取温度get the temperature{uchar a,b,f;Init_Ds18b20(); //初始化f=70;while(f>0)f--;show_time();Write_One_Byte(0xcc); //忽略ROM指令Write_One_Byte(0xbe); //温度转换指令a = Read_One_Byte(); //读取到的第一个字节为温度LSBb = Read_One_Byte(); //读取到的第一个字节为温度MSBshow_time();if(b>127){flag=1;a=~a;b=~b;a+=0x01;}else{flag=0;}temp = b; //先把高八位有效数据赋于temptemp <<= 8; //把以上8位数据从temp低八位移到高八位temp = temp|a; //两字节合成一个整型变量f_temp = temp*0.0625; ////temp = (f_temp*10+0.5)*0.9; //放大十倍//0.9调试加上理论不需要temp = f_temp*10+0.5;//f_temp=f_temp+0.5; // //同时进行一个四舍五入操作。