Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2012992
  • 博文数量: 356
  • 博客积分: 8284
  • 博客等级: 中将
  • 技术积分: 4580
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-15 20:25
个人简介

天行健,君子以自强不息

文章分类

全部博文(356)

文章存档

2018年(1)

2016年(4)

2015年(13)

2014年(14)

2013年(2)

2012年(25)

2011年(43)

2010年(65)

2009年(189)

分类: LINUX

2009-12-05 23:30:11

 

 

#include

#include

 

sbit SCK=P3^6;            

sbit SDA=P3^4;           

sbit RST = P3^5;   // DS1302复位

 

bit ReadRTC_Flag;

 

unsigned char l_tmpdate[7]={0,0,12,15,5,3,8};//秒分时日月周年08-05-15 12:00:00

unsigned 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  '-' '熄灭‘表

code unsigned char table1[]={0,1,2,3,4,5,6,7};

                     //显示位码表

 

                                                                                   

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 RTC

void Set_RTC(void); //set RTC

 

void InitTIMER0(void);//inital timer0

 

void main(void)   

{

    InitTIMER0();

      Set_RTC();

       while(1){

        if(ReadRTC_Flag)        //通过判断ReadRTC_Flag标志位的反复置位,定期向ds1302读取数据

        {

           ReadRTC_Flag=0;         //置位标志清零

              Read_RTC();

              switch (l_tmpdate[0]/5)   //设计每个5 交替显示 年月日 时分秒,注意,此种显示方法设计得十分巧妙

              {

              case 0:

              case 2:

              case 4:

              case 6:

              case 8:

              case 10:

                     l_tmpdisplay[0]=l_tmpdate[2]/16;                //数据的转换,因我们采用数码管0~9的显示,将数据分开

                     l_tmpdisplay[1]=l_tmpdate[2]&0x0f;                  //即将l_tmpdate的高四位和低四位以十六进制数的形式分开,以下亦是如此

                     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;   

                     break;

              case 1:

              case 3:

              case 5:

              case 7:

              case 9:

              case 11:

                     l_tmpdisplay[0]=l_tmpdate[6]/16;

                     l_tmpdisplay[1]=l_tmpdate[6]&0x0f;

                     l_tmpdisplay[2]=10;

                     l_tmpdisplay[3]=l_tmpdate[4]/16;

                     l_tmpdisplay[4]=l_tmpdate[4]&0x0f;

                     l_tmpdisplay[5]=10;

                     l_tmpdisplay[6]=l_tmpdate[3]/16;

                     l_tmpdisplay[7]=l_tmpdate[3]&0x0f;

                     break;

              default:

                     break;

              }

      

        }

       }

}

 

void InitTIMER0(void)            //初始化定时器中断的设置

{

 TMOD|=0x01;//定时器设置 16

 TH0=0xef;//初始化值

 TL0=0xf0;

 ET0=1;

 TR0=1;

 EA=1;

}

 

 

 

void Write_Ds1302_Byte(unsigned  char temp) //ds1302中写入一个字节的数据,注意此处没有制定要写入的地址,此种方法不是很好

{

 unsigned char i;

 for (i=0;i<8;i++)     //循环8 写入数据

  {

   SCK=0;

     SDA=temp&0x01;          //每次传输低字节,通过temp0x01相与得到temp的最后一位

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

     SCK=1;

   }

}                 //注意,向ds1302写入数据时,是从最低位开始写起

 

/****************************************************************************/

//函数功能:向ds1302的指定地址里面写入一个字节的数据

//调用函数:Write_Ds1302_Byte()

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的指定地址里面读出一个字节的数据

//调用函数:Write_Ds1302_Byte()

unsigned char Read_Ds1302 ( unsigned char address )

{

      unsigned char i,temp=0x00;

      RST=0;

       _nop_();

      SCK=0;

       _nop_();

      RST=1;

       _nop_();

      Write_Ds1302_Byte(address);

      

      for (i=0;i<8;i++)           //循环8 读取数据

      {           

             if(SDA)

             temp|=0x80;                 //每次传输低字节

              SCK=0;

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

             SCK=1;

       }

      RST=0;

       _nop_();         //以下为DS1302复位的稳定时间

      RST=0;

       SCK=0;

       _nop_();

       SCK=1;

       _nop_();

       SDA=0;

       _nop_();

       SDA=1;

       _nop_();

       return (temp);               //返回

}

/****************************************************************************/

void Read_RTC(void)           //读取 日历

{

 unsigned char i,*p;

 p=read_rtc_address;    //地址传递,read_rtc_address在前面被定义为一个全局变量的

//数组,此处p为他的首地址

 for(i=0;i<7;i++)           //7次读取 秒分时日月周年

 {

  l_tmpdate[i]=Read_Ds1302(*p);//注意,此处的Read_RTC函数没有设定返回值,因为 l_tmpdate被设定为全局变量

  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;

       } //上面的for语句里面的几段话的意思如下:

         //因为l_tmpdate为十六进制数,要转换成是进制的bcd码,将l_tmpdate的除以10再乘以16再加上l_tmpdate16取余的结果

      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]];            //查表法得到要显示数字的数码段 ,显示断码

       P2=table1[i];                               //数码管位码

       i++;

       if(i==8)

         {

          i=0;

          num++;

          if(10==num)       //隔段时间读取1302的数据。时间间隔可以调整

            {

               ReadRTC_Flag=1; //使用标志位判断

               num=0;

               }

         

          }

 }

 

 

阅读(2042) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~