DS1302模块学习笔记
概述
DS1302自带识别2000-2099年间的平年和闰年,自动分配2月的天数。
工作电压2.0~5.5v包含了3.3v和5v,所以单片机可以给ds1302供电
芯片引脚说明
X1与X2间接一个32.768KHz晶振,32.768KHz晶振容易分频得到1秒用来计时,32768为2^15次方,计数刚好填满16位寄存器。
Vcc1通常用来接备用电池(纽扣电池);Vcc2接单片机(单片机给芯片供电)
通信时序
读一字节数据函数
读一字节数据:先确保RST从低拉到高,SCLK为低电平,再把8位写命令字节数据的最0位(最低位)放到数据线上,再拉高SCLK(芯片接收一位)延时1us,再拉回低,循环8次,把8位写命令字节数据通过移位完整的发出去(芯片接收8位写命令字节数据);在下一个高电平前切换数据脚位输入模式,读取数据线电平,把电平的高低用1/0来表示放在新建存放8位数据变量的最低位,再拉高,在拉低,循环8次完成一次读数据.(最后读出来的是BCD码,需要转成十进制才能直接使用)
u8 ds1302_readbyte(u8 address)
{
uint8_t temp;
Delay_us(3);
CE(1);
ds1302_setdatamode(0);address = address|0x01;//读操作
for(uint8_t i = 0; i < 8; i++)
{
DATA(address &(0x01<<i));
SCL(1);Delay_us(3);
SCL(0);Delay_us(3);
}
ds1302_setdatamode(1);
for(uint8_t i=0;i<8;i++)
{
if(DATA_R) temp|=(0x01<<i); else temp &=~(~(0xfe)<<i);
SCL(1);Delay_us(3);
SCL(0);Delay_us(3);
}
CE(0);Delay_us(3);
temp = (temp>>4)*10+(temp&0x0f);//返回10进制
return temp;
}
写一字节数据函数
写一字节数据:先确保RST从低拉到高,SCLK为低电平,再把8位写命令字节数据的最0位(最低位)放到数据线上,再拉高SCLK(芯片接收一位)延时1us,再拉回低,循环8次,把8位写命令字节数据通过移位完整的发出去(芯片接收8位写命令字节数据);再把8位写数据的最0位(最低位)放到数据线上,再拉高SCLK(芯片接收一位)延时1us,再拉回低,循环8次,把8位写命令字节数据通过移位完整的发出去(芯片接收8位写数据);完成写一字节数据操作.
void ds1302_writebyte(u8 address, u8 data)
{
CE(1); // 启动DS1302总线
ds1302_setdatamode(0); // 设置为输出模式
address &= 0xFE; // 最低位置零,表示写操作
// 写入地址
for(uint8_t i = 0; i < 8; i++)
{
DATA(address &(0x01<<i));
SCL(1); Delay_us(3);
SCL(0);Delay_us(3);
}
// 写入数据
for(uint8_t i = 0; i < 8; i++)
{
DATA(data & (0x01<<i));
SCL(1); Delay_us(3);
SCL(0); Delay_us(3);
}
CE(0);
Delay_us(3);
}
一个函数写完年、月、日、星期、时、分、秒
void ds1302_settime(u8* str)
{
ds1302_writebyte(DS1302_CONTROL_ADDR,0x00);//关闭写保护
ds1302_writebyte(DS1302_SEC_ADDR,0x80); //暂停时钟
ds1302_writebyte(DS1302_YEAR_ADDR,str[0]);
ds1302_writebyte(DS1302_MONTH_ADDR,str[1]);
ds1302_writebyte(DS1302_DAY_ADDR,str[2]);
ds1302_writebyte(DS1302_WEEK_ADDR,str[3]);
ds1302_writebyte(DS1302_HOUR_ADDR,str[4]);
ds1302_writebyte(DS1302_MIN_ADDR,str[5]);
ds1302_writebyte(DS1302_SEC_ADDR,str[6]);
ds1302_writebyte(DS1302_CHARGER_ADDR,0xA5);//打开充电功能 选择2K电阻充电方式
ds1302_writebyte(DS1302_CONTROL_ADDR,0x80);//打开写保护
}
打开了写保护,就数据写不进寄存器。
写入寄存器的数据要从十进制变为对应的BCD码才能正确写入你想写入的数据
读取时间
void ds1302_gettime(u8 *str)
{
str[0]= ds1302_readbyte(DS1302_YEAR_ADDR);
str[1]= ds1302_readbyte(DS1302_MONTH_ADDR);
str[2]= ds1302_readbyte(DS1302_DAY_ADDR);
str[3]= ds1302_readbyte(DS1302_WEEK_ADDR);
str[4]= ds1302_readbyte(DS1302_HOUR_ADDR);
str[5]= ds1302_readbyte(DS1302_MIN_ADDR);
str[6]= ds1302_readbyte(DS1302_SEC_ADDR);
}