DS1302 概述
时序图分析
理解说明:
先说单字节写时序,首先,字节序开始。SCLK = 低电平,RST = 0,接着RST = 1,这里要注意datasheet中的时间,不过对于72Mhz MCU,IO翻转速度也能够满足。开始后,IO就要准备发送的命令寄存器了,先发送低位再发送高位,可以看出,IO总是先准备好数据,接着SCLK上升沿,送入数据。 每次都是先发送命令寄存器,再去发送8bits数据。写入完毕后,SCLK = 0,RST = 0,表示字节序结束。
读时序:
首先,字节序开始。SCLK = 0,RST = 0,RST = 1。在SCLK的时钟信号下,IO发送给DS1302的字节序,低位先发送,高位最后,这里和写字节序同理,IO先准备好数据,然后在SCLK的上升沿时候送入数据。==Warning:==读字节序,是下降沿读取,而且在写字节序的最后一个时钟脉冲的下降沿,已经是读取第一位了,可以看出总共有15个时钟脉冲,这与写时序16个脉冲还有点区别。最后在下降沿下,依次读取8bits数据。
如果有不足之处,请欢迎改正。
读写时序
可以看出,向控制寄存器0x8E地址写入0x00(取消写保护),然后再从0x8E地址读取出来为0x00,表示取消了写保护,此时我们可以向DS1302的可写寄存器进行写入值了。以下是逻辑分析仪抓取的波形。注意:发送、接收数据都是低位先发送,低位先接收。
写保护寄存器读写操作:
读取星期寄存器:0x8B
读取小时寄存(0x85)器数据
寄存器表
重点寄存器描述
时钟暂停
AM-PM/12-24方式
写保护寄存器
比如,想要自己设置时间的时候或者朝RAM中写入东西前,bit7必须为0
慢速充电(Trickle charge)寄存器
这部分建议看手册,这部分可以通过设置寄存器来达到给备用电池充电的目的,电池可以是超级电容,也可以是微型锂电池。
其它部分
晶振和电源
BCD码转十进制计算
8421 BCD码是最基本和最常用的BCD码,它和四位自然二进制码相似,各位的权值为8、4、2、1,故称为有权BCD码。和四位自然二进制码不同的是,它只选用了四位二进制码中前10组代码,即用0000~1001分别代表它所对应的十进制数,余下的六组代码不用。
DS1302使用的是8421 BCD码,十进制范围是0~9。
举例:秒寄存器转为10进制值
第一种方法:
dstime.get_time.second = second/16*10+second%16;
第二种方法:
dstime.get_time.second = ((second & 0x70)>>4)*10 + (second & 0x0F);
简单点说就是,取出一个字节的高4位作为十进制的十位,取出字节中的低4位作为十进制的个位,然后相加组合成秒,同样,其它的日期也是同理。
完整的程序
平台和配置:
芯片:STM32F103C8T6
IDE:STM32Cubemx,CLion
下载:ST-Link V2
逻辑分析仪:某宝30块8通道,软件:Logic2.4.7
注意事项:CLion中printf重定向和Keil中不一样问题!
main.c
#include "ds1302.h"
int main(void)
{
ds1302_init();
while(1)
{
print_times();
HAL_Delay(500);
}
}
ds1302.h
//
// Created by lxp on 2024/3/29.
//
#ifndef CLOCK_DS1302_H
#define CLOCK_DS1302_H
#include "stm32f1xx.h"
#define DS1302_GPIO GPIOB
#define DS1302_DATA GPIO_PIN_12
#define DS1302_CLK GPIO_PIN_13
#define DS1302_RST GPIO_PIN_14
#define DS1302_DATA_IN {
GPIOB->CRH &= 0xfff0ffff; GPIOB->CRH |= (uint32_t)(8<<16); }
#define DS1302_DATA_OUT {
GPIOB->CRH &= 0xfff0ffff; GPIOB->CRH |= (uint32_t)(3<<16); }
#define DS1302_DATA_LOW HAL_GPIO_WritePin(DS1302_GPIO,DS1302_DATA,GPIO_PIN_RESET)
#define DS1302_DATA_HIGH HAL_GPIO_WritePin(DS1302_GPIO,DS1302_DATA,GPIO_PIN_SET)
#define DS1302_CLK_LOW HAL_GPIO_WritePin(DS1302_GPIO,DS1302_CLK,GPIO_PIN_RESET)
#define DS1302_CLK_HIGH HAL_GPIO_WritePin(DS1302_GPIO,DS1302_CLK,GPIO_PIN_SET)
#define DS1302_RST_LOW HAL_GPIO_WritePin(DS1302_GPIO,DS1302_RST,GPIO_PIN_RESET)
#define DS1302_RST_HIGH HAL_GPIO_WritePin(DS1302_GPIO,DS1302_RST,GPIO_PIN_SET)
typedef struct _time{
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t week;
uint8_t hours;
uint8_t minute;
uint8_t second;
}_Time;
typedef struct _time_user{
_Time set_time;
_Time get_time;
}Time;
extern Time dstime;
//register addr
//写保护寄存器
#define WRITE_PROTECT 0x8e
#define WRITE_PROTECT_CLOSE 0x00
#define WRITE_PROTECT_OPEN 0x80
#define SECONDE_ADDR 0x80
#define MINUTE_ADDR 0x82
#define HOURS_ADDR 0x84
#define DAY_ADDR 0x86