因项目需要使用IIC串行接口高精度实时时钟SD2405ALPI芯片按照时间要求自动启动单片机,因此研究了一下SD2405ALPI芯片,并且在STM32F407单片机上实现了根据小时和分钟的要求,时间到时(时钟芯片的小时等于预定的小数,时钟芯片的分钟等于预定的分钟)后自动启动单片机。
SD2405ALPI实时时钟芯片共有20个控制寄存器(00H---13H),另外还有12个RAM寄存器(14H---1FH)用于存储参数。
SD2405ALPI实时时钟芯片共有7个寄存器(00H---06H),用于读取芯片的时间(年、月、日、时、分、秒、星期)或都往芯片写时间(年、月、日、时、分、秒、星期)。
1、00H=秒 寄存器
2、01H=分钟 寄存器
3、02H=小时 寄存器
4、03H=星期 寄存器
5、04H=日 寄存器
6、05H=月 寄存器
7、06H=年 寄存器
SD2405ALPI实时时钟芯片支持12小时和24小时二种。如果小时寄存器的最高位为1,代表24小时;如果小时寄存器的最高位为0,代表12小时。
例如:读取的小时为0x03,代表实时时钟被设置为12小时制,当前时间为3点。
例如:读取的小时为0x83,代表实时时钟被设置为24小时制,当前时间为3点。
例如:读取的小时为0x93,代表实时时钟被设置为24小时制,当前时间为13点。
SD2405ALPI实时时钟芯片的星期为七进制数。
0---星期天 1---星期一 2---星期二 3---星期三 4---星期四 5---星期五 6---星期六
1、如果读取的时间为:年=0x19,月=0x09,日=0x28,星期=0x02,小时=0x83,分钟=0x59,秒=0x58
代表 2019年9月28日星期二 3点(24小时制)59分58秒
2、如果读取的时间为:年=0x08,月=0x09,日=0x28,星期=0x03,小时=0xA3,分钟=0x59,秒=0x58
代表 2008年9月28日星期三 23点(24小时制)59分58秒
3、如果读取的时间为:年=0x08,月=0x09,日=0x28,星期=0x03,小时=0x03,分钟=0x59,秒=0x58
代表 2008年9月28日星期三 03点(12小时制)59分58秒
总结:读时钟芯片时间(年、月、日、星期、时、分、秒),必须将读取到的数值由BCD码转换十六进制。
1、要将芯片设置为2018年12月6日星期五 15点12分16秒 ,必须给时钟芯片送如下数值
年=0x18,月=0x12,日=0x06,星期=0x05,小时=0x95,分钟=0x12,秒=0x16
总结:给芯片写的时间(年、月、日、星期、时、分、秒)之前,必须先将要写的数值由十六进制转换成BCD码,然后送给芯片。
07H---0EH为时间报警寄存器。
07H为【秒】报警寄存器(前提是你必须在0EH寄存器中允许秒报警)
08H为【分钟】报警寄存器(前提是你必须在0EH寄存器中允许分钟报警)
09H为【小时】报警寄存器(前提是你必须在0EH寄存器中允许小时报警)
0AH为【星期】报警寄存器(前提是你必须在0EH寄存器中允许星期报警)
0BH为【日】报警寄存器(前提是你必须在0EH寄存器中允许日报警)
0CH为【月】报警寄存器(前提是你必须在0EH寄存器中允许月报警)
0DH为【年】报警寄存器(前提是你必须在0EH寄存器中允许年报警)
0EH为【报警允许】寄存器。
bit0=1,代表允许秒报警,bit0=0,代表禁止秒报警。
bit1=1,代表允许分钟报警,bit1=0,代表禁止分钟报警。
bit2=1,代表允许小时报警,bit2=0,代表禁止小时报警。
bit3=1,代表允许星期报警,bit3=0,代表禁止星期报警。
bit4=1,代表允许日报警,bit4=0,代表禁止日报警。
bit5=1,代表允许月报警,bit5=0,代表禁止月报警。
bit6=1,代表允许年报警,bit6=0,代表禁止年报警。
例子:
假如你想2021年12月31日报警,那么需要在0EH允许年报警、月报警、允许日报警
假如你想2021年12月31日8点报警,那么需要在0EH允许年报警、月报警、允许日报警、允许小时报警。
假如你想2021年12月31日8点30分报警,那么需要在0EH允许年报警、月报警、允许日报警、允许小时报警、允许分钟报警。
假如你想2021年12月31日8点30分20秒报警,那么需要在0EH允许年报警、月报警、允许日报警、允许小时报警、允许分钟报警、允许秒报警。
假如你想星期一报警,那么需要在0EH允许星期报警
0FH---13H为控制寄存器。其中0FH为CTR1控制寄存器,10H为CTR2控制寄存器,11H为CTR3控制寄存器。
1、写允许和写禁止。
当CTR2控制寄存器(10H)的WRTC1位=1,CTR1控制寄存器(0FH)的WRTC3位=1,WRTC2位=1,则允许00H---1FH这些寄存器进行写操作(允许写)。
当CTR2控制寄存器(10H)的WRTC1位=0,CTR1控制寄存器(0FH)的WRTC3位=0,WRTC2位=0,则禁止00H---1FH这些寄存器进行写操作(禁止写或者写后无效)。
警告:写禁止时,00H---0EH寄存器禁止写,11H-1FH寄存器禁止写。
写禁止时,0FH寄存器只有WRTC3位和WRTC2位允许写,0FH寄存器其余位均禁止写。
写禁止时,10H寄存器只有WRTC1位允许写,10H寄存器其余位均禁止写。
总结:写允许时,00H---1FH所有的寄存器都允许写;写禁止时,只有0FH寄存器的WRTC3位和WRTC2位以及10H寄存器的WRTC1位允许写(只有3个位允许写),其余均不允许写。
2、配置中断允许和中断类型
10H寄存器的INTS1位和INTS0位用于选择中断类型。
当配置10H寄存器的INTS1=0,INTS0=1表示启用报警中断输出。
当配置10H寄存器的INTS1=1,INTS0=1表示启用倒计时中断输出。
10H寄存器的INTAE位用于设置时间报警中断禁止/允许。 INTAE=0,禁止时间报警中断,INTAE=1,允许时间报警中断
10H寄存器的INTDE位用于设置倒计时中断禁止/允许。 INTDE=0,禁止倒计时中断,INTDE=1,允许倒计时中断
10H寄存器的INTFE位用于设置频率中断禁止/允许。 INTFE=0,禁止频率中断,INTFE=1,允许频率中断
假如你想启用时间报警中断,10H寄存器设置如下:WRTC1=1,INTS1=0,INTS0=1,INTAE=1
假如你想启用频率中断,10H寄存器设置如下:WRTC1=1,INTS1=1,INTS0=0,INTFE=1
假如你想启用倒计时中断,10H寄存器设置如下:WRTC1=1,INTS1=1,INTS0=1,INTDE=1
10H寄存器的IM位用于设置实时时钟INT引脚的输出模式。
1、当IM位=0,当触发报警时为单事件报警,INT引脚持续输出低电平,只有当你将0FH寄存器的INTAF位清零后,INT引脚才会输出高电平。
2、当IM位=1,当触发报警时为周期性报警,INT引脚持续输出宽度为250的周期性脉冲,只有当你将0FH寄存器的INTAF位清零后,INT引脚才会输出高电平。
SD2405ALP器件IIC写地址为0x64
SD2405ALP器件IIC读地址为0x65
七、源程序
// //写SD2405允许程序 // void WriteTimeOn(void) { I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x10); //设置写地址10H I2CWaitAck(); I2CSendByte(0x80); //置WRTC1=1 I2CWaitAck(); I2CStop(); I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x0F); //设置写地址0FH I2CWaitAck(); I2CSendByte(0x84); //置WRTC2,WRTC3=1 I2CWaitAck(); I2CStop(); } // //写SD2405禁止程序 // void WriteTimeOff(void) { I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x0F); //设置写地址0FH I2CWaitAck(); I2CSendByte(0x0) ; //置WRTC2,WRTC3=0 I2CWaitAck(); I2CStart(); I2CSendByte(0x64); I2CWaitAck(); I2CSendByte(0x10); //设置写地址10H I2CWaitAck(); I2CSendByte(0x0) ; //置WRTC1=0(10H地址) I2CWaitAck(); I2CStop(); } //设置SD2405中断程序(设置报警时间:小时+分钟) void WriteALARM(uint8_t hour , uint8_t minute) { WriteTimeOn(); //写SD2405允许 I2CStart(); I2CSendByte(0x64); //发送SD2400写寄存器命令 I2CWaitAck(); I2CSendByte(0x08); //发送起始地址(0x08=分钟报警寄存器) I2CWaitAck(); I2CSendByte(HEXtoBCD(minute)); //分钟 I2CWaitAck(); I2CStop(); I2CStart(); I2CSendByte(0x64); //发送SD2400写寄存器命令 I2CWaitAck(); I2CSendByte(0x09); //发送起始地址(0x09=小时报警寄存器) I2CWaitAck(); I2CSendByte(HEXtoBCD(hour)); //小时 I2CWaitAck(); I2CStop(); I2CStart(); I2CSendByte(0x64); //发送SD2400写寄存器命令 I2CWaitAck(); I2CSendByte(0x0E); //发送起始地址(0x0E=报警允许寄存器) I2CWaitAck(); I2CSendByte(0x06); //设置报警允许(使能小时、分钟报警) I2CWaitAck(); I2CStop(); I2CStart(); I2CSendByte(0x64); //发送SD2400写寄存器命令 I2CWaitAck(); I2CSendByte(0x10); //发送起始地址(0x10=CTR2控制寄存器) I2CWaitAck(); I2CSendByte(0x92); //设置INT中断选通(INTS1,INTS0),及报警中断总允许位(INTAE) I2CWaitAck(); I2CStop(); WriteTimeOff(); //写SD2405禁止 } //关闭报警中断 void ClrALARM(void) { WriteTimeOn(); //写SD2405允许 I2CStart(); I2CSendByte(0x64); //发送SD2400写寄存器命令 I2CWaitAck(); I2CSendByte(0x10); //发送起始地址 I2CWaitAck(); I2CSendByte(0x90); //清报警中断总允许位(INTAE) I2CWaitAck(); I2CStop(); WriteTimeOff(); //写SD2405禁止 }