DS1302数码管显示程序
- 格式:doc
- 大小:28.50 KB
- 文档页数:7
/**************************************************;文件名:DS1302.c;功能:设置时间,然后将时间读出显示在数码管上;硬件描述:PORTD口接数码管的8个笔段; PORTA 0~2及PORTE 0~2分别接6位数码管的位;RC3接SCK,RC4接SDA,RC2接RST*/#include "pic.h"#define uchar unsigned char#define uint unsigned int#define Hidden 16__CONFIG(HS&WDTDIS&LVPDIS); //配置文件,设置为HS方式振荡,禁止看门狗,低压编程关闭ucharDispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x8 6,0x8E,0xFF};uchar BitTab[]={0xfb,0xfd,0xfe};uchar DispBuf[6];#define LSB 0x01#define WrEnDisCmd 0x8e //写允许/禁止指令代码#define WrEnDat 0x00 //写允许数据#define WrDisDat 0x80 //写禁止数据#define OscEnDisCmd 0x80 //振荡器允许/禁止指令代码#define OscEnDat 0x00 //振荡器允许数据#define OscDisDat 0x80 //振荡器禁止数据#define WrMulti 0xbe //写入多个字节的指令代码#define WrSingle 0x84 //写入单个字节的指令代码#define RdMulti 0xbf //读出多个字节的指令代码#define cClk RC3 //与时钟线相连的PIC16F877A芯片的管脚#define cDat RC4 //与数据线相连的PIC16F877A芯片的管脚#define cRst RC2 //与复位端相连的PIC16F877A芯片的管脚#define SCL_CNT TRISC3 //SCL管脚控制位#define SDA_CNT TRISC4 //SDA管脚控制位#define RST_CNT TRISC2 //RST管脚控制位void mDelay(uint DelayTime){ uint temp;for(;DelayTime>0;DelayTime--){ for(temp=0;temp<270;temp++){;}}}void interrupt Disp(){ static uchar dCount; //用作显示的计数器if(TMR1IF==1&&TMR1IE==1)//Timer 1 inetrrupt{TMR1H=-(8000/256);TMR1L=-(8000%256); //重置定时初值}PORTA|=0x07; //关前面的显示PORTE|=0X07; //关前面的显示PORTD=DispTab[DispBuf[dCount]]; //显示第i位显示缓冲区中的内容if(dCount<3)PORTE&=BitTab[dCount]; //第1~3位是由PORTE控制的elsePORTA&=BitTab[dCount-3]; //第4~6位是由PORTA的低3位控制的dCount++;if(dCount==6)dCount=0;TMR1IF=0; //清中断标志}//数码管位 1 2 3 4 5 6//引脚RE0 RE1 RE2 RA2 RA1 RA0//根据这个表,只要改变PORTA&=0xfe,即可点亮任意一个数码管//例:PORTA&=0xfd //点亮第5位数码管// PORTE&=0xfe //点亮第3位数码管void uDelay(uchar i){ for(;i>0;i--){;}}void SendDat(uchar Dat){ uchar i;for(i=0;i<8;i++){cDat=Dat&LSB; //数据端等于tmp数据的末位值Dat>>=1;cClk=1;uDelay(1);cClk=0;}}/*写入1个或者多个字节,第1个参数是相关命令#define WrMulti 0xbe //写入多个字节的指令代码#define WrSingle 0x84 //写入单个字节的指令代码第2个参数是待写入的值第3个参数是待写入数组的指针*/void WriteByte(uchar CmdDat,uchar Num,uchar *pSend){uchar i=0;SDA_CNT=0; //数据端设为输出cRst=0;uDelay(1);cRst=1;SendDat(CmdDat);for(i=0;i<Num;i++){ SendDat(*(pSend+i));}cRst=0;}/*读出字节,第一个参数是命令#define RdMulti 0xbf //读出多个字节的指令代码第2个参数是读出的字节数,第3个是指收数据数组指针*/void RecByte(uchar CmdDat,uchar Num,uchar *pRec){uchar i,j,tmp;SDA_CNT=0; //数据端设为输出cRst=0; //复位引脚为低电平uDelay(1);cClk=0;uDelay(1);cRst=1;SendDat(CmdDat); //发送命令SDA_CNT=1; //数据端设为输入for(i=0;i<Num;i++){ for(j=0;j<8;j++){ tmp>>=1;if(cDat)tmp|=0x80;cClk=1;uDelay(1);cClk=0;}*(pRec+i)=tmp;}uDelay(1);cRst=0;}/*当写保护寄存器的最高位为0时,允许数据写入寄存器。
DS1302应用刚学单片机,好多好奇,所以想做个简单的时钟。
下面是PROTEUS仿真电路和电路图,简单易懂。
文笔不好,说了多余。
下面是程序。
#include<reg52.h>#include<intrins.h>#include<ds1302.h>#define uint unsigned int#define uchar unsigned char#define BCDTUAN(str) (str/10*16+str%10) //定义宏,将要写入DS1302的时间转化为BCD码#define Write_Sec 0x80#define Write_Min 0x82#define Write_Hou 0x84#define Write_Dat 0x86#define Write_Mon 0x88#define Write_day 0x8a#define Write_Yea 0x8c#define Write_WP 0x8e //写保护位#define Write_TCR 0x90#define Read_Sec 0x81#define Read_Min 0x83#define Read_Hou 0x85#define Read_Dat0x87#define Read_Mon 0x89#define Read_Day 0x8b#define Read_Yea 0x8d#define CLK_BurstW 0xbf //时钟突发模式写#define CLK_BurstR 0xbf //时钟突发模式读#define Write_RAM_Begin 0xc0 //RAM第一个字节写指令#define Read_RAM_Begin 0xc1 //RAM第一个字节读指令#define RAM_BurstW 0xfe //突发模式写RAM#define RAM_BurstR 0xff //突发模式读RAMsbit _74hc154_A = P1^0;sbit _74hc154_B = P1^1;sbit _74hc154_C = P1^2;sbit _74hc154_D = P1^3;sbit CE =P1^6;sbit SCLK=P1^5;sbit IO =P1^4;uchar code scan[][4]={{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{0,1,0,0},{0,1,0,1},{0,1,1,0},{0,1,1,1},{1,0,0,0},{1,0,0,1},{1,0,1,0},{1,0,1,1},{1,1,0,0},{1,1,0,1},{1,1,1,0},{1,1,1,1}};uchar scanbuff[]={0,0,0,0,0,0,0,0,0,0,0,0};uchar code dispdate[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};void WriteDS1302(void); //向DS1302写入时间。
DS1302+AT89S51单片机时钟C程序(六位共阳数码管显示)DS1302+A T89S51单片机时钟C程序(六位共阳数码管显示)//DS1302时钟芯片程序#include#define uchar unsigned char#define uint unsigned intsbit CLK=P2^3; //定义口sbit IO=P2^4;sbit RST=P2^5;sbit ACC7=ACC^7;sbit ACC0=ACC^0;uchara[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}, //定义数码管显示码b[8]={0x00,0x00,0x12,0x23,0x11,0x07,0x08,0xbe},//写入时钟数据,最后be突发访问c[7],s,s1,ml1,mh1,ml2,mh2,ml3,mh3; //c存放读.出时钟数据void delay(uint z) // 延时{uint i;uchar j;for(i=z;i>0;i--)for(j=200;j>0;j++);}// 显示子程序void display(uchar mh1,uchar ml1,uchar mh2,uchar ml2,uchar mh3,uchar ml3){uchar x,k,r;for(k=0;k<80;k++){for(r=0;r<8;r++){x=P2&0XF8; P2=x+r ;if(r==2||r==5) { P0=0XBF; delay(3); }//------秒------- if(r==0) {P0=a[ml1] ;delay(3) ;}if(r==1){P0=a[mh1] ; delay(3) ;}//------fen--------- if(r==3) {P0=a[ml2] ; delay(3) ;}if(r==4){P0=a[mh2] ; delay(3) ;}//-----shi---------if(r==6){P0=a[ml3] ;delay(3) ;}if(r==7){P0=a[mh3] ;delay(3) ;}delay(3);}}}//********DS1302读写程序************ void w(uchar u) //写入1位字节{uchar i;ACC = u;for(i=8; i>0; i--){IO = ACC0;CLK = 1;CLK = 0;ACC = ACC >> 1;}}uchar r(void) //读出1位字节{uchar i;for(i=8; i>0; i--){ACC = ACC >>1;ACC7 = IO;CLK = 1;CLK = 0;}return(ACC);}void W1302(uchar ucAddr, uchar ucDa){RST = 0;CLK = 0;RST = 1;w(ucAddr); // 地址,命令w(ucDa); //写1Byte数据CLK = 1;RST = 0;}void wclock(uchar *p) //写入时钟多字节数据{uchar i;// W1302(0x80,0x00); //停止时钟W1302(0x8e,0x00); // 允许写RST=0;CLK=0;RST=1;w(0xbe); //写多字节命令for(i=8;i>0;i--){w(*p); //按数组指针逐个写入,写入数据在主函数调用时指向b数组p++;}W1302(0x00,0x50); //启动定时器CLK=1;RST=0;}void rclock(uchar *p) //读出时钟多字节数据{uchar i;RST=0;CLK=0;RST=1;w(0xbf);for(i=7;i>0;i--){*p=r();p++;}CLK=1;RST=0;}void main(void){uchar mh,ml,fh,fl,sh,sl,z,v,q,e,y,t,k; wclock(b);while(1){rclock(c);mh=(c[0]&0xf0)>>4;ml=c[0]&0x0f;fh=(c[1]&0xf0)>>4;fl=c[1]&0x0f;sh=(c[2]&0xf0)>>4;sl=c[2]&0x0f;display(mh,ml,fh,fl,sh,sl);if(mh==3&&ml==0) { for(k=0;k<3;k++) {z=(c[3]&0xf0)>>4; v=c[3]&0x0f;q=(c[4]&0xf0)>>4; e=c[4]&0x0f;y=(c[6]&0xf0)>>4; t=c[6]&0x0f; display(z,v,q,e,y,t); } }}}。
DS1302可调时钟+DS18B20温度数码管切换显示(2013-01-04 15:30:28)转载▼标签:校园#include#include#define uchar unsigned char#define uint unsigned int#define Write_Protect 0x8e //写保护#define OutPut P2 //显示输出sbit DQ=P1^7; //ds18b20单总线定义为P1.7sbit Beep=P3^2; //蜂鸣器输出端定义为P3.2sbit RST=P1^2; //复位端口定义在P1.2引脚sbit IO=P1^1; //数据输出端定义在P1.1引脚sbit SCLK=P1^0; //时钟输出端口定义在P1.0引脚sbit key=P1^3; //时间调节控制键sbit key1=P1^5; //每按一次位加一sbit key2=P1^4; //每按一次位减一sbit key3=P1^6; //显示切换uchar data disdata[5];uint tvalue;//温度值uchar tflag;//温度正负标志uchar code Wei[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //位选数据uchar code Duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0--9共阴代码code uchar Waddr[]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a};code uchar Raddr[]={0x81,0x83,0x85,0x87,0x89,0x8d,0x8b};uchar timeset[]={0x01,0x02,0x03,0x04,0x05,0x00,0x01};uchar time_buf[7];uchar time_disp[7];uchar dispdat[8];uchar Btdis=0,k=0,z;bit btx,btx1,btx2,btx3,bt1,bt2,bt3;bit Btread;void ex_model(); //显示模式切换void delaynms(uchar n){uchar i,j;for(i=n;i>0;i--)for(j=125;j>0;j--);}void Ds1302_Write_Byte(unsigned char addr, unsigned char d){unsigned char i;RST=1;//写入目标地址:addraddr = addr & 0xFE; //最低位置零for (i = 0; i < 8; i++){if (addr & 0x01){IO=1;}else{IO=0;}SCLK=1;SCLK=0;addr = addr >> 1; }//写入数据:dfor (i = 0; i < 8; i++){if (d & 0x01){IO=1;}else{IO=0;}SCLK=1;SCLK=0;d = d >> 1;}RST=0; //停止DS1302总线}uchar Ds1302_Read_Byte(unsigned char addr){unsigned char i;unsigned char temp;RST=1;//写入目标地址:addraddr = addr | 0x01; //最低位置高for (i = 0; i < 8; i ++){if (addr & 0x01)IO=1;}else{IO=0;}SCLK=1;SCLK=0;addr = addr >> 1;}//输出数据:tempfor (i = 0; i < 8; i++){temp = temp >> 1;if (IO){temp |= 0x80;}else{temp &= 0x7F;SCLK=1;SCLK=0;}RST=0; //停止DS1302总线return temp;}void Write1302(uchar dat){uchar i;SCLK=0;for(i=0;i<8;i++){IO=dat&0x01;SCLK=1;SCLK=0;dat=dat>>1;}}uchar Readset1302(uchar Cmd){uchar dat;SCLK=0;RST=1;Write1302(Cmd);SCLK=1;RST=0;return dat;}void Ds1302_Write_Time(void){unsigned char i,tmp;uchar flag;flag=Readset1302(0x81);if(flag&0x80) //判断时钟芯片是否停止,为1时时钟停止{//掉电保存for(i=0;i<7;i++) //BCD 处理{tmp=timeset[i]/10;//timeset[]={0x01,0x02,0x03,0x04,0x05,0x06,0x01}time_buf[i]=timeset[i]; //time_buf[7]time_buf[i]=time_buf[i]+tmp*16;}Ds1302_Write_Byte(0x8e,0x00); //关闭写保护Ds1302_Write_Byte(Waddr[6],time_buf[6]); //周Ds1302_Write_Byte(Waddr[5],time_buf[0]); //年Ds1302_Write_Byte(Waddr[4],time_buf[1]); //月Ds1302_Write_Byte(Waddr[3],time_buf[2]); //日Ds1302_Write_Byte(Waddr[2],time_buf[3]); //时Ds1302_Write_Byte(Waddr[1],time_buf[4]); //分Ds1302_Write_Byte(Waddr[0],time_buf[5]); //秒Ds1302_Write_Byte(0x8e,0x80); //打开写保护}}void Ds1302_Read_Time(void){unsigned char i,tmp;// Ds1302_Write_Byte(0x8e,0x00); //关闭写保护time_buf[0]=Ds1302_Read_Byte(Raddr[5]); //年time_buf[1]=Ds1302_Read_Byte(Raddr[4]); //月time_buf[2]=Ds1302_Read_Byte(Raddr[3]); //日time_buf[3]=Ds1302_Read_Byte(Raddr[2]); //时time_buf[4]=Ds1302_Read_Byte(Raddr[1]); //分time_buf[5]=(Ds1302_Read_Byte(Raddr[0]))&0x7F; //秒time_buf[6]=Ds1302_Read_Byte(Raddr[6]); //周// Ds1302_Write_Byte(0x8e,0x80); //打开写保护for(i=0;i<8;i++) //BCD 处理{tmp=time_buf[i]/16;//time_buf[]={年,月,日,时,分,秒,周}time_buf[i]=time_buf[i];time_disp[i]=time_buf[i]+tmp*10;}}void Ds1302_Init(void){RST=0;//RST脚置低SCLK=0;//SCK脚置低Ds1302_Write_Byte(0x80,0x00);}void display(){uchar i;if(Btdis==0){if(bt2==0){dispdat[0]=Duan[time_disp[3]/10]; //时dispdat[1]=Duan[time_disp[3]];}else{dispdat[0]=0xff;dispdat[1]=0xff;}dispdat[2]=0xbf; //"-"if(bt3==0){dispdat[3]=Duan[time_disp[4]/10]; //分dispdat[4]=Duan[time_disp[4]];}else{dispdat[3]=0xff;dispdat[4]=0xff;}dispdat[5]=0xbf;dispdat[6]=Duan[time_disp[5]/10]; //秒dispdat[7]=Duan[time_disp[5]];}if(Btdis==1){if(bt1==0){dispdat[0]=Duan[time_disp[0]/10]; //年dispdat[1]=Duan[time_disp[0]];}else{dispdat[0]=0xff;dispdat[1]=0xff;}dispdat[2]=0xbf; //"-"if(bt2==0){dispdat[3]=Duan[time_disp[1]/10]; //月dispdat[4]=Duan[time_disp[1]];}else{dispdat[3]=0xff;dispdat[4]=0xff;}dispdat[5]=0xbf;if(bt3==0){dispdat[6]=Duan[time_disp[2]/10]; //日dispdat[7]=Duan[time_disp[2]];}else{dispdat[6]=0xff;dispdat[7]=0xff;}}if(Btdis==2){dispdat[0]=0xff;if(bt1==0){dispdat[1]=Duan[time_disp[6]]; //周}else{dispdat[1]=0xff;}dispdat[2]=0xbf; //"-" dispdat[3]=0xbf;dispdat[4]=0xbf;dispdat[5]=0xbf;dispdat[6]=Duan[time_disp[5]/10];dispdat[7]=Duan[time_disp[5]];}if(Btdis==3){ds1820disp();}for(i=0;i<8;i++){P0=dispdat[i];OutPut=Wei[i]; //Wei[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}delaynms(1);P0=0xff;}}void baoshi(){ uchar i;if(((time_disp[4])==59)&&((time_disp[5])>=55)&&((time_disp[5])<=60))//分和秒的报时条件{for(i=0;i<8;i++) //小灯轮流点亮,蜂鸣器发出滴答声{P3=Duan[i];delaynms(300);}}elseP3=0xdb;}void keyscan(){display();if(!key){if(btx==0){if(!key){btx=1;k++;}while(k==1){Btdis=1;display();if(!key){if(btx==0){if(!key){btx=1;k++;}}}else{btx=0;}if(!key1){if(btx1==0){if(!key1){btx1=1;if(time_disp[0]<99){time_disp[0]++;}else{time_disp[0]=0;}}}}else{btx1=0;}if(!key2){if(btx2==0){if(!key2){btx2=1;if(time_disp[0]>0){time_disp[0]--;}else{time_disp[0]=99;}}}}else{btx2=0;}}while(k==2){Btdis=1;display();if(!key){if(btx==0){if(!key){btx=1;k++;}}}else{btx=0;}if(!key1){if(btx1==0){if(!key1){btx1=1;if(time_disp[1]<12){time_disp[1]++;if(time_disp[1]==2){if(time_disp[0]%4==0){if(time_disp[2]>29){time_disp[2]=29;}}else if(time_disp[2]>28){time_disp[2]=28;}}}else{time_disp[1]=1;}}}}else{btx1=0;}if(!key2){if(btx2==0){if(!key2){btx2=1;if(time_disp[1]>1){time_disp[1]--;if(time_disp[1]==2){if(time_disp[0]%4==0){if(time_disp[2]>29){time_disp[2]=29;}}else if(time_disp[2]>28){time_disp[2]=28;}}}else{time_disp[1]=12;}}}}else{btx2=0;}}while(k==3){Btdis=1;display();if(!key){if(btx==0){if(!key){btx=1;k++;}}}else{btx=0;}if(!key1){if(btx1==0){if(!key1){btx1=1;if(time_disp[1]==2){if(time_disp[0]%4==0){if(time_disp[2]<29){time_disp[2]++;}else{time_disp[2]=1;}}else if(time_disp[2]<28){time_disp[2]++;}else{time_disp[2]=1;}}else if(time_disp[1]<8){if(time_disp[1]%2==0) //小于8月的月份除以2的余数为0则为小月{if(time_disp[2]<30){time_disp[2]++;}else{time_disp[2]=1;}}else if(time_disp[1]%2==1) //小于8月的月份除以2的余数为1则为大月{if(time_disp[2]<31){time_disp[2]++;}else{time_disp[2]=1;}}}else if(time_disp[1]>7){if(time_disp[1]%2==0){if(time_disp[2]<31){time_disp[2]++;}else{time_disp[2]=1;}}else if(time_disp[1]%2==1){if(time_disp[2]<30){time_disp[2]++;}else{time_disp[2]=1;}}}}}}else{btx1=0;}if(!key2){if(btx2==0){if(!key2){btx2=1;if(time_disp[1]==2){if(time_disp[0]%4==0){if(time_disp[2]>1){time_disp[2]--;}{time_disp[2]=29;}}else if(time_disp[2]>1){time_disp[2]--;}else{time_disp[2]=28;}}else if(time_disp[1]<8){if(time_disp[1]%2==0){if(time_disp[2]>1){time_disp[2]--;}{time_disp[2]=30;}}else if(time_disp[1]%2==1){if(time_disp[2]>1){time_disp[2]--;}else{time_disp[2]=31;}}}else if(time_disp[1]>7){if(time_disp[1]%2==0){if(time_disp[2]>1)time_disp[2]--;}else{time_disp[2]=31;}}else if(time_disp[1]%2==1){if(time_disp[2]>1){time_disp[2]--;}else{time_disp[2]=30;}}}}}else{btx2=0;}}while(k==4){Btdis=2;display();if(!key){if(btx==0){if(!key){btx=1;k++;}}}{btx=0;}if(!key1){if(btx1==0){if(!key1){btx1=1;if(time_disp[6]<7){time_disp[6]++;}else{time_disp[6]=1;}}}else{btx1=0;}if(!key2){if(btx2==0){if(!key2){btx2=1;if(time_disp[6]>1){time_disp[6]--;}else{time_disp[6]=7;}}}}else{btx2=0;}}while(k==5){Btdis=0;display();if(!key){if(btx==0){if(!key){btx=1;k++;}}}{btx=0;}if(!key1){if(btx1==0){if(!key1){btx1=1;if(time_disp[3]<23){time_disp[3]++;}else{time_disp[3]=0;}}}else{btx1=0;}if(!key2){if(btx2==0){if(!key2){btx2=1;if(time_disp[3]>0){time_disp[3]--;}else{time_disp[3]=23;}}}}else{btx2=0;}}while(k==6){Btdis=0;display();if(!key){if(btx==0){if(!key){btx=1;k++;}}}{btx=0;}if(!key1){if(btx1==0){if(!key1){btx1=1;if(time_disp[4]<59){time_disp[4]++;}else{time_disp[4]=0;}}}else{btx1=0;}if(!key2){if(btx2==0){if(!key2){btx2=1;if(time_disp[4]>0){time_disp[4]--;}else{time_disp[4]=59;}}}}else{btx2=0;}}while(k==7){uchar tmp;uchar i;for(i=0;i<7;i++){timeset[i]=time_disp[i];}//将调整后的时候写入DS1302for(i=0;i<7;i++) //BCD 处理{tmp=timeset[i]/10;//timeset[]={0x01,0x02,0x03,0x04,0x05,0x06,0x01}time_buf[i]=timeset[i]; //time_buf[7]time_buf[i]=time_buf[i]+tmp*16;}Ds1302_Write_Byte(0x8e,0x00); //关闭写保护Ds1302_Write_Byte(Waddr[6],time_buf[6]); //周Ds1302_Write_Byte(Waddr[5],time_buf[0]); //年Ds1302_Write_Byte(Waddr[4],time_buf[1]); //月Ds1302_Write_Byte(Waddr[3],time_buf[2]); //日Ds1302_Write_Byte(Waddr[2],time_buf[3]); //时Ds1302_Write_Byte(Waddr[1],time_buf[4]); //分Ds1302_Write_Byte(Waddr[0],time_buf[5]); //秒Ds1302_Write_Byte(0x8e,0x80); //打开写保护k=0;}}else{btx=0;}if(!key3){if(btx3==0){if(!key3){btx3=1;if(Btdis<3){Btdis++;}else{Btdis=0;}}}}else{btx3=0;}}void ex_model(){if(((time_disp[5])>=0)&&((time_disp[5])<=8)) //前八秒显示温度Btdis=3;if(((time_disp[5])>=9)&&((time_disp[5])<=12)) //显示周Btdis=2;if(((time_disp[5])>=13)&&((time_disp[5])<=18)) //显示年Btdis=1;if(((time_disp[5])>=19)&&((time_disp[5])<=59)) //显示当前时间Btdis=0;}void tiaoshidisplay(){if(z==15){z=0;switch(k){case 1:bt1=~bt1;P3=~P3;break; //年case 2:bt2=~bt2;bt1=0;P3=~P3;break; //月case 3:bt3=~bt3;bt2=0;P3=~P3;break; //日case 4:bt1=~bt1;bt3=0;P3=~P3;break; //周case 5:bt2=~bt2;bt1=0;P3=~P3;break; //时case 6:bt3=~bt3;bt2=0;P3=~P3;break; //分default:bt3=0;break;}}}void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst(){ unsigned char x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd(){ unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){ DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar wdata){unsigned char i=0;for (i=8; i>0; i--) { DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}read_temp(){uchar a,b;ds1820rst();ds1820wr(0xcc);/ds1820wr(0x44);/ds1820rst();ds1820wr(0xcc);/ds1820wr(0xbe);/a=ds1820rd();。
DS1302驱动程序详解DS1302引脚介绍特性介绍驱动程序详解sbit IO=P1^0; //DS1302数据线sbit SCLK=P1^1; //DS1302时钟线sbit RST=P1^2; //DS1302复位线uchar WEEK[][4]={"SUN","***","MON","TUS","WEN","THU","FRI","SAT"}; //亦可定义成指针数组*WEEK[]uchar LCD_DSY_BUFFER1[]={"DA TE 00-00-00 "};uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00 "};uchar DateTime[7];void Initialize_LCD();void Display_LCD_String(uchar p,uchar *s);void DelayMS(uint ms);//------------------------------------------------------------------//向DS1302写入一个字节//------------------------------------------------------------------void Write_A_Byte_TO_DS1302(uchar x){uchar i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备for (i=0;i<8;i++){IO=x & 0x01; //取出x的第0位数据写入1302SCLK=1; //上升沿写入数据SCLK=0; //重新拉低SCLK,形成脉冲x >>=1; //将x的各数据位右移1位,准备写入下一个数据位}}//------------------------------------------------------------------//从DS1302读取一个字节,//注意:DS1302中所存放的数据是BCD码,在读写时要注意转换////------------------------------------------------------------------uchar Get_A_Byte_FROM_DS1302(){uchar i,b=0x00;for (i=0;i<8;i++){b |= _crol_((uchar)IO,i);//将uchar类型的IO数据左移i位SCLK=1; //将SCLK置于高电平,为下降沿读出SCLK=0; //时钟下降沿读取}return (b/16)*10+b%16; //将BCD码转换为十进制数}//------------------------------------------------------------------//从DS1302指定位置读取数据//------------------------------------------------------------------ uchar Read_Data(uchar addr){uchar dat;RST=0; //拉低RSTSCLK=0; //确保写数据前SCLK被拉低RST=1; //启动数据传输Write_A_Byte_TO_DS1302(addr); //写入命令字dat=Get_A_Byte_FROM_DS1302();SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递return dat;}//------------------------------------------------------------------//读取当前日期时间//------------------------------------------------------------------ void GetTime(){uchar i,addr =0x81;for (i=0;i<7;i++){DateTime[i] = Read_Data(addr);addr+=2;}}//------------------------------------------------------------------//日期与时间值转换为数字字符//------------------------------------------------------------------ void Format_DataTime(uchar d,uchar *a){a[0]=d/10+'0';a[1]=d%10+'0';}//------------------------------------------------------------------//主程序//------------------------------------------------------------------ void main(){Initialize_LCD();while(1){GetTime();Format_DataTime(DateTime[6],LCD_DSY_BUFFER1+5); //0x8D 年份寄存器Format_DataTime(DateTime[4],LCD_DSY_BUFFER1+8); //0x89 月份寄存器Format_DataTime(DateTime[3],LCD_DSY_BUFFER1+11); //0x87 日期寄存器//星期strcpy (LCD_DSY_BUFFER1+13,WEEK[DateTime[5]]);//将字符串WEEK[DateTime[5]]复制到字符数组LCD_DSY_BUFFER1+13中//0x8B 周日寄存器Format_DataTime(DateTime[2],LCD_DSY_BUFFER2+5); //0x85 小时寄存器Format_DataTime(DateTime[1],LCD_DSY_BUFFER2+8); //0x83 分钟寄存器Format_DataTime(DateTime[0],LCD_DSY_BUFFER2+11); //0x81 秒寄存器Display_LCD_String(0x00,LCD_DSY_BUFFER1); //第一行显示年、月、日、星期几Display_LCD_String(0x40,LCD_DSY_BUFFER2); //第二行显示小时、分钟、秒}}。
#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar table0[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; //液晶显示数字0——9代码sbit SCLK=P1^0;sbit DATA=P1^1;sbit CE=P1^2;sbit RS=P2^0;sbit RW=P2^1;sbit EN=P2^2;sbit FB=P0^7;sbit start=P1^4;sbit stop=P1^5;uchar i;/*******************延时n微秒函数*****************/void delaynus(uchar n) //n us延时函数{// uchar i;for(i=n;i>0;i--);}/*******************写数据函数*****************/void write1302(uchar add,uchar dat){CE=0;SCLK=0;CE=1;for(i=0;i<8;i++) //写入地址{DATA=add&0x01;SCLK=1;SCLK=0;add>>=1;}for(i=0;i<8;i++) //写入数据{DATA=dat&0x01;SCLK=1;SCLK=0;dat>>=1;}SCLK=1;CE=0;}/*******************读数据函数*****************/uchar read1302(uchar add){uchar dat;CE=0;SCLK=0;CE=1;for(i=8;i>0;i--) //写入地址{DATA=add&0x01;SCLK=1;SCLK=0;add>>=1;}for(i=8;i>0;i--) //读出数据/********************为神马???**************************/{dat>>=1;if(DATA==1)dat=dat|0x80;SCLK=1;SCLK=0;}SCLK=1;CE=0;return dat;}/*******************DS1302初始化函数*****************/void init1302(){uchar flag;flag=read1302(0x81);if(flag&0x80){write1302(0x8e,0x00);write1302(0x80,0x00);write1302(0x82,(((1/10)<<4)|(1%10)));write1302(0x84,(((20/10)<<4)|(20%10)));write1302(0x86,(((19/10)<<4)|(19%10)));write1302(0x88,(((7/10)<<4)|(7%10)));write1302(0x8a,((2/10)<<4)|(2%10));write1302(0x8c,(((11/10)<<4)|(11%10)));write1302(0x90,0xa5); //充电。
/*****************************************电路P1口接74HC573锁存4位数码管位远,P0接4位数码管段选。
P2.5,p2.6,p2.7接DS1302. *****************************************/ORG 0000HAJMP STARTORG 000BHAJMP TIM0SCLK EQU P2^7IO EQU P2^6RST EQU P2^5ALL_FLAG EQU 31H ;标志位SEC EQU 32H ;秒MIN EQU 33H ;分HOUR EQU 34H ;时DAY EQU 35H ;日MON EQU 36H ;月WEEK EQU 37H ;星期YEAR EQU 38H ;年DS_DAT EQU 39HDS_ADD EQU 3AHDS_DATA EQU 3BHS1 EQU r7ORG 70HSTART:MOV TMOD ,#00000001BMOV TH0 ,#HIGH(65536-1000);HIGH和LOW写反了会错MOV TL0 ,#LOW(65536-1000)SETB EASETB ET0SETB TR0LCALL DS_INITLOOP2:CALL DELAYCALL DELAYCALL DELAYCALL DELAYCALL DELAYCALL DELAYLCALL DS_R_TIMEsjmp LOOP2DELAY:MOV R1,#10 ;1ms延时子程序D0: MOV R2,#248DJNZ R2,$DJNZ R1,D0RET/***************************************** DS1302写字节函数*****************************************/ DS_W_BYTE:MOV R0,#08MOV A,DS_DATDS_W1:RRC AMOV IO,CNOPSETB SCLKnopCLR SCLKDJNZ R0,DS_W1RET/***************************************** DS1302读字节函数*****************************************/ DS_R_BYTE:SETB IOMOV A,#00HMOV R0,#08DS_R1:MOV C,IORRC ASETB SCLKNOPCLR SCLKNOPDJNZ R0,DS_R1MOV DS_DA T,ARET/***************************************** DS1302读数据函数入口地址存至DS_ADD;读取到的数据存入DS_DA T *****************************************/ DS_R_DAT:CLR RSTNOPCLR SCLKNOPSETB RSTNOPMOV DS_DA T,DS_ADDLCALL DS_W_BYTELCALL DS_R_BYTESETB SCLKCLR RSTNOPNOPSETB SCLKNOPNOPCLR IONOPNOPsetb IONOPNOPRET/***************************************** DS1302写数据函数入口地址DS_ADD,入口数据DS_DA TA*****************************************/ DS_W_DAT:CLR RSTNOPCLR SCLKNOPSETB RSTNOPMOV DS_DA T,DS_ADDLCALL DS_W_BYTEMOV DS_DA T,DS_DATALCALL DS_W_BYTEMOV DS_DA T,ASETB SCLKCLR RSTNOPNOPSETB SCLKNOPNOP ;加了延时CLR IONOPNOPsetb IONOPNOPRET/*****************************************DS1302读时间函数入口地址DS_ADD,*****************************************/DS_R_TIME:MOV DS_ADD,#81HLCALL DS_R_DATMOV SEC,DS_DATMOV DS_ADD,#83HLCALL DS_R_DATMOV MIN,DS_DATMOV DS_ADD,#85HLCALL DS_R_DATMOV HOUR,DS_DATMOV DS_ADD,#87HLCALL DS_R_DATMOV DAY,DS_DATMOV DS_ADD,#89HLCALL DS_R_DATMOV MON,DS_DATMOV DS_ADD,#8BHLCALL DS_R_DATMOV WEEK,DS_DATMOV DS_ADD,#8DHLCALL DS_R_DATMOV YEAR,DS_DATRET/*****************************************DS1302写时间函数入口地址DS_ADD,入口数据*****************************************/DS_W_TIME:CLR RSTCLR SCLKMOV DS_ADD,#8EH ;语序写MOV DS_DATA,#00HLCALL DS_W_DA TMOV DS_ADD,#80HMOV DS_DATA,SECLCALL DS_W_DA TMOV DS_ADD,#82HMOV DS_DATA,MINLCALL DS_W_DA TMOV DS_ADD,#84HMOV DS_DATA,HOURLCALL DS_W_DA TMOV DS_ADD,#86HMOV DS_DATA,DAYLCALL DS_W_DA TMOV DS_ADD,#88HMOV DS_DATA,MONLCALL DS_W_DA TMOV DS_ADD,#8AHMOV DS_DATA,WEEKLCALL DS_W_DA TMOV DS_ADD,#8CHMOV DS_DATA,YEARLCALL DS_W_DA TMOV DS_ADD,#8EH ;写保护MOV DS_DATA,#80HLCALL DS_W_DA TRET/*****************************************DS1302初始化*****************************************/DS_INIT:CLR RSTCLR SCLKMOV DS_ADD,#8EH ;允许写MOV DS_DATA,#00HLCALL DS_W_DA TMOV DS_ADD,#90HMOV DS_DATA,0xa5LCALL DS_W_DA TMOV DS_ADD,#80HMOV DS_DATA,#00HLCALL DS_W_DA TMOV DS_ADD,#82HMOV DS_DATA,#00HLCALL DS_W_DATMOV DS_ADD,#84HMOV DS_DATA,#23HLCALL DS_W_DA TMOV DS_ADD,#86HMOV DS_DATA,#16HLCALL DS_W_DA TMOV DS_ADD,#88HMOV DS_DATA,#12HLCALL DS_W_DA TMOV DS_ADD,#8aHMOV DS_DATA,#02HLCALL DS_W_DA TMOV DS_ADD,#8cHMOV DS_DATA,#14HLCALL DS_W_DA TMOV DS_ADD,#8EH ;写保护MOV DS_DATA,#80HLCALL DS_W_DA TRETTIM0:PUSH ACCPUSH PSWPUSH DPHPUSH DPLPUSH BMOV TH0 ,#HIGH(65536-1000) MOV TL0 ,#LOW(65536-1000) MOV A ,SECMOV B,#16DIV ABMOV 50H ,BMOV 51H, AMOV A,MINMOV B,#16DIV ABMOV 52H,BMOV 53h,AMOV A,HOURMOV B ,#16DIV ABMOV 54H,BMOV 55H,AINC S1MOV DPTR,#TABMOV P1,#0HCJNE S1,#1H,Z1NOPNOPMOV A ,50HMOVC A,@A+DPTRMOV P0,ASETB P1.0SJMP LOOPZ1:CJNE S1,#02H,Z2MOV A,51H MOVC A,@A+DPTRMOV P0,ASETB P1.1SJMP LOOPZ2:CJNE S1,#03H,Z3MOV P0,#0BFH SETB P1.2SJMP LOOPZ3:CJNE S1,#04H,Z4MOV A,52H MOVC A,@A+DPTRMOV P0,ASETB P1.3SJMP LOOPZ4:CJNE S1,#05H,Z5MOV A,53H MOVC A,@A+DPTRMOV P0,ASETB P1.4SJMP LOOPZ5:CJNE S1,#06H,Z6MOV P0,#0BFHSETB P1.5SJMP LOOPZ6:CJNE S1,#07H,Z7MOV A,54HMOVC A,@A+DPTRMOV P0,ASETB P1.6SJMP LOOPZ7:CJNE S1,#08H,Z8MOV A,55HMOVC A,@A+DPTRMOV P0,ASETB P1.7MOV S1,#0HSJMP LOOPZ8:LJMP 00HLOOP:POP BPOP DPLPOP DPHPOP PSWPOP ACCRETITAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFHEND。
#include<reg52.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charsbit k1=P1^0; //开关的位置sbit k2=P1^1;sbit k3=P1^2;sbit k4=P1^3;sbit clk=P3^6; //时钟线sbit en=P3^5; //使能端sbit io=P3^4; //DS1302的IO口sbit lcden=P2^7; //液晶使能端sbit lcdrd=P2^6; //数据命令端sbit lcdwr=P2^5; //读写选择端sbit beep=P2^4; //蜂鸣器位置bit flag; //按键标志位uchar code t[]="LCD LOCK"; //第一行显示字符uchar code b[]="****"; //第二行显示字符uchar c[8] ={0x00}; //定义显示缓冲区uchar d[7] ={0,0,0x12,0,0,0,0}; //DS1302时间缓冲区,存放秒、分、时、日、月、uchar e[2]={0}; //用来存放分钟小时的中间值void delay(uint x) //延时函数{ uint i,j;for(i=0;i<x;i++)for(j=0;j<115;j++); //延时X*MS}void write_com(uchar com) //命令函数{ lcdrd=0; //选择命令端P0=com; //要写的命令送到P0口delay(5);lcden=1; //开启使能端delay(5);lcden=0; //关闭使能端}void write_data(uchar dat) //数据函数{ lcdrd=1; //数据选择端P0=dat;delay(5);lcden=1; //开使能delay(5);lcden=0;}bit busy() //忙碌检查函数{ bit result;lcdrd=0;lcdwr=1;lcden=1;_nop_(); //延时几微秒_nop_();_nop_();_nop_();result=(bit)(P0&0x80);lcden=0;return result;}void lcdclr() //LCD清屏函数{ write_com(0x01); //清零显示,数据指针清零delay(5);}void init() //初始化函数{ delay(15);write_com(0x38); //16*2显示,5*7点阵,8位数据delay(15);write_com(0x38);write_com(0x06); //写一个字符地址指针加1 delay(5);write_com(0x0c); //设置显示,不显示光标delay(5);write_com(0x01); //显示清零,数据指针清零}void write_byte(uchar date) //写一个字节函数{ uchar i;for(i=0;i<8;i++){ clk=0; //低电平改变数据if(date&0x01)io=1;elseio=0;clk=1; //高电平写入1302_nop_();date=date>>1;}}uchar read_byte() //读一个字节函数{uchar i,temp=0;io=1;for(i=0;i<7;i++){clk=0;if(io==1)temp=temp|0x80;elsetemp=temp&0x7f;clk=1; //产生下跳沿temp=temp>>1;}return temp;}void write1302(uchar com,uchar dat) //写1302函数在某个地址写数据{ clk=0;en=1;write_byte(com);write_byte(dat);clk=0;en=0;}uchar read1302(uchar add) //读1302函数,从地址读数据{ uchar d;clk=0;en=1;write_byte(add); //先写地址d=read_byte(); //后读数据clk=0;en=0;return d;}void set1302(uchar add,uchar *p,uchar n) //时间初始化{ write1302(0x80,0x00); //写控制,允许写操作for(;n>0;n--){ write1302(add,*p);p++;add=add+2;}write1302(0x8e,0x80); //写保护,不允许写操作}void get1302(uchar add,uchar *p,uchar n) //读取当前数据{ for(;n>0;n--){ *p=read1302(add);p++;add=add+2;}}void init1302() //初始化1302函数{ en=0;clk=0;write1302(0x80,0x00); //写秒寄存器write1302(0x90,0xab); //写充电器write1302(0x8e,0x80); //写保护,禁止写}void BEEP() //蜂鸣器函数{ beep=0; //响蜂鸣器delay(100); //响0.1sbeep=1;delay(100);}void lcdcon(uchar m1,m2,m3) //将数据转化成适合LCD显示的数据{ c[0]=m1/10+0x30; //小时十位数据c[1]=m1%10+0x30; //小时个位数据c[2]=m2/10+0x30; //分钟十位数据c[3]=m2%10+0x30; //分钟个位数据c[4]=m3/10+0x30; //秒十位c[5]=m3%10+0x30; //秒个位}void lcddis() //LCD显示函数{ write_com(0x44|0x80); //第二行第四列write_data(c[0]); //小时十位write_data(c[1]); //小时个位write_data(':'); //显示:write_data(c[2]); //显示分钟十位write_data(c[3]); //显示分钟个位write_data(':');write_data(c[4]); //显示秒十位write_data(c[5]); //显示秒个位}void keyscan() //按键函数{ uchar fen,shi; //定义两个16位分钟和小时write1302(0x8e,0x00); //1302写保护,允许写write1302(0x80,0x80); //时钟停止运行if(k2==0) //按键2被按下{ d elay(10); //去抖动if(k2==0) //确认被按下{ while(!k2); //等待按键释放BEEP(); //蜂鸣器函数d[2]=d[2]+1; //小时加1if(d[2]==24) //满24清零d[2]=0;shi=d[2]/10*16+d[2]%10; //将小时转化成16进制write1302(0x84,shi); //调整后写入1302}}if(k3==0) //按键3被按下{ delay(10); //抖动if(k3==0) //确认被按下{ while(!k3); //等待按键放开BEEP(); //蜂鸣器函数d[1]=d[1]+1; //分钟加1if(d[1]==60) //满60清零d[1]=0;fen=d[1]/10*16+d[1]%10; //将分钟转化为16进制write1302(0x82,fen); //调整后,写入1302}}if(k4==0) //按键4被按下{ d elay(10); //去抖动if(k4==0) //确认被按下{ while(!k4); //等待按键释放BEEP(); //蜂鸣器函数write1302(0x80,0x00); //调整后,启动时钟运行write1302(0x8e,0x80); //写保护,禁止写flag=0; //按键1标志位清零}}}void gettime() //读取当前时间,转化为10进制{ uchar miao,fen,shi;write1302(0x8e,0x00); //控制命令,0表示允许写write1302(0x90,0xab); //电流控制miao=read1302(0x81); //读取秒fen=read1302(0x83); //读取分shi=read1302(0x85); //读取小时d[0]=miao/16*10+miao%16; //转化为10进制d[1]=fen/16*10+fen%16; //转化为10进制d[2]=shi/16*10+shi%16; //转换为10进制}void main() //主函数{ uchar i;P0=0xff;P2=0xff;init1302(); //1302初始化函数lcdclr(); //1302清屏函数write_com(0x00|0x80); //第一行第0列i=0;while(t[i]!=0){ write_data(t[i]); //第一个字符显示i++;}write_com(0x40|0x80); //第二行显示第0列i=0;while(b[i]!=0);{ write_data(b[i]);i++;}init1302();while(1){ gettime();if(k1==0) //按键1按下{ delay(10); //去抖动if(k1==0) //确认按下{ while(!k1); //等待按键释放BEEP(); //蜂鸣器函数flag=1; //按键1标志位置位,进行时钟调整}}if(flag==1) //如为1,则进行调整keyscan();lcdcon(d[2],d[1],d[0]); //将1302的数据送到函数转换lcddis(); //调整LCD显示,显示小时,分钟,秒}}。
/#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit beep=P3^5;sbit ds1302_RST=P2^5;sbit ds1302_IO=P2^6;sbit ds1302_SCLK=P2^7;sbit ACC0=ACC^0;sbit ACC7=ACC^7;void init();void delay_50us(uint t);void display();uchar read_Byte();void write_Byte(uchar tdata);void write_data_ds1302(uchar taddr,uchar tdata);uchar read_data_ds1302(uchar taddr);void set_ds1302(uchar *P1302);void get_ds1302() ;void init_ds1302();uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};uchar initial_time[]={0x00,0x00,0x12};// 秒分时日月周年uchar data now_time[3];/******************************************//* 主函数*//******************************************/void main(){init();init_ds1302();set_ds1302(initial_time);while(1){get_ds1302();display();}}/******************************************/ /* 延时子程序*/ /******************************************/ void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}/******************************************/ /* 初始化子程序*/ /******************************************/ void init(){P0=0xff;P2=0xff;P1=0x00;}/******************************************/ /* 数码管显示子程序*/ /******************************************/ void display(){uchar i;P1=0x01;i=now_time[0]%16; //显示秒个P0=table[i];delay_50us(20);P1=0x02;i=now_time[0]/16; //显示秒十P0=table[i];delay_50us(20);P1=0x04;P0=table[10];//显示"-"delay_50us(20);P1=0x08;i=now_time[1]%16; //显示分个P0=table[i];delay_50us(20);P1=0x10;i=now_time[1]/16; //显示分十P0=table[i];delay_50us(20);P1=0x20;P0=table[10]; //显示"-"delay_50us(20);P1=0x40;i=now_time[2]%16; //显示时个P0=table[i];delay_50us(20);P1=0x80;i=now_time[2]/16; //显示时十P0=table[i];delay_50us(10);}/*ds1302模块部分*//******************************************//* 读数据*//******************************************/uchar read_Byte(){uchar i;for(i=8;i>0;i--){ACC=ACC>>1;ACC7=ds1302_IO;//由于ds1302读数据的时候,第一个数据读取在发一个Byte命令后,在第八位的下降沿ds1302_SCLK=1;ds1302_SCLK=0;//产生下降沿输出一位数据}return(ACC);}/******************************************//* 写字节*//******************************************/void write_Byte(uchar tdata){uchar i;ACC=tdata;for(i=8;i>0;i--){ds1302_IO=ACC0;ds1302_SCLK=1;ds1302_SCLK=0;//产生上升沿输入数据ACC=ACC>>1;}}/******************************************//* 写数据*//******************************************/void write_data_ds1302(uchar taddr,uchar tdata){ds1302_RST=0;ds1302_SCLK=0;ds1302_RST=1;write_Byte(taddr);write_Byte(tdata);ds1302_RST=0;ds1302_SCLK=1;}/******************************************//* 读数据*//******************************************/uchar read_data_ds1302(uchar taddr){uchar tdata;ds1302_RST=0;ds1302_SCLK=0;ds1302_RST=1;write_Byte(taddr);tdata=read_Byte();ds1302_RST=0;ds1302_SCLK=1;return(tdata);}/******************************************//* 设置初始时间*//******************************************/void set_ds1302(uchar *P1302){uchar i;uchar taddr = 0x80;write_data_ds1302(0x8e,0x00); /* 控制命令,WP=0,写操作*/ for(i =3; i>0; i--){write_data_ds1302(taddr,*P1302); /* 秒分时日月星期年*/P1302++;taddr+=2;}write_data_ds1302(0x8e,0x80); /* 控制命令,WP=1,写保护*/}/*********************************************************************函数名:get_ds1302()*功能描述:设置初始时间*函数说明:先写地址,后读命令/数据*调用函数:*全局变量:*输入:now_time[];*返回:***********************************************************************/void get_ds1302(){uchar k;uchar taddr = 0x81;for (k=0; k<3.; k++){now_time[k] = read_data_ds1302(taddr);/*格式为: 秒分时日月星期年*/taddr+= 2;}}/******************************************//* 1302初始化*//******************************************/void init_ds1302(){ds1302_RST=0;ds1302_SCLK=0;write_data_ds1302(0x8e,0x00);write_data_ds1302(0x90,0xa5);//打开充电二级管一个二级管串联一个2K电阻}。
/****************************************************************************** ** 标题: 试验数码管显示时钟**** 通过本例程了解DS1302时钟芯片的基本原理和使用,理解并掌握DS1302时钟芯片** 驱动程序的编写以及实现数字字符在数码管中的显示。
** 注意:JP1302跳线冒要短接。
** 请学员认真消化本例程,懂DS1302在C语言中的操作******************************************************************************** */#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义#include <intrins.h>sbit SCK=P3^6; //时钟sbit SDA=P3^4; //数据sbit RST = P3^5;// DS1302复位sbit LS138A=P2^2;sbit LS138B=P2^3;sbit LS138C=P2^4;bit ReadRTC_Flag;//定义读DS1302标志unsigned char l_tmpdate[7]={0,0,12,15,5,3,8};//秒分时日月周年08-05-15 12:00:00unsigned char l_tmpdisplay[8];code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年最低位读写位code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};code unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴数码管0-9 '-' '熄灭‘表/******************************************************************//* 函数声明*//******************************************************************/void Write_Ds1302_byte(unsigned char temp);void Write_Ds1302( unsigned char address,unsigned char dat );unsigned char Read_Ds1302 ( unsigned char address );void Read_RTC(void);//read RTCvoid Set_RTC(void); //set RTCvoid InitTIMER0(void);//inital timer0/******************************************************************//* 主函数*//******************************************************************/void main(void){InitTIMER0(); //初始化定时器0Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽while(1){if(ReadRTC_Flag){ReadRTC_Flag=0;Read_RTC();l_tmpdisplay[0]=l_tmpdate[2]/16; //数据的转换,因我们采用数码管0~9的显示,将数据分开l_tmpdisplay[1]=l_tmpdate[2]&0x0f;l_tmpdisplay[2]=10; //加入"-"l_tmpdisplay[3]=l_tmpdate[1]/16;l_tmpdisplay[4]=l_tmpdate[1]&0x0f;l_tmpdisplay[5]=10;l_tmpdisplay[6]=l_tmpdate[0]/16;l_tmpdisplay[7]=l_tmpdate[0]&0x0f;}}}/******************************************************************//* 定时器0初始化*//******************************************************************/void InitTIMER0(void){TMOD|=0x01;//定时器设置16位TH0=0xef;//初始化值TL0=0xf0;ET0=1;TR0=1;EA=1;}/******************************************************************/ /* 写一个字节*/ /******************************************************************/ void Write_Ds1302_Byte(unsigned char temp){unsigned char i;for (i=0;i<8;i++) //循环8次写入数据{SCK=0;SDA=temp&0x01; //每次传输低字节temp>>=1; //右移一位SCK=1;}}/******************************************************************/ /* 写入DS1302 */ /******************************************************************/ void Write_Ds1302( unsigned char address,unsigned char dat ){RST=0;_nop_();SCK=0;_nop_();RST=1;_nop_(); //启动Write_Ds1302_Byte(address); //发送地址Write_Ds1302_Byte(dat); //发送数据RST=0; //恢复}/******************************************************************/ /* 读出DS1302数据*/ /******************************************************************/ unsigned char Read_Ds1302 ( unsigned char address ){unsigned char i,temp=0x00;RST=0;_nop_();_nop_();SCK=0;_nop_();_nop_();RST=1;_nop_();_nop_();Write_Ds1302_Byte(address);for (i=0;i<8;i++) //循环8次读取数据{if(SDA)temp|=0x80; //每次传输低字节SCK=0;temp>>=1; //右移一位_nop_();_nop_();_nop_();SCK=1;}RST=0;_nop_(); //以下为DS1302复位的稳定时间_nop_();RST=0;SCK=0;_nop_();_nop_();_nop_();_nop_();SCK=1;_nop_();_nop_();SDA=0;_nop_();_nop_();SDA=1;_nop_();_nop_();return (temp); //返回}/******************************************************************/ /* 读时钟数据*/ /******************************************************************/ void Read_RTC(void) //读取日历{unsigned char i,*p;p=read_rtc_address; //地址传递for(i=0;i<7;i++) //分7次读取秒分时日月周年{l_tmpdate[i]=Read_Ds1302(*p);p++;}}/******************************************************************/ /* 设定时钟数据*/ /******************************************************************/ void Set_RTC(void) //设定日历{unsigned char i,*p,tmp;for(i=0;i<7;i++){ //BCD处理tmp=l_tmpdate[i]/10;l_tmpdate[i]=l_tmpdate[i]%10;l_tmpdate[i]=l_tmpdate[i]+tmp*16;}Write_Ds1302(0x8E,0X00);p=write_rtc_address; //传地址for(i=0;i<7;i++) //7次写入秒分时日月周年{Write_Ds1302(*p,l_tmpdate[i]);p++;}Write_Ds1302(0x8E,0x80);}/******************************************************************/ /* 定时器中断函数*/ /******************************************************************/ void tim(void) interrupt 1 using 1//中断,用于数码管扫描{static unsigned char i,num;TH0=0xf5;TL0=0xe0;P0=table[l_tmpdisplay[i]]; //查表法得到要显示数字的数码段switch(i){case 0:LS138A=0; LS138B=0; LS138C=0; break;case 1:LS138A=1; LS138B=0; LS138C=0; break;case 2:LS138A=0; LS138B=1; LS138C=0; break;case 3:LS138A=1; LS138B=1; LS138C=0; break;case 4:LS138A=0; LS138B=0; LS138C=1; break;case 5:LS138A=1; LS138B=0; LS138C=1; break;case 6:LS138A=0; LS138B=1; LS138C=1; break;case 7:LS138A=1; LS138B=1; LS138C=1; break;}i++;if(i==8){i=0;num++;if(10==num) //隔段时间读取1302的数据。
DS1302时钟数码管显示DS1302时钟芯片,大家都知道是什么来的。
不懂的百度下就知道了。
这个只是读取出时间,其它功能没有写出来,用了四位共阳数码管显示。
具体电路和仿真可以到中国电子DIY之家论坛搜索/*********************************** DS1302简单时间显示** 数码管显示************************************/#include#define uchar unsigned char#define uint unsigned int#define W P2 //位选#define D P0 //段选sbit IO=P1^0; //数据口sbit SCLK=P1^1; //控制数据时钟sbit RST=P1^2; //使能端、复位端/************按键引脚定义***********/sbit s1=P1^5; //按键加sbit s2=P1^6; //按键减sbit s3=P1^7; //按键选择char knum=0,snum,fnum;/***********写时分秒地址************/#define write_shi 0x84#define write_fen 0x82#define write_miao 0x80/***********读时分秒地址************/#define read_shi 0x85#define read_fen 0x83#define read_miao 0x81char shi,fen,miao; //读出数据存储变量uchard[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xd8,0x80,0x90}; //不带小数点uchardd[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //带小数点void delay(uint z) //延时函数,z的取值为这个函数的延时ms数,如delay(200);大约延时200ms.{ //delay(500);大约延时500ms.uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}uchar read_1302(uchar add) //读函数{uchar i,date;RST=0; //禁止读写数据for(i=0;i<8;i++){RST=1;SCLK=0;IO=add&0x01;add>>=1;SCLK=1;}for(i=0;i<8;i++){if(IO)date=date|0x80;elsedate=date|0x00;SCLK=1;date>>=1;SCLK=0;}RST=0;date=date/16*10+date%16; //进制转换16转10进制IO=0; //数据读完后,IO口必须为0,不然小时一直显示85 return date;}void write_1302(uchar add,uchar dat) //写函数{uchar i;RST=0; //禁止读写数据// SCLK=0;for(i=0;i<8;i++) //写地址{RST=1; //允许读写数据SCLK=0;IO=add&0x01;add>>=1;SCLK=1;}for(i=0;i<8;i++) //写数据{RST=1; //允许读写数据SCLK=0;IO=dat&0x01;dat>>=1;SCLK=1;}RST=0;}void init_1302() //初始化函数设置时间{write_1302(0x8e,0x00); //保护取消,可以进行读写操作write_1302(write_miao,0x56);write_1302(write_fen,0x49);write_1302(write_shi,0x14);write_1302(0x8e,0x80); //保护启动,不能进行读写操作}void display(uchar shi,uchar fen,uchar miao) //显示函数{if(knum==0){snum=30;fnum=30;}if(knum==1){fnum++;snum=30;}if(knum==2){snum++;fnum=30;}if(snum>=30){W=0x01; //位选D=d[shi/10]; //段选delay(5);D=0XFF; //消隐if(miao%2==0) //小数点闪烁{W=0x02;D=dd[shi%10];delay(5);D=0XFF; //消隐}else{W=0x02;D=d[shi%10];delay(5);D=0XFF; //消?}if(snum==60)snum=0;}if(fnum>=30){W=0x04;D=d[fen/10];delay(5);D=0XFF; //消隐W=0x08;D=d[fen%10];delay(5);D=0XFF; //消隐if(fnum==60)fnum=0;}}void read_sf(){shi=read_1302(read_shi);fen=read_1302(read_fen);miao=read_1302(read_miao);display(shi,fen,miao);}void keyscan() //按键扫描函数{if(s3==0) //选择按键按下{delay(10);if(s3==0){while(!s3)display(shi,fen,miao); //加上这句,按键按下就不会闪knum++; if(knum==1) //分闪烁{write_1302(0x8e,0x00); //保护取消write_1302(write_miao,0x80);}if(knum==3) //时钟启动{knum=0;write_1302(write_miao,0x00);write_1302(0x8e,0x80); //保护启动}}}if(knum==1) //分钟调节{if(s1==0) //加{delay(10);if(s1==0){while(!s1)display(shi,fen,miao); //加上这句,按键按下就不会闪fen++; fen=fen/10*16+fen%10; //转为16进制if(fen==0x60)fen=0x00;write_1302(write_fen,fen); //写入1302read_sf(); //读出时间,然后显示}}if(s2==0){delay(10);if(s2==0){while(!s2)display(shi,fen,miao); //加上这句,按键按下就不会闪fen--; fen=fen/10*16+fen%10; //转为16进制if(fen==-1)fen=0x59;write_1302(write_fen,fen);read_sf();}}}if(knum==2){if(s1==0){delay(10);if(s1==0){while(!s1)display(shi,fen,miao); //加上这句,按键按下就不会闪shi++; shi=shi/10*16+shi%10; //转为16进制if(shi==0x24)shi=0x00;write_1302(write_shi,shi);read_sf();}}if(s2==0){delay(10);if(s2==0){while(!s2)display(shi,fen,miao); //加上这句,按键按下就不会闪shi--;shi=shi/10*16+shi%10; //转为16进制if(shi==-1)shi=0x23;write_1302(write_shi,shi);read_sf();}}}}void main(){// init_1302();while(1){read_sf();keyscan();}}。
/************************************************************************/ // huaqinMCU DS1302 实验程序数码管显示时钟设置说明// "8键"为时钟设置、时分切换、保存"0键"为加"4键"为减/************************************************************************/ #include <reg52.h>#define uchar unsigned char#define uint unsigned int//===以下IO定义请根据您硬件的连接修改===sbit T_RST=P3^5;//ds1302-5sbit T_IO=P3^4;//ds1302-6sbit T_CLK=P3^6;//ds1302-7sbit ACC0=ACC^0;sbit ACC7=ACC^7;//累加器A 51单片机原理中有介绍sbit up=P3^1;sbit down=P3^2;sbit set=P3^0;uchar a,b,clock_ss,clock_sg,clock_fs,clock_fg,clock_ms,clock_mg;int hour,mie,sei;uchar clk_time[3]; //秒,分,时寄存器初始值code uchar ledmap[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//数码管段码/******************DS1302:写入操作(上升沿)*********************/void write_byte(uchar da){uchar i;ACC=da;for(i=8;i>0;i--){T_IO=ACC0;T_CLK=0;T_CLK=1;ACC=ACC>>1;}}/******************DS1302:读取操作(下降沿)*****************/uchar read_byte(void){uchar i;for(i=0;i<8;i++){ACC=ACC>>1;T_CLK = 1;T_CLK = 0;ACC7 = T_IO;}return(ACC);}/******************DS1302:写入数据(先送地址,再写数据)***************************/ void write_1302(uchar addr,uchar da){T_RST=0; //停止工作T_CLK=0;T_RST=1; //重新工作write_byte(addr); //写入地址write_byte(da);T_RST=0;T_CLK=1;}/******************DS1302:读取数据(先送地址,再读数据)**************************/ uchar read_1302(uchar addr){uchar temp;T_RST=0; //停止工作T_CLK=0;T_RST=1; //重新工作write_byte(addr); //写入地址temp=read_byte();T_RST=0;T_CLK=1; //停止工作return(temp);}/***********************延时程序=a*1ms**************************************/void delay(uchar a){uchar i;while(a-- !=0){ // led_disp();for(i=0;i<125;i++);}}/***********************显示程序**********************************************//* DS1302秒,分,时寄存器是BCD码形式:用16求商和余进行"高4位"和"低4位"分离*/ /****************************************************************************/void led_disp(){ uchar cant1,cant2;if(b==0){cant1=0;cant2=0;clock_ms=clk_time[0]/ 16; clock_mg=clk_time[0]%16;clock_fs=clk_time[1]/ 16; clock_fg=clk_time[1]%16;mie=clock_fs*10+ clock_fg;clock_ss=clk_time[2]/ 16; clock_sg=clk_time[2]%16;//BCD*to*10hour=clock_ss*10+ clock_sg; //用16求商和余进行"高4位"和"低4位"分离}if(b==1){cant1++;cant2=0;clock_ss=hour/ 10; clock_sg=hour%10;clock_fs=mie/ 10; clock_fg=mie%10;clock_ms=sei/10; clock_mg=sei%10;}if(b==2){ cant1=0;cant2++;clock_ss=hour/ 10; clock_sg=hour%10;clock_fs=mie/ 10; clock_fg=mie%10;clock_ms=sei/10; clock_mg=sei%10;}if(cant1<=3){P2=0;P0=ledmap[clock_ss];delay(1);P0=0X00;P2=1;P0=ledmap[clock_sg];//时个位delay(1);P0=0X00;}if(cant1==5)cant1=0;P2=2;P0=ledmap[10];//显示"-"数组里的0x40delay(1);P0=0X00;if(cant2<=3){P2=3;P0=ledmap[clock_fs];//分十位delay(1);P0=0X00;P2=4;P0=ledmap[clock_fg];//时个位delay(1);P0=0X00;}if(cant2==5)cant2=0;P2=5;P0=ledmap[10];//显示"-"数组里的0x40delay(1);P0=0X00;P2=6;P0=ledmap[clock_ms];//秒十位delay(1);P0=0X00;P2=7;P0=ledmap[clock_mg];delay(1);P0=0X00;}/***********************按键延时程序=a*1ms**************************************/ void delayAJ(uchar a){uchar i;while(a--){for(i=0;i<125;i++);{led_disp();}}}void key(){uchar clock_s1, clock_s2, clock_f1, clock_f2;delayAJ(5);if(set==0){delayAJ(5);//消抖if(set==0){b++;delayAJ(5);}while(!set){delayAJ(5);}}if(b!=0)//时分设定{if(up==0){delayAJ(5);//消抖if(up==0){if(b==1){hour++;if(hour>=24){hour=0;}delayAJ(10);}if(b==2){mie++;if(mie>=60){mie=0;}delayAJ(10);}//以上时钟+设定}}if(down==0){delayAJ(5);//消抖if(down==0){delayAJ(5);if(b==1){hour--;if(hour<0){hour=23;}delayAJ(10);}if(b==2){mie--;if(mie<0){mie=59;}delayAJ(10);}//以上时钟-设定}}//********************以下是转BCD码的程序DS1302认BCD码clock_s1=hour/10;clock_s2=hour%10;clock_s1=clock_s1&0xff;clock_s2=clock_s2&0xff;clock_s1<<=4;clock_s1=clock_s1|clock_s2;// 10to16clock_f1=mie/10;clock_f2=mie%10;clock_f1=clock_f1&0xff; //全1出1 与运算clock_f2=clock_f2&0xff;clock_f1<<=4;clock_f1=clock_f1|clock_f2;// 10to16//*******************************************转BCD码的程序DS1302认BCD码}if(b==3){b=0;write_1302(0x8e,0x00); //WP=0 写操作write_1302(0x80,0x01);//0x80是写秒数据此处写进"01"秒write_1302(0x82,clock_f1);//0x82是写分数据write_1302(0x84,clock_s1);//0x84是写时数据write_1302(0x8e,0x80); //WP=1 写保护delay(255);}}/************************主程序**********************************************/ void main(void){uchar temp=0x80;uchar i;b=0;P3=0xff;while(1){temp=0x81;//读的初始地址for(i=0;i<3;i++)//分别把秒分时数据读出分3次读好一次地址加2" temp+=2;"{clk_time[i]=read_1302(temp);temp+=2;}key();//键盘扫描}}。