写不明白就不要写
Attention:
①上升沿前写,下降沿后读。
②“读”、“写”指令,操作必复位。
③“读”指令,读完必加 IO = 0。
④操作1302,必先去写保护。
电路接口
简介:DS1302是
BCD码
作为编码方式的,而且是压缩BCD码
,8位表示0-99整数(Year = 99),7位表示0-79整数(Sec、Min = 60),6位表示0-49整数(Hour = 24、Date = 31),5位表示0-19整数(Month = 12),4位表示0-9整数(WeekDay = 7)。
时序逻辑
- 来句废话:DS1302是变种SPI,通过SCLK和I/O相互配合,发送和接收信息。SCLK在上升沿前,主机通过I/O口发送数据,DS1302在上升沿是接收;SCLK在下降沿后,DS1302通过I/O口发送数据,主机接收。
寄存器结构
- 0号寄存器: 秒(BCD码,高四位为十位,低四位为个位)
- 1号寄存器: 分(BCD码,高四位为十位,低四位为个位)
- 2号寄存器: 时 (MSB最高位为24/12,低四位)
- 3号寄存器: 天 (BCD码,高四位为十位,低四位为个位)
- 4号寄存器: 月 (BCD码,高四位为十位,低四位为个位)
- 5号寄存器: 周(BSD码,低三位)
- 6号寄存器: 年 (BCD码,高四位为十位,低四位为个位)
- 7号寄存器: 控制字(MSB为写保护位,1为写保护)
程序
链路层:收发复位
- DS1302的
时序口诀
为:上升沿前写,下降沿后读
发:上升沿从机接收数据,所以上升沿前
主机要发
送数据,保持到上升沿后;
收:下降沿从机发送数据,所以下降沿后
主机要读
数据,直到下一下降沿前。 - 每次读写都由:写寄存器地址 + 若干读数据/写数据 组成,每次
读写都要重置
DS1302时序,即SCLK = 0
//DS1302上升沿前发数据
void Transmit_Byte(u8 dat)
{
u8 mask;
for(mask = 0x01;mask != 0;mask <<= 1)
{
if(dat & mask)
DS1302_IO = 1;
else
DS1302_IO = 0; // Transmit bit
DS1302_SCLK = 0;
DS1302_SCLK = 1; // raising edge
}
}
//DS1302下降沿后接数据
u8 Receive_Byte()
{
u8 mask, dat=0;
for(mask = 0x01;mask != 0;mask <<= 1)
{
DS1302_SCLK = 1;
DS1302_SCLK = 0; // falling edge
if(DS1302_IO)
dat |= mask; // Receive bit
}
return dat;
}
//中层操作需要复位
void Reset_CE()
{
DS1302_CE = 0;
DS1302_SCLK = 0;
}
网络层:单发单收 + 快发快收
Read
读操作,需要将IO口主动拉低,即DS1302_IO = 0
。或加上10K上拉电阻
。- 寄存器(1-7)作为参数,左移1位,或上0x80/0x81,即可构成地址。
奇读偶写
写(addr<<1)|0x80
读(addr<<1)|0x81
void DS1302_SingleWrite(u8 addr ,u8 dat)
{
Reset_CE();
Transmit_Byte((addr<<1)|0x80);
Transmit_Byte(dat);
}
u8 DS1302_SingleRead(u8 addr)
{
u8 dat=0;
Reset_CE();
Transmit_Byte((addr<<1)|0x81);
dat = Receive_Byte();
DS1302_IO = 0; // pay attention for it
return dat;
}
void DS1302_BurstWrite(u8 *dat)
{
u8 i;
Reset_CE();
Transmit_Byte(0xBE);
for(i=0;i<8;i++)
{
Transmit_Byte(*dat++);
}
}
void DS1302_BurstRead(u8 *dat)
{
u8 i;
Reset_CE();
Transmit_Byte(0xBF);
for(i=0;i<8;i++)
{
dat[i] = Receive_Byte();
}
DS1302_IO = 0; // pay attention for it
}
运输层:设定/读出时间(结构体)
- 使用了结构体,也对应了寄存器顺序(倒序),可建结构体数组,方便管理。
//DS1302.h//
extern struct STime
{
u8 Year;
u8 Week;
u8 Month;
u8 Day;
u8 Hour;
u8 Minute;
u8 Second;
};
void Set_RealTime(struct STime *Time)
{
u8 buf[8];
buf[7] = 0;
buf[6] = Time->Year;
buf[5] = Time->Week;
buf[4] = Time->Month;
buf[3] = Time->Day;
buf[2] = Time->Hour;
buf[1] = Time->Minute;
buf[0] = Time->Second;
DS1302_BurstWrite(buf);
}
void Get_RealTime(struct STime *Time)
{
u8 buf[8];
DS1302_BurstRead(buf);
Time->Year = buf[6];
Time->Week = buf[5];
Time->Month = buf[4];
Time->Day = buf[3];
Time->Hour = buf[2];
Time->Minute = buf[1];
Time->Second = buf[0];
}
应用层:初始化 + 显示DP
- DS1302初始化一定要先向7号寄存器的MSB写0,以解除写保护
void Init_DS1302()
{
struct STime InitTime[] = {0x18,0x03,0x12,0x31,0x23,0x59,0x55}; //year week mon date hour min sec
DS1302_SingleWrite(7,0x00);
Set_RealTime(&InitTime);
}
void DP_DS1302_Date(struct STime *Time)
{
SEG_buff[7] = SEG_code[Time->Year >> 4];
SEG_buff[6] = SEG_code[Time->Year & 0x0F];
SEG_buff[5] = SEG_code[10];
SEG_buff[4] = SEG_code[Time->Month >> 4];
SEG_buff[3] = SEG_code[Time->Month & 0x0F];
SEG_buff[2] = SEG_code[10];
SEG_buff[1] = SEG_code[Time->Day >> 4];
SEG_buff[0] = SEG_code[Time->Day & 0x0F];
}
void DP_DS1302_Time(struct STime *Time)
{
SEG_buff[7] = SEG_code[Time->Hour >> 4];
SEG_buff[6] = SEG_code[Time->Hour & 0x0F];
SEG_buff[5] = SEG_code[10];
SEG_buff[4] = SEG_code[Time->Minute >> 4];
SEG_buff[3] = SEG_code[Time->Minute & 0x0F];
SEG_buff[2] = SEG_code[10];
SEG_buff[1] = SEG_code[Time->Second >> 4];
SEG_buff[0] = SEG_code[Time->Second & 0x0F];
}