1、DS1320操作顺序:先给芯片一个命令,读或者写。然后再进行操作,读命令就从芯片读取数据;写命令就把数据写到芯片。
2、注意事项:最好使用无符号字符型,因为涉及到数据移位操作,带符号数容易出问题!!
#include<reg52.h>
#include<intrins.h>
sbit IO = P3^4; //数据输入和输出引脚
sbit CE = P3^5; //复位引脚,高电平启用数据传输
sbit Clock = P3^6; //时钟输入引脚
/*38译码器的输入端定义*/
sbit AA = P2^0;
sbit BB = P2^1;
sbit CC = P2^2;
/*DS1302中的数据以BCD码存储,每4位2进制表示一位十进制
下面Time数组中的第一个0x00就表示0十秒0秒;0x15表示24小时
形式的下午15点*/
char Time[] = {0x25,0x31,0x11,0x03,0x05,0x01,0x22};//初始化时间秒,分,时,日,月,周,年
char Read_Cmd[7] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
char Write_Cmd[7] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
/*数码管0-F段码值*/
unsigned char Seg_Code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
/*向DS1320发送命令,告知对其进行的操作是读还是写,和读写的是时分秒等的哪一位*/
void Ds1302_Cmd(char Cmd)
{
char n;
CE = 0;_nop_();
Clock = 0;_nop_();
CE = 1;_nop_();
for(n = 0;n <= 7;n ++)//发送八位命令代码,已保存在上面的数组中
{
IO = Cmd & 0x01;
Cmd = Cmd >> 1;
Clock = 1; //上升沿读取数据
_nop_();
Clock = 0;
_nop_();
}
}
/*向DS1320中写入8位数据*/
void WriteDatToDs1320(char Dat)
{
char n;
for(n = 0;n <= 7;n ++)
{
IO = Dat & 0x01;
Dat = Dat >> 1;
Clock = 1; //上升沿读取数据
_nop_();
Clock = 0; //时钟重置为0
_nop_();
}
CE = 0; //传输数据结束
_nop_();
}
/*从DS1320接收8位数据*/
char ReadDatFromDs1320() //数据是从最低位开始接收,因此要进行下列移位操作
{
char n;
unsigned char Data_Temp,Data; /*这里注意使用无符号字符类型,否则移位会发生错误!!!
具体原因可能是C51的编译器关于移位是逻辑右移还是算术右移的问题,我也搞不懂*/
for(n = 0;n <= 7;n ++)
{
Data_Temp = IO;
Data = ((Data >> 1) | (Data_Temp << 7));
/*Data右移1位,空出最高位(为0);Data_Temp为接收到的一
位数据将其左移7位,这样就与Data最高位对齐,在进行“或”运
算,将数据传给Data,再进行下一次循环,这样先接收的数据就
逐渐移到了低位,最后接收的数据就到了高位。*/
Clock= 1;_nop_();
Clock= 0; //下降沿放置数据.
_nop_();
}
/*DS1320复位稳定时间*/
CE = 0; //关闭数据传输
_nop_();
Clock = 1;
_nop_();
IO = 0;
_nop_();
IO = 1;
_nop_();
return Data;
}
/*从DS1320中读取全部时间,要进行7次读数据操作,每次读取一个参数*/
void ReadTimeFromDs1320()
{
unsigned char n;
for(n = 0;n <= 6;n ++)
{
Ds1302_Cmd(Read_Cmd[n]); //先发送读的命令
Time[n] = ReadDatFromDs1320();//读取8位数据
}
}
/*初始化DS1320中的时间为Time数组中的时间,将预先设定的全部时间
写到DS1320中,由于有7个参数,因此要循环7次*/
void Ds1320_Init()
{
int n;
Ds1302_Cmd(0x8e);
WriteDatToDs1320(0x00);//这两句话是关闭写保护
/*像DS1320中写入:秒,分,时,日,月,周,年七组8位数据*/
for(n = 0;n <= 6;n ++)
{
Ds1302_Cmd(Write_Cmd[n]);WriteDatToDs1320(Time[n]);
/*例如:当n = 1时,先发送写秒的命令,再发送秒的数据
命令和数据都提前保存在了数组中,具体命令代码查阅数
据手册,如下图*/
}
Ds1302_Cmd(0x8e);WriteDatToDs1320(0x80);//打开写保护.
}
//扫描数码管显示程序
void Display(int Hour1,int Hour2,int Min1,int Min2,int Sec1,int Sec2)
{
int i,j;
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):AA=0;BB=0;CC=0;P0 = Seg_Code[Hour1];break;//显示第0位
case(1):AA=1;BB=0;CC=0;P0 = Seg_Code[Hour2];break;//显示第1位
case(2):AA=0;BB=1;CC=0;P0 = 0X40;break;//显示第2位
case(3):AA=1;BB=1;CC=0;P0 = Seg_Code[Min1];break;//显示第3位
case(4):AA=0;BB=0;CC=1;P0 = Seg_Code[Min2];break;//显示第4位
case(5):AA=1;BB=0;CC=1;P0 = 0X40;break;//显示第5位
case(6):AA=0;BB=1;CC=1;P0 = Seg_Code[Sec1];break;//显示第6位
case(7):AA=1;BB=1;CC=1;P0 = Seg_Code[Sec2];break;//显示第7位
}
j = 50;
while(j--);
P0 = 0X00;
}
}
/*主程序*/
void main()
{
int Hour1,Hour2,Min1,Min2,Sec1,Sec2;
Ds1320_Init();
while(1)
{
ReadTimeFromDs1320();//读取时间并存储到Time数组中
Hour1 = Time[2]/16; //小时的十位,Time[2]对16取余,因为是16进制
Hour2 = Time[2]&0x0f;//保留低四位的小时个位数
Min1 = Time[1]/16;
Min2 = Time[1]&0x0f;
Sec1 = Time[0]/16;
Sec2 = Time[0]&0x0f;
Display(Hour1,Hour2,Min1,Min2,Sec1,Sec2);
}
}