DS1302
一.引脚分装
1.DIP直插
2.SO贴片


其中,CE为高电平的时候下面的命令(io和SCLK)才有用。时间存储在实时时钟里,在左边被访问和读写
二.内部寄存器

WP是读写保护
三.考虑的问题
在哪(xx寄存器) 写入 什么
在哪(xx寄存器) 读出 什么(1302芯片返回的,单片机需要读到)

第六位:给1——RAM,给0——CK
6~1完成“在哪”的任务
第零位:完成“读/写”的任务,给1——读,给0——写
在二的表中已经把“读/写”的命令列出来了
1.时序定义

上升沿(io口的电平被)写入(/向时钟芯片写入数据),下降沿(DS1302把他的数据)输出(时钟芯片向单片机写入数据),所以,只有READ中的D0~D7是芯片写入的
写入时,先写入数据再进行上升沿。
2.每个按键的功能
- K1选择模式 MODE=1👉设置时间 MODE=0👉显示流动的时间
- K2选择要更改的时间值(年月日时分秒)
- K3更改某个时间值,+
- K4更改某个时间值,-
四.代码
DS1302.C
1.
void DS1302_WriteByte(unsigned char Command,Data)//写入
{
unsigned char i;
DS1302_CE=1;
for(i=0;i<8;i++)
{
DS1302_IO=Command&(0x01<<i);//1~7位直接清零,只留第0位
DS1302_SCLK=1;
DS1302_SCLK=0;
}
对于每一位,先写入操作指令再给上升沿
2.
unsigned char DS1302_ReadByte(unsigned char Command)
{
unsigned char i,Data=0x00;
Command|=0x01; //将指令转换为读指令
DS1302_CE=1;
for(i=0;i<8;i++)//读出-指令
{
DS1302_IO=Command&(0x01<<i);
DS1302_SCLK=0;
DS1302_SCLK=1;
}
for(i=0;i<8;i++)//读出-数据
{
DS1302_SCLK=1;//看时序图,先少一个高电平
DS1302_SCLK=0;//最后是低电平
if(DS1302_IO){Data|=(0x01<<i);}
}
DS1302_CE=0;
DS1302_IO=0; //读取后将IO设置为0,否则读出的数据会出错
return Data;
}
关于为什么要return DataX,👇我的理解
- 首先在DS1302_WriteByte中写入数据,是多少秒(0~15),就输入0x xx,然后16进制转2进制
- 在DS1302_ReadByte中读取数据,对每一位进行判断
- e.g. 写入时写入了0x03—16转2—>0000 0100,然后在read函数里对每一位进行判断,执行完读命令字后,数据传输到IO口上,是1的,Data就置1,否则置0,所以Data就是个接收数据的中转站罢了。
- 然后return之后,LCD那里的定义是unsigned int Number在传参时,已经自动把2进制转换为10进制了,所以显示出来的数据就是10进制的。
3.自动清零
e.g.希望让a超过5之后清零,从0开始再递增
if(a>5){a=0;}
<==>
a=%6;//a=6%6=0
4.
if(DS1302_Time[1]==1||DS1302_Time[1]==3||DS1302_Time[1]==5||DS1302_Time[1]==7||DS1302_Time[1]==8||DS1302_Time[1]==10||DS1302_Time[1]==12)
{
if(DS1302_Time[2]<1){DS1302_Time[2]=31;}
if(DS1302_Time[2]>31){DS1302_Time[2]=1;} //12-31调回11-xx时会显示11-31,所以需要加上这句话
}
关于为什么要在K4-这里复制一部分K3+的代码
- 从12-31调回11月份时,会显示为11-31,所以要加上那部分代码
5.
某个时间值被选中后跳动
if(TimeSetSelect==0&&TimeSetFlashFlag==1){LCD_ShowString(1,1," ");}
else{LCD_ShowNum(1,1,DS1302_Time[0],2);}
定时器每隔500ms对TimeSetFlashFlag置1或0,当TSFF为1且时间值选中的是0—时 时,在原本显示时的时间那一块地方显示空格;如果不符合if的条件,则显示时间,所以TSFF在0和1跳动时,决定了频闪的显示。