我们今天来认识新的元器件————时钟芯片。
- 首先,还是要看原理图的:
DS1302芯片我们只用三个引脚,分别是:SCLK(串行时钟),I/O(数据输入/输出引脚),**RST(复位脚)**这三个接口。功能如下:SCLK:控制数据的输入与输出;I/O:三线接口时的双向数据线;CE(也就是RST)(这个引脚很重要):输入信号。需要特别注意的是:在读写数据期间,必须为高。如果CE输入为低电平,则所有数据传输终止。
在这之后,我们需要阅读DS1302的说明书,才能写程序。
第一点,初始化。在初始化之前,我们需要理解写保护位这个概念。
写保护位:
控制寄存器的位7是写保护位,前7位(0位至6位)被强制为0且读取时总是读0.在任何对时钟或RAM的写操作以前,位7必须为0.当为高时,写保护位禁止任何寄存器的写操作。初始加电状态未定义。因此,在试图写器件之前应该清除WP位。
再来看时序图:
现在,我开始解读这个图,而我们写程序也在一定程度上依靠这个图。刚才所说的写保护位就是WP,这张表得先从倒数第二行看起,倒数第一行基本没有什么用。再往上7位依次存储的是:年,星期,月,天,时,分,秒。我们需要注意的是:最左边读和写这两行有点特别,以读为例:是从80到8c这7位。还需注意的是:存储数据时,需要区分高8位和低8位的,原因在于有时是两位数,以防乱码。
**在上电时,CE必须为0.同样的,SCLK必须为0.直到CE变为1.**下面贴出程序:
void dsinit()//1 初始化
{
uchar i;
uchar add=0x80;//再次定义的add是这7个地方是从80开始直到8c,所以初始值为80
write(0x8e,0x00);//对WP进行初始化,先是写(0x8e),而后是对高8位的BIT 7赋值,其他位是0
//对8Eh 写完后,需要往上从8ch至80h总共是7个地方进行逐一赋值
for(i=0;i<7;i++)
{
write(add,ds[i]);
add=add+2;//这7个值是以2为间隔的
}
write(0x8e,0x80);//1000 0000写完后将其关闭WP
}
- 其次,我们要写写的函数,此时需要依照时序图写:
这时,我们首先需要做的是拉低CE和SCLK 的电平。然后将CE拉高,进行写数据和写地址。最终将CE拉低。此外,我们还要写一个读字节的子函数转换8位二进制数。程序如下:
void writebyte(uchar dat)//3 子函数
{
uchar i;
for(i=0;i<8;i++)//将8位二进制的数转化为十六进制
{
SCLK=0;
IO=dat&0x01;//分离逐一写
SCLK=1;
dat>>=1;
}
}
void write(uchar add,uchar dat)//2 写东西
{
uchar num;
CE=0;//给一个低电平,拉低
SCLK=0;//同上
//I/O没有必要操作
CE=1;//给一个高电平,拉高,接受数据
writebyte(add);//写地址
//因为是十进制的数,需要将高8位和低8位分开,才不会导致乱码
num=(dat/10<<4)|(dat%10);// 55
//假设55/10=5,后向左移4位,就到了高8位 ,就到了十位,剩下的个位就自然到了低8位
writebyte(num);//写数据
CE=0;
}
- 最后,就是写读的函数。
此时,需要注意要分离出高8位和低8位的值。还有就是I/O 口的赋值情况。程序如下:
void readtime()//5 读的函数
{
uchar i;
uchar add=0x81;//读时间是从81开始的
write(0x8e,0x00);
for(i=0;i<7;i++)
{
shijian[i]=read(add);
add=add+2;
}
write(0x8e,0x80);
}
uchar read(uchar add)//4 单字节读的子函数
{
uchar i,temp;
uchar dat1,dat2;//转换高8位和低8位的两个参数
//初始化
CE=0;
SCLK=0;
CE=1;
writebyte(add);
//开始读字节
for(i=0;i<8;i++)
{
SCLK=0;
temp>>=1;
if(IO)//IO是否等于1
{
temp|=0x80;
}
SCLK=1;
}
IO=0;//IO必须归0,要不然会影响下一次的写
dat1=temp/16;//0XFF 1111 1111目的是将高8位和低8位分开此为高4位
dat2=temp%16;//此为低四位
temp=dat1*10+dat2;//之后再组合在一起
return temp;
}
总共这么5步,就实现了时钟的功能。