⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds1302.c

📁 1302测试,一个完整的1602和DS1302的AVR学习
💻 C
字号:
#include<iom16v.h>
#include<macros.h>

#define uchar unsigned char 
#define uint  unsigned int

//ds1302引脚配置
#define DS1302_RST 4  //pC4
#define DS1302_SDA 5  //pC5
#define DS1302_SCLK 6 //pC6
//DS1302_RST=1
#define Set_DS1302_RST()  PORTC|=1<<DS1302_RST
//DS1302_RST=0
#define Clr_DS1302_RST()  PORTC&=~(1<<DS1302_RST)
//DS1302_SDA=1
#define Set_DS1302_SDA()  PORTC|=1<<DS1302_SDA
//DS1302_SDA=0
#define Clr_DS1302_SDA()  PORTC&=~(1<<DS1302_SDA)
//DS1302_SCLK=1
#define Set_DS1302_SCLK() PORTC|=1<<DS1302_SCLK
//DS1302_SCLK=0
#define Clr_DS1302_SCLK() PORTC&=~(1<<DS1302_SCLK)
//DS1302的SDA置为输出脚
#define Set_DS1302_DDRSDA() DDRC|=1<<DS1302_SDA
//DS1302的SDA置为输入脚
#define Clr_DS1302_DDRSDA() DDRC&=~(1<<DS1302_SDA)
//DS1302的SDA输入数据1判断
#define DS1302_SDA_bit    (PINC&(1<<DS1302_SDA) 
//DS1302相关寄存器
#define DS1302_SEC_Reg 0x80
#define DS1302_MIN_Reg 0x82
#define DS1302_HR_Reg 0x84
#define DS1302_DATE_Reg 0x86
#define DS1302_MONTH_Reg 0x88
#define DS1302_DAY_Reg 0x8a
#define DS1302_YEAR_Reg 0x8c
#define DS1302_CONTROL_Reg 0x8e
#define DS1302_CHARGER_Reg 0x90
#define DS1302_CLKBURST_Reg 0xbe

/*DS1302写数据*/
void DS1302_Write(uchar addr,uchar data)
  {
    uchar i;
   
    Set_DS1302_DDRSDA();
    Clr_DS1302_RST();
    asm("nop");
    asm("nop");
    Clr_DS1302_SCLK();
    asm("nop");
    asm("nop");
    Set_DS1302_RST();
    asm("nop");
    asm("nop");
     for(i=8;i>0;i--)
       { 
        if(addr&0x01) Set_DS1302_SDA();
        else Clr_DS1302_SDA();
        asm("nop");
        asm("nop");
        Set_DS1302_SCLK(); 
        asm("nop");
        asm("nop");
        Clr_DS1302_SCLK();
        asm("nop");
        asm("nop");
        addr>>=1;
       }
     for(i=8;i>0;i--)
       { 
        if(data&0x01) Set_DS1302_SDA();
        else Clr_DS1302_SDA();
        asm("nop");
        asm("nop");
        Set_DS1302_SCLK();
        asm("nop");
        asm("nop");
        Clr_DS1302_SCLK();
        asm("nop");
        asm("nop");
        data>>=1;
       }
    Clr_DS1302_RST();
    asm("nop");
    asm("nop");
    Clr_DS1302_DDRSDA();
  }

/*DS1302读数据*/
uchar DS1302_Read(uchar addr)
  {
    uchar data=0,i;
	
    addr =addr|=0x01;//置读标志
    Set_DS1302_DDRSDA();
    Clr_DS1302_RST();
    asm("nop");
    asm("nop");
    Clr_DS1302_SCLK();
    asm("nop");
    asm("nop");
    Set_DS1302_RST();
    asm("nop");
    asm("nop");
    for(i=8;i>0;i--)
      {
       if(addr&0x01) Set_DS1302_SDA();
       else Clr_DS1302_SDA();
       asm("nop");
       asm("nop");
       Set_DS1302_SCLK(); 
       asm("nop");
       asm("nop"); 
       Clr_DS1302_SCLK();
       asm("nop");
       asm("nop");
       addr>>=1;
      }
    Clr_DS1302_DDRSDA();
    for(i=8;i>0;i--)
      { 
       data>>=1;
       if(DS1302_SDA_bit)==(1<<DS1302_SDA)) data|=0x80;
       Set_DS1302_SCLK();
       asm("nop");
       asm("nop");
       Clr_DS1302_SCLK();
       asm("nop");
       asm("nop"); 
      }
    Clr_DS1302_RST();
    asm("nop");
    asm("nop");
    return(data);
  }

/*DS1302校验数据*/
uchar Check_DS1302(void)
  {
   DS1302_Write(DS1302_CONTROL_Reg,0x80);
   if(DS1302_Read(DS1302_CONTROL_Reg)==0x80) return 1;
   return 0;
  }

  uchar BcdToBin(uchar val) 
  { 
  val = (val >> 4) *10+(val &0x0f); //将BCD码转换为10进制数 
  return val; ///返回10进制数 
  } 

uchar BinToBcd(uchar val) 
  { 
  return ((val / 10) *16+val % 10); 
  } 

/*------------------------------------------------------------ 
                         公元任一年的星期算法 
--------------------------------------------------------------
蔡勒(Zeller)公式。
即w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1公式中的符号含义如下,
w:星期;c:世纪-1;y:年(两位数);m:月(m大于等于3,小
于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14
月来计算,比如2003年1月1日要看作2002年的13月1日来计算);d:
日;[ ]代表取整,即只要整数部分。(C是世纪数减一,y是年份后
两位,M是月份,d是日数。1月和2月要按上一年的13月和 14月来算,
这时C和y均按上一年取值。)算出来的W除以7,余数是几就是星期几。
如果余数是0,则为星期日。
以2049年10月1日(100周年国庆)为例,用蔡勒(Zeller)公式进行计
算,过程如下:蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/
10]+d-1 =49+[49/4]+[20/4]-2×20+[26×(10+1)/10]+1-1 =49+[12.25]
+5-40+[28.6] =49+12+5-40+28 =54(除以7余5)即2049年10月1日是星期5
-------------------------------------------------------------*/
//在使用前要给出>>'当前世纪','年份'(两位数),'月份','日'
//作者: 潘钟声   2008年4月20日星期日 14:35:00
unsigned char WeekDay_cal(char c,char y, char m, char d) 
 {
  char week,tempy; 
  c=c-1;
  y=(y >> 4) *10+(y &0x0f);//将BCD码转换为10进制数 
  m=(m >> 4) *10+(m &0x0f);//将BCD码转换为10进制数 
  d=(d >> 4) *10+(d &0x0f);//将BCD码转换为10进制数 
  tempy=y;
  if(m==1){m=13;y=y-1;}//月份为1月,转为去年的年份的13月
  if(m==2){m=14;y=y-1;}//月份为2月,转为去年的年份的14月
  //如是00年的1月或2月则要转到99年算,世纪也要退一个世纪
  if(((tempy==0)&&(m==13))||((tempy==0)&&(m==14))){c=c-1;y=99;}
  week=(y+y/4+c/4-2*c+(26*(m+1))/10+d-1)%7;//计算星期,0为星期日
  return (week);///返回星期 
 }
/*************************************************************/
   
/*DS1302初始化*/
void DS1302_Init(void)
  {
    DS1302_Write(DS1302_CONTROL_Reg,0x00);//关闭写保护 
    DS1302_Write(DS1302_SEC_Reg,0x80);//暂停 
    DS1302_Write(DS1302_CHARGER_Reg,0xa9);//涓流充电
    DS1302_Write(DS1302_YEAR_Reg,0x08);   //年
    DS1302_Write(DS1302_MONTH_Reg,0x04);  //月
    DS1302_Write(DS1302_DATE_Reg,0x26);  //日
    DS1302_Write(DS1302_DAY_Reg,0x00); //周
    DS1302_Write(DS1302_HR_Reg,0x15); //时
    DS1302_Write(DS1302_MIN_Reg,0x20); //分
    DS1302_Write(DS1302_SEC_Reg,0x00); //秒
    DS1302_Write(DS1302_CONTROL_Reg,0x80);//打开写保护
  }

/*DS1302读时间*/
void ReadTime(void)
  {//DS1302变量,把个位和十位分开
   uint T,Y,M,D,YH,YL,MMH,MML,DH,DL,WK,HH,HL,MH,ML,SH,SL;
   
   Y=DS1302_Read(DS1302_YEAR_Reg);//年
   YL=Y&0x0f;
   YH=Y>>4;
   M=DS1302_Read(DS1302_MONTH_Reg);//月
   MML=M&0x0f;
   MMH=(M>>4)&0x01;
   D=DS1302_Read(DS1302_DATE_Reg);//日
   DL=D&0x0f;
   DH=(D>>4)&0x03;
   //WK=DS1302_Read(DS1302_DAY_Reg);//周
   //WK=WK&0x07;
   WK=WeekDay_cal(21,Y,M,D);//星期运算,21为当前世纪
   T=DS1302_Read(DS1302_HR_Reg);//时
   HL=T&0x0f;
   HH=(T>>4)&0x03;
   T=DS1302_Read(DS1302_MIN_Reg);//分
   ML=T&0x0f;
   MH=(T>>4)&0x07;
   T=DS1302_Read(DS1302_SEC_Reg);//秒
   SL=T&0x0f;
   SH=(T>>4)&0x07;
   
   ds1302F(YH,YL,MMH,MML,DH,DL,WK,HH,HL,MH,ML,SH,SL);
  
  } 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -