求单片机简易数字钟的课程设计 :要求自制一个单片机最小系统,包括串口下载、复位电路,采用内部定时器计

采用外部时钟芯片DS1302,设计一个具有秒、分、日、月、年的数字时钟,采用四位一体数码管显示相关信息,秒、分显示一页,日、月显示一页,年显示一页。QQ 1282031855

下面的程序配合这个电路运行就是对的

这个是完整的程序,电路图如下

#include <reg52.h>

//定义共阳极字型码0123456789-

unsigned char code dispcode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

unsigned char time[]={0,0,0,0};//用来储存分秒

unsigned char date[]={0,0,0,0};//用来储存日时

unsigned char year[]={0,0,0,0};//用来储存年月

typedef struct __SYSTEMTIME__

{

unsigned char Second;

unsigned char Minute;

unsigned char Hour;

unsigned char Week;

unsigned char Day;

unsigned char Month;

unsigned char Year;

unsigned char DateString[9];

unsigned char TimeString[9];

}SYSTEMTIME; //定义的时间类型

SYSTEMTIME time1;

sbit  DS1302_CLK = P1^6;              //实时时钟时钟线引脚 

sbit  DS1302_IO  = P1^7;              //实时时钟数据线引脚 

sbit  DS1302_RST = P1^5;              //实时时钟复位线引脚

sbit  ACC0 = ACC^0;

sbit  ACC7 = ACC^7;

sbit P10=P1^0;

sbit P11=P1^1;

sbit P12=P1^2;

sbit P13=P1^3;

sbit P14=P1^4;

//#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 0x8C

#define DS1302_RAM(X) (0xC0+(X)*2)    //用于计算 DS1302_RAM 地址的宏 

void DS1302InputByte(unsigned char d)  //实时时钟写入一字节(内部函数)

    unsigned char i;

    ACC = d;

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

    {

        DS1302_IO  = ACC0;            //相当于汇编中的 RRC

        DS1302_CLK = 1;

        DS1302_CLK = 0;                 //发一个高跳变到低的脉冲

        ACC = ACC >> 1; 

    } 

}

unsigned char DS1302OutputByte(void)  //实时时钟读取一字节(内部函数)

    unsigned char i;

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

    {

        ACC = ACC >>1;          //相当于汇编中的 RRC 

        ACC7 = 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; 

    DS1302InputByte(ucAddr);        // 地址,命令 

    DS1302InputByte(ucDa);        // 写1Byte数据

    DS1302_CLK = 1;

    DS1302_RST = 0;                  //RST 0->1->0,CLK 0->1

unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据

{

    unsigned char ucData;

    DS1302_RST = 0;

    DS1302_CLK = 0;

    DS1302_RST = 1;                //enable

    DS1302InputByte(ucAddr|0x01);        // 地址,命令 

    ucData = DS1302OutputByte();         // 读1Byte数据

    DS1302_CLK = 1;                      //RST 0->1->0,CLK 0->1

    DS1302_RST = 0;                    

    return(ucData);

}

void DS1302_SetProtect(bit flag)        //是否写保护

{

if(flag)

Write1302(0x8E,0x10); //WP=1,不能写入

else

Write1302(0x8E,0x00);//WP=0,可以写入 

}

void DS1302_SetTime(unsigned char Address, unsigned char Value)        // 设置时间函数

{

DS1302_SetProtect(0);

Write1302(Address, ((Value/10)<<4 | (Value%10))); //高4位为十位,低4位为个位

}

void DS1302_GetTime(SYSTEMTIME *Time)

{

unsigned char ReadValue;

ReadValue = Read1302(DS1302_SECOND);

Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//转换成10进制的秒

ReadValue = Read1302(DS1302_MINUTE);

Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_HOUR);

Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_DAY);

Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_WEEK);

Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_MONTH);

Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);

ReadValue = Read1302(DS1302_YEAR);

Time->Year = ((ReadValue&0xf0)>>4)*10 + (ReadValue&0x0F);

}

void Initial_DS1302(void)

{

unsigned char Second=Read1302(DS1302_SECOND);

if(Second&0x80)    //如果第七为1(表明没有启动), 则启动时钟   

DS1302_SetTime(DS1302_SECOND,0);

}

       

void delay(unsigned char i)     //延时子程序  

{

  unsigned char j;

  while((i--)!=0)

  {

    for(j=625;j>0;j--);

  }

}

/*unsigned char button_time(n,x,y)        //时钟调整子程序

unsigned char n,x,y;

{

    if(P1^7==0)

    {

        delay(50);

        if(P1^7==0)

     {

         n++;

            if(n==x)

         n=0;

            while(P1^7==0);

     }

    }

    if(P1^1==0)

    {

        delay(50);

        if(P1^1==0)

     {

            if(n==0)

         n=y;

         else

            n--;

            while(P1^1==0);

        }

    }

    return n;

}

*/

/*unsigned char button_date(n,x,y)        //日期调整子程序

unsigned char n,x,y;

{

    if(P1^7==0)

    {

        delay(50);

        if(P1^7==0)

     {

         n++;

            if(n==x)

         n=1;

            while(P1^7==0);

     }

    }

    if(P1^1==0)

    {

        delay(50);

        if(P1^1==0)

     {

            if(n==1)

         n=y;

         else

            n--;

            while(P1^1==0);

        }

    }

    return n;

}*/

void display1(minute10,minute1,second10,second1) //显示第一页 分秒 子程序

//unsigned char second10,second1,minute10,minute1;  

{

  P2=0x08;

  P0=dispcode[second1];//显示秒的个位

  delay(1);

  P2=0x04;

  P0=dispcode[second10]; //显示秒的十位

  delay(1);

  P2=0x02;

  P0=dispcode[minute1]; //显示分的个位

  delay(1);

  P2=0x01;

  P0=dispcode[minute10];//显示分的十位

  delay(1);

}

void display2(data10,data1,hour10,hour1) //显示第二页 天时 子程序

//unsigned char data10,data1,hour10,hour1;  

{

  P2=0xf8;

  P0=dispcode[data1];//显示天的个位

  delay(1);

  P2=0xf4;

  P0=dispcode[data10]; //显示天的十位

  delay(1);

  P2=0xf2;

  P0=dispcode[hour1]; //显示时的个位

  delay(1);

  P2=0xf1;

  P0=dispcode[hour10];//显示时的十位

  delay(1);

}

void display3(year10,year1,month10,month1) //显示第三页 年月 子程序

//unsigned char year10,year1,month10,month1;  

{

  P2=0xf2;

  P0=dispcode[month1];//显示月的个位

  delay(1);

  P2=0xf1;

  P0=dispcode[month10]; //显示月的十位

  delay(1);

  P2=0xf8;

  P0=dispcode[year1]; //显示月的个位

  delay(1);

  P2=0xf4;

  P0=dispcode[year10];//显示月的十位

  delay(1);

}

void main()

{  

   unsigned char flag=0;

   Initial_DS1302();     //初始化DS1302这个时钟芯片, 

   P10=0;  //点亮测试灯

   while(1)     

   {

       DS1302_GetTime(&time1);   //读取时间参数 

           

       time[3]=(time1.Second)%10; //把秒的个位数据存入time[3]

       time[2]=(time1.Second)/10; //把秒的十位数据存入time[2]

       time[1]=(time1.Minute)%10; //把分的个位数据存入time[1]

       time[0]=(time1.Minute)/10; //把分的十位数据存入time[0]

       

   date[3]=(time1.Day)%10;

   date[2]=(time1.Day)/10;

   date[1]=(time1.Hour)%10;

   date[0]=(time1.Hour)/10;

   year[3]=(time1.Year)%10;

   year[2]=(time1.Year)/10;

   year[1]=(time1.Month)%10;

       year[0]=(time1.Month)/10;

 //      display1(time[0],time[1],time[2],time[3]);

   if(P11==0)

   {

delay(50);

if(P11==0)

{

flag++;

if(flag>2)//flag: 1 显示第二页 日 时;2 显示第三页 年 月  0:显示第一页 分秒

{

flag=0;

}

}

while(P11==0);

}

   /*if(P1^6==0) //如果按下Time Set键一下,开始显示日期,再按一下进入日期跟时钟的调节模式

   {

    delay(50);

if(P1^6==0)

{

flag++;

if(flag>6)

{

flag=0;

}

}

while(P1^6==0);

}*/

switch(flag)

{

case 0:display1(time[0],time[1],time[2],time[3]); //调用子函数display,把存入数组time的数据给显示出来

   break;

case 1:display2(date[0],date[1],date[2],date[3]); //调用子函数display,把存入数组date的数据给显示出来

   break;

case 2:display3(year[0],year[1],year[2],year[3]);

   break;

/* case 3:time1.Month=button_date(time1.Month,13,12); //调整月

   DS1302_SetTime(0x88,time1.Month);

   display(10,10,date[2],date[3]);

   break;

case 4:time1.Day=button_date(time1.Day,32,31); //调整日

   DS1302_SetTime(0x86,time1.Day);

   display(10,10,date[4],date[5]);

   break;

case 5:time1.Minute=button_time(time1.Minute,60,59);     //调整分

   DS1302_SetTime(0x82,time1.Minute);

   display(time[2],time[3],10,10);

   break;

case 6:time1.Second=button_time(time1.Second,60,59);     //调整秒

       DS1302_SetTime(0x80,time1.Second);

   display(10,10,time[4],time[5]);

   break;*/

}  

}

}

温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-10-09
去5d6d我的领地proteus论坛看看,有很多例程和源码
第2个回答  2011-10-09
可以联系我
相似回答