#include<reg51.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int sbit CLK_1302 = P3^5; sbit DIO_1302 = P3^6; sbit RST_1302 = P3^7; sbit K1 = P1^0; sbit K2 = P1^1; sbit K3 = P1^2; sbit K4 = P1^3; sbit P2_7=P2^7; uchar shift; uchar code seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d, 0x7d,0x07,0x7f,0x6f,0x40,0x00}; uchar data disbuf[6]; uchar init [] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uchar init1[] ={0x00,0x00}; /******************************************************************/ void delay_10us(uchar n) { do { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } while(n--); }
void delay_ms(uint n) { do delay_10us(131); while(n--); } /**********************************************************/
/*底层函数,写1B数据到1302
/**********************************************************/ void write_byte(uchar inbyte) { uchar i; for(i=0;i<8;i++) { CLK_1302=0; //写的时候低电平改变数据 if(inbyte&0x01) DIO_1302=1; else DIO_1302=0; CLK_1302=1; //写的时候高电平,把数据写入ds1302 _nop_(); inbyte=inbyte>>1; } } /**********************************************************/
/*底层函数,从1302读1B数据
/**********************************************************/ uchar read_byte() //sclk的下跳沿读数据 { uchar i,ch=0; DIO_1302=1; //设置为输入口 for(i=0;i<7;i++) { CLK_1302=0; if(DIO_1302==1) ch=ch|0x80; else ch=ch&0x7f; CLK_1302=1; //产生下跳沿 ch=ch>>1; } return (ch); }
/**********************************************************/ /* 往ds1302的某个地址写入数据 /**********************************************************/ void write_ds1302(uchar cmd,uchar indata) { CLK_1302=0; RST_1302=1; write_byte(cmd); write_byte(indata); CLK_1302=0; RST_1302=0; }
/**********************************************************/ /* 读ds1302某地址的的数据 /**********************************************************/ uchar read_ds1302(uchar addr) { uchar backdata; CLK_1302=0; RST_1302=1;
write_byte(addr); //先写地址 backdata=read_byte(); //然后读数据 CLK_1302=0; RST_1302=0; return (backdata); }
/**********************************************************/ /* 设定值写入DS1302 /**********************************************************/ void Set_W1302(uchar addr) { uchar temp; write_ds1302(0x8e,0x00); temp=(init1[0]<<4)+init1[1]; write_ds1302(addr,temp); write_ds1302(0x8e,0x80); }
/**********************************************************/ /* 读取当前时间 /**********************************************************/ void read_nowtime(uchar addr,uchar *p,uchar n) { for(;n>0;n--) { *p=read_ds1302(addr); p++; addr=addr+2; } }
/*********************************************************/ /* LED显示函数 /*********************************************************/ void display_led(uchar t) { uchar i,temp; P2=0x00; SCON=0x00; temp=0x7f; //led显示 SBUF=temp; while(!TI);TI=0; for(i=0;i<6;i++) { P2=seg[disbuf]; delay_ms(t); if(temp==0xfd) break; P2=0x00; temp=temp<<7|temp>>1; SBUF=temp; while(!TI);TI=0; } P2=0x00; temp=0xef; SBUF=temp; while(!TI);TI=0; for(i=0;i<3;i++) //显示点,用于隔开分时秒,年月日 { P2_7=1; delay_ms(t); P0=0x00; temp=temp<<2|temp>>6; SBUF=temp; while(!TI);TI=0; } } /*********************************************************/ /* LED时间数据送入缓冲器 /*********************************************************/ void display_led_clk(void) { read_nowtime(0x81,init,3); //读出当前时间,读出7个字节 disbuf[0]=(init[2]&0xf0)>>4; disbuf[1]=init[2]&0x0f; //时分秒 disbuf[2]=(init[1]&0xf0)>>4; disbuf[3]=init[1]&0x0f; disbuf[4]=(init[0]&0xf0)>>4; disbuf[5]=init[0]&0x0f; } /*********************************************************/ /* LED日期数据送入缓冲器 /*********************************************************/ void display_led_date(void) { init[6]=read_ds1302(0x87); disbuf[4]=(init[6]&0xf0)>>4; disbuf[5]=init[6]&0x0f; init[4]=read_ds1302(0x89); disbuf[2]=(init[4]&0xf0)>>4; //年月日 disbuf[3]=init[4]&0x0f; init[3]=read_ds1302(0x8d); disbuf[0]=(init[3]&0xf0)>>4; disbuf[1]=init[3]&0x0f; } /*********************************************************/ /* LED星期数据送入缓冲器 /*********************************************************/ void display_led_week(void) { uchar i; init[5]=read_ds1302(0x8b); for(i=0;i<5;i++) disbuf=10; disbuf[5]=init[5]&0x0f; //周 } /**********************************************************/ /*主函数 /**********************************************************/ void main() { P2=0x00; SCON=0x00; while(1) { if(!K1) delay_ms(10); if(!K1) shift++; while(!K1); if(shift==3) shift=0; switch(shift) { case 0: display_led_clk(); display_led(1); break; case 1: display_led_date(); display_led(1); break; case 2: display_led_week(); display_led(1); break;
}
} } 上面程序是实现数字时钟,及年月日,周切换显示 在proteus上,可以仿真。可是硬件不能实现 会不会是DS1302那时序出了问题。 请大侠指点,谢谢啦!~~
|