在多字节访问期间,当地址指针达到3Fh,即RAM空间的末尾时,它会环绕到位置00h,即时钟空间的开头。
这个RAM是留给用户使用的存储空间,RTC不会用到这部分RAM
DS1307上的RAM(随机存储器)用于存储临时数据,用户自定义的设置以及其他需要在断电时保持的信息。以下是DS1307上RAM的主要用途:
存储用户数据: 用户可以将自定义数据存储在DS1307的RAM中。这可以包括配置参数、计数器值、标志位等。因为这部分RAM是带电池支持的,所以即使在主电源断电时,这些数据也会被保持。
保存配置信息: DS1307的RAM可以用于存储与实时时钟(RTC)和其他功能相关的配置信息。这些配置信息可能包括时钟格式(12小时或24小时制)、日期格式、方波输出频率等。
临时存储: RAM还可用于存储临时性的运行时数据。例如,当进行时钟校准或其他运行时操作时,可能需要在RAM中存储一些中间数据。
断电备份: 由于RAM是带电池支持的,所以它提供了断电备份的功能。即使主电源断电,RAM中的数据仍然会被保存,确保在电源重新连接时可以恢复先前的状态。
总的来说,DS1307上的RAM为用户提供了一块持久存储区域,允许在断电时保留关键的信息。这在需要在系统重新上电时恢复先前状态或保留特定配置和数据时非常有用。
设置时钟,比如设置时钟为2024-01-26 10:37:10 周五
发送的字节依次为:设备地址0x68,寄存器地址00,接下来7个字节是要设置进00h-06h这7个寄存器的值。
读取时钟
1.先发送一个数据00,将读取指针只想寄存器0.这个操作在数据手册有说。
2.然后连续读取出数据
#include
#include "esp_log.h"
#include "ds1307_driver.h"
#include "driver/i2c.h"
#include
static const char *TAG = "ds1307-driver";
#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
#define DS1307_I2C_ADDR 0x68 /*!< Slave address of the MPU9250 sensor */
RTC_time_typedef time;
esp_err_t ds1307_init(void)
{
int ret;
// 初始化iic
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(i2c_master_port, &conf);
ret = i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
ESP_LOGI(TAG, "I2C initialized successfully");
return ret;
}
esp_err_t ds1307_read_time(date_time_t *p_time)
{
int ret;
uint8_t write_buf[8] = {0};
uint8_t *p = (uint8_t *)p_time;
// 1.先要发一个字节(write),值为0,
write_buf[0] = 0;
ret = i2c_master_write_to_device(I2C_MASTER_NUM, DS1307_I2C_ADDR, write_buf, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
vTaskDelay(20 / portTICK_PERIOD_MS);
// 开始读取数据
ret = i2c_master_read_from_device(I2C_MASTER_NUM, DS1307_I2C_ADDR, (uint8_t *)&time, 7, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
ESP_LOGI(TAG, "get raw data:%x,%x,%x,%x,%x,%x,%x,", *(p + 0), *(p + 1), *(p + 2), *(p + 03), *(p + 04), *(p + 05), *(p + 06));
p_time->second = time.seconds.ten_sec * 10 + time.seconds.seconds;
p_time->minute = time.minutes.ten_min * 10 + time.minutes.minutes;
p_time->hour = time.hours.ten_hour * 10 + time.hours.hours;
p_time->week = time.weeks.week;
p_time->day = time.dates.ten_date * 10 + time.dates.date;
p_time->month = time.months.ten_month * 10 + time.months.month;
p_time->year = time.years.ten_year * 10 + time.years.year;
ESP_LOGI(TAG, "%d-%d-%d %d:%d:%d week=%d", p_time->year, p_time->month, p_time->day, p_time->hour, p_time->minute, p_time->second, p_time->week);
return ret;
}
/**
* @brief 设置芯片的时间
*/
esp_err_t ds1307_set_time(date_time_t datetime)
{
int ret;
RTC_time_typedef time;
uint8_t write_buf[9] = {0};
uint8_t *p = (uint8_t *)&time;
time.years.ten_year = datetime.year / 10;
time.years.year = datetime.year % 10;
time.months.ten_month = datetime.month / 10;
time.months.month = datetime.month % 10;
time.dates.ten_date = datetime.day / 10;
time.dates.date = datetime.day % 10;
time.weeks.week = datetime.week;
time.hours.ten_hour = datetime.hour / 10;
time.hours.hours = datetime.hour % 10;
time.minutes.ten_min = datetime.minute / 10;
time.minutes.minutes = datetime.minute % 10;
time.seconds.ten_sec = datetime.second / 10;
time.seconds.seconds = datetime.second % 10;
time.seconds.ch = 0;
ESP_LOGI(TAG, "set raw data:%x,%x,%x,%x,%x,%x,%x,", *(p + 0), *(p + 1), *(p + 2), *(p + 03), *(p + 04), *(p + 05), *(p + 06));
memcpy(write_buf + 1, p, 7);
ret = i2c_master_write_to_device(I2C_MASTER_NUM, DS1307_I2C_ADDR, write_buf, 8, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
return ret;
}
头文件
#ifndef __DS1307_H_
#define __DS1307_H_
#include "driver/i2c.h"
typedef struct
{
union
{
uint8_t value;
struct
{
uint8_t seconds : 4;
uint8_t ten_sec : 3;
uint8_t ch : 1;
};
};
} second_data_TypeDef; // 秒
typedef struct
{
union
{
uint8_t value;
struct
{
uint8_t minutes : 4;
uint8_t ten_min : 3;
uint8_t bit7 : 1;
};
};
} minutes_data_TypeDef; // 分
typedef struct
{
union
{
uint8_t value;
struct
{
uint8_t hours : 4;
uint8_t ten_hour : 2;
uint8_t jinzhi : 1;
uint8_t : 1;
};
};
} hours_data_TypeDef; // 时
typedef struct
{
union
{
uint8_t value;
struct
{
uint8_t week : 3;
uint8_t : 5;
};
};
} weeks_data_TypeDef; // 周
typedef struct
{
union
{
uint8_t value;
struct
{
uint8_t date : 4;
uint8_t ten_date : 2;
uint8_t : 2;
};
};
} dates_data_TypeDef; // 日
typedef struct
{
union
{
uint8_t value;
struct
{
uint8_t month : 4;
uint8_t ten_month : 1;
uint8_t : 3;
};
};
} months_data_TypeDef; // 月
typedef struct
{
union
{
uint8_t value;
struct
{
uint8_t year : 4;
uint8_t ten_year : 4;
};
};
} years_data_TypeDef; // 年
typedef struct
{
second_data_TypeDef seconds;
minutes_data_TypeDef minutes;
hours_data_TypeDef hours;
weeks_data_TypeDef weeks;
dates_data_TypeDef dates;
months_data_TypeDef months;
years_data_TypeDef years;
} RTC_time_typedef;
typedef struct
{
uint16_t year;
uint16_t month;
uint16_t day;
uint8_t week;
uint16_t hour;
uint16_t minute;
uint16_t second;
} date_time_t;
esp_err_t ds1307_init(void);
esp_err_t ds1307_read_time(date_time_t *p_time);
esp_err_t ds1307_set_time(date_time_t datetime);
#endif
main文件
#include
#include "esp_log.h"
#include "ds1307_driver.h"
static const char *TAG = "i2c_DS1307_main";
void app_main(void)
{
date_time_t date_time={
.year = 24,
.month = 1,
.day = 26,
.week = 5,
.hour = 10,
.minute = 37,
.second = 10,
},date_time_now;
ESP_ERROR_CHECK(ds1307_init());
/* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */
ESP_ERROR_CHECK(ds1307_set_time(date_time));
ESP_LOGI(TAG, "set successfully");
vTaskDelay(3000/portTICK_PERIOD_MS);
while(1)
{
ds1307_read_time(&date_time_now);
vTaskDelay(1000/portTICK_PERIOD_MS);
}
}