Added ds1307 RTC drivers
This commit is contained in:
2
.settings/com.st.stm32cube.ide.mcu.sfrview.prefs
Normal file
2
.settings/com.st.stm32cube.ide.mcu.sfrview.prefs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
sfrviewstate={"fFavorites"\:{"fLists"\:{}},"fProperties"\:{"fNodeProperties"\:{}}}
|
||||||
100
Core/Inc/ds1307.h
Normal file
100
Core/Inc/ds1307.h
Normal file
@@ -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_ */
|
||||||
356
Core/Src/ds1307.c
Normal file
356
Core/Src/ds1307.c
Normal file
@@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user