From 82dfb42b676cb512e14c8ee0c2594544e9b40818 Mon Sep 17 00:00:00 2001 From: StefansE Date: Thu, 26 Mar 2026 11:27:17 +0100 Subject: [PATCH] Added ds1307 RTC drivers --- .../com.st.stm32cube.ide.mcu.sfrview.prefs | 2 + Core/Inc/ds1307.h | 100 +++++ Core/Src/ds1307.c | 356 ++++++++++++++++++ 3 files changed, 458 insertions(+) create mode 100644 .settings/com.st.stm32cube.ide.mcu.sfrview.prefs create mode 100644 Core/Inc/ds1307.h create mode 100644 Core/Src/ds1307.c diff --git a/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs b/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs new file mode 100644 index 0000000..98a69fc --- /dev/null +++ b/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +sfrviewstate={"fFavorites"\:{"fLists"\:{}},"fProperties"\:{"fNodeProperties"\:{}}} diff --git a/Core/Inc/ds1307.h b/Core/Inc/ds1307.h new file mode 100644 index 0000000..c0f6ee6 --- /dev/null +++ b/Core/Inc/ds1307.h @@ -0,0 +1,100 @@ +/** + * @copyright (c) 2021 Noel Dom https://www.youtube.com/channel/UCINCDcQylATh2wS5BAYIBPg. + * + * @brief Device Driver for DS1307 Real-time clock (RTC) + * @file ds1307.h + * @version 0.1.0 + * @date 2021 + * @author Noel Dominguez. + */ +#ifndef DS1307_H_ +#define DS1307_H_ + +#include "i2c.h" +#include "DBG.h" + + +typedef enum { + + MONDAY = 1, + TUESDAY, + WEDNESDAY, + THURSDAY, + FRIDAY, + SATURDAY, + SUNDAY +}ds1307_days_t; + +typedef enum{ + JAN = 1, + FEBRUARY, + MARCH, + APRIL, + MAY, + JUNE, + JULY, + AUGUST, + SEPTEMBER, + OCTOBER, + NOVEMBER, + DECEMBER +}ds1307_months_t; + +typedef enum{ + DS1307_OK, + DS1307_ERROR +}ds1307_err_t; + +typedef struct { + + uint8_t seconds; + uint8_t minutes; + uint8_t hours; + ds1307_days_t day; + uint8_t date; + ds1307_months_t month; + uint16_t year; + int8_t t_zone_hour; + int8_t t_zone_min; + + +}ds1307_dev_t; + + +/** + * @brief I2C Scanner utility . + * + * @param[in] I2Chnd: i2c handler + * @param[in] delay_: delay between each device scan + * + */ +void start_i2c_scan(I2C_HandleTypeDef *I2Chnd, uint32_t delay_); +void ds1307_init(void); +ds1307_err_t ds1307_set_hour(uint8_t hour); +uint8_t ds1307_get_hour(void); +ds1307_err_t ds1307_set_hour(uint8_t hour); +void ds1307_set_clock_halt(uint8_t halt); +uint8_t ds1307_get_clock_halt(void); +void ds1307_set_second(uint8_t second); +uint8_t ds1307_get_second(void); +void ds1307_set_minutes(uint8_t minutes); +uint8_t ds1307_get_minutes(void); +void ds1307_set_day(uint8_t day); +ds1307_days_t ds1307_get_day(void); +void ds1307_set_date(uint8_t date); +uint8_t ds1307_get_date(void); +void ds1307_set_month(ds1307_months_t month); +ds1307_months_t ds1307_get_month(void); +void ds1307_set_year(uint16_t year); +uint16_t ds1307_get_year(void); +void ds1307_set_time_zone(int8_t hr, uint8_t min); +int8_t ds1307_get_time_zone_hour(void); +int8_t ds1307_get_time_zone_min(void); +void ds1307_update(ds1307_dev_t *ds1307_dev); +void ds1307_config(uint8_t seconds, uint8_t minutes, uint8_t hours,ds1307_days_t day, uint8_t date, + ds1307_months_t month, uint16_t year, int8_t t_zone_hour, int8_t t_zone_min); + +void ds1307_log_uart(ds1307_dev_t *ds1307_dev); + + +#endif /* DS1307_H_ */ diff --git a/Core/Src/ds1307.c b/Core/Src/ds1307.c new file mode 100644 index 0000000..a17b06d --- /dev/null +++ b/Core/Src/ds1307.c @@ -0,0 +1,356 @@ +/** + * @copyright (c) 2021 Noel Dom https://www.youtube.com/channel/UCINCDcQylATh2wS5BAYIBPg. + * + * @brief Device Driver for DS1307 Real-time clock (RTC) + * @file ds1307.c + * @version 0.1.0 + * @date 2021 + * @author Noel Dominguez. + */ + + +#include "ds1307.h" + +#define DS1307_ADDRES 0x68 +#define DS1307_SECONDS 0x00 +#define DS1307_MINUTES 0x01 +#define DS1307_HOURS 0x02 +#define DS1307_DAY 0X03 +#define DS1307_DATE 0x04 +#define DS1307_MONTH 0x05 +#define DS1307_YEAR 0x06 +#define DS1307_CONTROL 0x07 +#define DS1307_REG_UTC_HR 0x08 +#define DS1307_REG_UTC_MIN 0x09 +#define DS1307_REG_CENT 0x10 +#define DS1307_REG_RAM 0x11 +#define DS1307_TIMEOUT 1000 + + +#define DS1307_HANDLER hi2c1 + +typedef enum{ + DS1307_1HZ, + DS1307_4096HZ, + DS1307_8192HZ, + DS1307_32768HZ +}ds1307_rate_t; + + +static ds1307_err_t ds1307_write_byte(uint8_t ds1307_reg_addres, uint8_t data); +static uint8_t ds1307_read_byte(uint8_t ds1307_reg_addres); +static uint8_t ds1307_bcd_decode(uint8_t data); +static uint8_t ds1307_bcd_encode(uint8_t data); + +/** + * @brief Write byte data from an specific address ds1307 RTC + * + * @param ds1307_reg_addres: REG Address you can see more in datasheet page 4 figure 2 + * @param data + * @return ds1307_err_t: 0 if everything is ok + */ +static ds1307_err_t ds1307_write_byte(uint8_t ds1307_reg_addres, uint8_t data){ + + uint8_t buff[2] = {ds1307_reg_addres,data}; + ds1307_err_t ret_val; + ret_val = HAL_I2C_Master_Transmit(&DS1307_HANDLER, DS1307_ADDRES << 1, buff, 2, DS1307_TIMEOUT); + + return ret_val; +} +/** + * @brief Read byte data from an specific address ds1307 RTC + * + * @param ds1307_reg_addres: REG Address you can see more in datasheet page 4 figure 2 + * @return data: data read from reg address + */ +static uint8_t ds1307_read_byte(uint8_t ds1307_reg_addres){ + + uint8_t data; + HAL_I2C_Master_Transmit(&DS1307_HANDLER, DS1307_ADDRES << 1, &ds1307_reg_addres, 1, DS1307_TIMEOUT); + HAL_I2C_Master_Receive(&DS1307_HANDLER, DS1307_ADDRES << 1, &data, 1, DS1307_TIMEOUT); + return data; +} +/** + * @brief BCD decode + * + * @param data: Value to convert + * @return uint8_t: data converted + */ +static uint8_t ds1307_bcd_decode(uint8_t data){ + return (((data & 0xf0) >> 4) * 10) + (data & 0x0f); +} +/** + * @brief BCD Encode + * + * @param data: Value to convert + * @return uint8_t: data converted + */ +static uint8_t ds1307_bcd_encode(uint8_t data){ + return (data % 10 + ((data / 10) << 4)); +} + +/** + * @brief Init ds1307 + * + */ +void ds1307_init(void){ + ds1307_set_clock_halt(0); +} + +/** + * @brief To start the time and calendar, we must set the stop bit of the clock (CH) in 0, to stop, put the bit in 1 + * more information see datasheet on page 4 + * + * @param halt: 0 init, 1 stop + */ +void ds1307_set_clock_halt(uint8_t halt){ + uint8_t ch = (halt ? 1 << 7 : 0); + ds1307_write_byte(DS1307_SECONDS, ch | (ds1307_read_byte(DS1307_SECONDS) & 0x7F)); +} +/** + * @brief ds1307_get_clock_halt more info datasheet page 4 + * + * @return uint8_t + */ +uint8_t ds1307_get_clock_halt(void){ + return (ds1307_read_byte(DS1307_SECONDS) & 0x80) >> 7; +} + +/** + * @brief ds1307_set_hour + * + * @param hour + * @return ds1307_err_t + */ +ds1307_err_t ds1307_set_hour(uint8_t hour){ + return ds1307_write_byte(DS1307_HOURS,ds1307_bcd_encode(hour & 0x3F)); +} +/** + * @brief ds1307_get_hour + * + * @return uint8_t + */ +uint8_t ds1307_get_hour(void){ + return ds1307_bcd_decode(ds1307_read_byte(DS1307_HOURS) & 0x3F); +} + +/** + * @brief ds1307_set_second + * + * @param second + */ +void ds1307_set_second(uint8_t second){ + uint8_t val = ds1307_get_clock_halt(); + ds1307_write_byte(DS1307_SECONDS, ds1307_bcd_encode(second | val)); + +} +/** + * @brief ds1307_get_second + * + * @return uint8_t + */ +uint8_t ds1307_get_second(void){ + return ds1307_bcd_decode(ds1307_read_byte(DS1307_SECONDS) & 0x7F); +} +/** + * @brief ds1307_set_minutes + * + * @param minutes + */ +void ds1307_set_minutes(uint8_t minutes){ + ds1307_write_byte(DS1307_MINUTES, ds1307_bcd_encode(minutes)); +} +/** + * @brief ds1307_get_minutes + * + * @return uint8_t + */ +uint8_t ds1307_get_minutes(void){ + return ds1307_bcd_decode(ds1307_read_byte(DS1307_MINUTES)); + +} +/** + * @brief ds1307_set_day + * + * @param day + */ +void ds1307_set_day(uint8_t day){ + ds1307_write_byte(DS1307_DAY, ds1307_bcd_encode(day)); +} +/** + * @brief ds1307_get_day + * + * @return ds1307_days_t + */ +ds1307_days_t ds1307_get_day(void){ + return ds1307_read_byte(ds1307_bcd_decode(DS1307_DAY)); +} + + +/** + * @brief ds1307_set_date + * + * @param date + */ +void ds1307_set_date(uint8_t date){ + ds1307_write_byte(DS1307_DATE, ds1307_bcd_encode(date)); +} +/** + * @brief + * + * @return uint8_t + */ +uint8_t ds1307_get_date(void){ + return ds1307_bcd_decode(ds1307_read_byte(DS1307_DATE)); +} + +/** + * @brief ds1307_set_month + * + * @param month + */ +void ds1307_set_month(ds1307_months_t month){ + ds1307_write_byte(DS1307_MONTH, ds1307_bcd_encode(month)); +} +/** + * @brief ds1307_get_month + * + * @return ds1307_months_t + */ +ds1307_months_t ds1307_get_month(void){ + return ds1307_read_byte(ds1307_bcd_decode(DS1307_MONTH)); +} +/** + * @brief ds1307_set_year + * + * @param year setup year + */ +void ds1307_set_year(uint16_t year){ + ds1307_write_byte(DS1307_REG_CENT, year / 100); + ds1307_write_byte(DS1307_YEAR, ds1307_bcd_encode(year % 100)); +} +/** + * @brief ds1307_get_year + * + * @return uint16_t: current year + */ +uint16_t ds1307_get_year(void){ + uint16_t cent = ds1307_read_byte(DS1307_REG_CENT) * 100; + return ds1307_bcd_decode(ds1307_read_byte(DS1307_YEAR)) + cent; + +} +/** + * @brief Set your time zone more info at https://everytimezone.com/ + * + * @param hr: current hour + * @param min: current min + */ +void ds1307_set_time_zone(int8_t hr, uint8_t min){ + ds1307_write_byte(DS1307_REG_UTC_HR, hr); + ds1307_write_byte(DS1307_REG_UTC_MIN, min); +} +/** + * @brief Get the actual timezone-hour configured in the rtc + * + * @return int8_t actual time zone + */ +int8_t ds1307_get_time_zone_hour(void){ + return ds1307_read_byte(DS1307_REG_UTC_HR); +} +/** + * @brief Get the actual timezone-min configured in the rtc + * + * @return int8_t: actual time zone + */ +int8_t ds1307_get_time_zone_min(void){ + return ds1307_read_byte(DS1307_REG_UTC_MIN); +} + + +/** + * @brief Update ds1307 data + * + * @param dev: ds1307 pointer + */ +void ds1307_update(ds1307_dev_t *ds1307_dev){ + + ds1307_dev->seconds = ds1307_get_second(); + ds1307_dev->minutes = ds1307_get_minutes(); + ds1307_dev->hours = ds1307_get_hour(); + ds1307_dev->day = ds1307_get_day(); + ds1307_dev->date = ds1307_get_date(); + ds1307_dev->month = ds1307_get_month(); + ds1307_dev->year = ds1307_get_year(); + ds1307_dev->t_zone_hour = ds1307_get_time_zone_hour(); + ds1307_dev->t_zone_min = ds1307_get_time_zone_min(); +} +/** + * @brief Use this function to configure the DS1307, you only need to call this function once on the the first run of your RTC. + * + * @param seconds + * @param minutes + * @param hours + * @param day + * @param date + * @param month + * @param year + * @param t_zone_hour + * @param t_zone_min + */ +void ds1307_config(uint8_t seconds, uint8_t minutes, uint8_t hours,ds1307_days_t day, uint8_t date, + ds1307_months_t month, uint16_t year, int8_t t_zone_hour, int8_t t_zone_min) +{ + ds1307_set_second(seconds); + ds1307_set_minutes(minutes); + ds1307_set_hour(hours); + ds1307_set_day(day); + ds1307_set_date(date); + ds1307_set_month(month); + ds1307_set_year(year); + ds1307_set_time_zone(t_zone_hour, t_zone_min); + +} +/** + * @brief: Display ds1307 info by UART, @todo you need to implement your printf function! + * + * @param: ds1307_dev ds1307 struct pointer + */ +void ds1307_log_uart(ds1307_dev_t *ds1307_dev){ + DBG_print("%d:%d:%d %d/%d/%d\n",ds1307_dev->hours,ds1307_dev->minutes,ds1307_dev->seconds, + ds1307_dev->date,ds1307_dev->month,ds1307_dev->year); +} +/** + * @brief This function helps to scan all connected devices on our I2C peripheral + * + * @param I2Chnd: I2C Handles + * @param delay_: Delay between scanning + */ +void start_i2c_scan(I2C_HandleTypeDef *I2Chnd, uint32_t delay_){ + + HAL_StatusTypeDef status; + uint8_t no_devices = 0; + DBG_print("\n\r [ I2C Scanner v0.1 ]"); + + for (uint8_t i = 0; i < 128; i++){ + + status = HAL_I2C_IsDeviceReady(I2Chnd , (uint16_t)(i<<1), 2, 2); + + if ( status != HAL_OK){ + //DBG_print(".\n\r"); + } else { + DBG_print("\n\rDevice found! Address: 0x%X",i); + ++no_devices; + } + + HAL_Delay(delay_); + + } + + if (!no_devices){ + DBG_print("\n\r No Devices found!"); + } else { + DBG_print("\n\r Total Devices found: %d",no_devices); + + } + +}