DS1302

写不明白就不要写

Attention:
①上升沿前写,下降沿后读。
②“读”、“写”指令,操作必复位。
③“读”指令,读完必加 IO = 0。
④操作1302,必先去写保护。


电路接口

DS1302_第1张图片

简介: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口发送数据,主机接收。
    DS1302_第2张图片

寄存器结构

DS1302_第3张图片

  • 0号寄存器: 秒(BCD码,高四位为十位,低四位为个位)
  • 1号寄存器: 分(BCD码,高四位为十位,低四位为个位)
  • 2号寄存器: 时 (MSB最高位为24/12,低四位)
  • 3号寄存器: 天 (BCD码,高四位为十位,低四位为个位)
  • 4号寄存器: 月 (BCD码,高四位为十位,低四位为个位)
  • 5号寄存器: 周(BSD码,低三位)
  • 6号寄存器: 年 (BCD码,高四位为十位,低四位为个位)
  • 7号寄存器: 控制字(MSB为写保护位,1为写保护)
    DS1302_第4张图片

程序

链路层:收发复位

  • 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];
}

你可能感兴趣的:(蓝桥杯单片机)