📄 ds1302.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 + -