#ifndef GUARD_DS3231_H #define GUARD_DS3231_H #ifdef __cplusplus extern "C" { #endif #include #include #define DS3231_ADDRESS_READ 0b11010001 #define DS3231_ADDRESS_WRITE 0b11010000 #define DS3231_OPERATION_SUCCESS 0 // this is returned if a function ran without errors // general time keeping registers #define DS3231_REGISTER_SECONDS 0 #define DS3231_REGISTER_MINUTES 0x1 #define DS3231_REGISTER_HOURS 0x2 #define DS3231_REGISTER_DAY 0x3 #define DS3231_REGISTER_DATE 0x4 #define DS3231_REGISTER_MONTH_CENTURY 0x5 #define DS3231_REGISTER_YEAR 0x6 // alarm 1 registers #define DS3231_REGISTER_ALARM1_SECONDS 0x7 #define DS3231_REGISTER_ALARM1_MINUTES 0x8 #define DS3231_REGISTER_ALARM1_HOURS 0x9 #define DS3231_REGISTER_ALARM1_DAY_DATE 0xa // alarm 1 trigger interval bits #define DS3231_ALARM1_A1M1_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.) #define DS3231_ALARM1_A1M2_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.) #define DS3231_ALARM1_A1M3_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.) #define DS3231_ALARM1_A1M4_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.) // alarm 2 registers #define DS3231_REGISTER_ALARM2_MINUTES 0xb #define DS3231_REGISTER_ALARM2_HOURS 0xc #define DS3231_REGISTER_ALARM2_DAY_DATE 0xd // alarm 2 trigger interval bits #define DS3231_ALARM2_A2M2_BIT (1 << 7) // used to signal when an alarm should be triggered (e.g. every second etc.) #define DS3231_ALARM2_A2M3_BIT (1 << 7) #define DS3231_ALARM2_A2M4_BIT (1 << 7) // other alarm bits #define DS3231_ALARM_DAY_BIT (1 << 6) // used to indicate if an alarm is set for a DAY or DATE // control register #define DS3231_REGISTER_CONTROL 0xe // control register bits #define DS3231_CONTROL_EOSC_BIT (1 << 7) #define DS3231_CONTROL_BBQSW_BIT (1 << 6) #define DS3231_CONTROL_CONV_BIT (1 << 5) #define DS3231_CONTROL_RS2_BIT (1 << 4) #define DS3231_CONTROL_RS1_BIT (1 << 3) #define DS3231_CONTROL_INTCN_BIT (1 << 2) // enable interrupts #define DS3231_CONTROL_A2IE_BIT (1 << 1) // enable alarm 2 #define DS3231_CONTROL_A1IE_BIT (1 << 0) // enable alarm 1 // status register #define DS3231_REGISTER_STATUS 0xf // status register bits #define DS3231_STATUS_OSF_BIT (1 << 7) // oscillator stop #define DS3231_STATUS_EN32KHZ_BIT (1 << 3) // enable 32KHz square wave output #define DS3231_STATUS_BSY_BIT (1 << 2) // device busy bit #define DS3231_STATUS_A2F_BIT (1 << 1) // alarm 2 triggered flag #define DS3231_STATUS_A1F_BIT (1 << 0) // alarm 1 triggered flag // aging register #define DS3231_REGISTER_AGING_OFFSET 0x10 // temperature registers #define DS3231_REGISTER_TEMPERATURE_MSB 0x11 #define DS3231_REGISTER_TEMPERATURE_LSB 0x12 // special toggle bits #define DS3231_HOUR_MODE_12_BIT (1 << 6) // this will be 1 in the HOURS register if 12 hour mode is selected. 0 if 24 hour mode selected #define DS3231_PM_BIT (1 << 5) // if using 12 hr mode, this bit is set in the HOURS register to indicate if the time is AM or PM with PM being indicated by a 1 and AM by a 0 #define DS3231_20_HOUR_BIT (1 << 5) // if using 24 hr mode, this bit is set in the HOURS register to indicate the hours between 20 and 23 #define DS3231_CENTURY_BIT (1 << 7) // in the month/century register bit 7 is set when a new century is entered // possible days typedef enum { DS_SUNDAY = 1, // must start from 1 according to datasheet DS_MONDAY = 2, DS_TUESDAY = 3, DS_WEDNESDAY = 4, DS_THURSDAY = 5, DS_FRIDAY = 6, DS_SATURDAY = 7, DAY_T_MAX = 8 } day_t; // possible months typedef enum { DS_JANUARY = 1, DS_FEBRUARY = 2, DS_MARCH = 3, DS_APRIL = 4, DS_MAY = 5, DS_JUNE = 6, DS_JULY = 7, DS_AUGUST = 8, DS_SEPTEMBER = 9, DS_OCTOBER = 10, DS_NOVEMBER = 11, DS_DECEMBER = 12, MONTH_T_MAX = 13 } month_t; // the available alarms of the ds3231 typedef enum { ALARM_1, ALARM_2, ALARM_NUMBER_T_MAX } alarm_number_t; // defines when alarms should be triggered, e.g. when seconds match typedef enum { ////////////////////////// // ALARM1 (A1) triggers // ////////////////////////// A1_EVERY_SEC, // triggers every second A1_SEC_MATCH, // triggers when seconds value in ALARM1 seconds register match ds3231 seconds register A1_MIN_SEC_MATCH, // triggers when seconds & min value the ALARM1 seconds & min registers match ds3231 seconds & min registers A1_HOUR_MIN_SEC_MATCH, // triggers when hours, min & seconds value in ALARM1 respective registers match ds3231 hour, min & seconds registers A1_DAY_DATE_HOUR_MIN_SEC_MATCH, // triggers when day/date, hours, min & seconds in ALARM1 register match the values in the ds3231 time & date registers // depending on what is "useDay" is true in the alarm_t used selects whether the alarm triggers on a day or date ////////////////////////// // ALARM2 (A2) triggers // ////////////////////////// A2_EVERY_MIN, // triggers every minute (at 0 seconds of the new minute) A2_MIN_MATCH, // triggers when ALARM2 minute register matches the ds3231 minute register A2_HOUR_MIN_MATCH, // triggers when ALARM2 minute & hour register matches the ds3231 minute & hour registers A2_DAY_DATE_HOUR_MIN_MATCH, // triggers when ALARM2 day/date, hour & min register match the ds3231 registers // depending on what is "useDay" is true in the alarm_t used selects whether the alarm triggers on a day or date ALARM_TRIGGER_T_MAX } alarm_trigger_t; // used to set alarms typedef struct { alarm_number_t alarmNumber; // which alarm to set uint8_t second; // the seconds value of the alarm, this is only valid for ALARM_1 uint8_t minute; // minutes value of alarm uint8_t hour; // hour value of alarm bool useDay; // if TRUE, then the value in the "dayDate" field is interpreted as the day_t to trigger the alarm // e.g. THURSDAY. // if FALSE, then the value in "dayDate" is interpreted as a numerical date value to trigger the alarm // e.g. 12 (the 12th of the month) uint8_t dayDate; // the day OR date of the alarm (depends on useDay); alarm_trigger_t trigger; // when the alarm will trigger, e.g. on match on mins & seconds } alarm_t; // the frequencies the bbsqw can output typedef enum { HZ_1, // 1 Hz KHZ_1_024, // 1.024 KHz KHZ_4_096, // 4.096 KHz KHZ_8_192, // 8.192 KHz BBSQW_FREQUENCY_MAX } bbsqw_frequency_t; //////////////////////////////////////////////////////////////// // Global variables // //////////////////////////////////////////////////////////////// // used to track the century static uint8_t century = 21; // year 20xx has a century of 21 // used to indicate the hour storing mode, either AM/PM (12 hour mode) or 24 hour mode static bool is24HourMode = true; //////////////////////////////////////////////////////////////// // Function prototypes // //////////////////////////////////////////////////////////////// void initDS3231(void); // time setting / getting functions void ds3231Use12HourMode(bool); uint8_t ds3231SetSecond(uint8_t); uint8_t ds3231GetSecond(void); uint8_t ds3231SetMinute(uint8_t); uint8_t ds3231GetMinute(void); uint8_t ds3231SetHour(uint8_t, bool); uint8_t ds3231GetHour(void); uint8_t ds3231SetDay(day_t); day_t ds3231GetDay(void); uint8_t ds3231SetDate(uint8_t); uint8_t ds3231GetDate(void); uint8_t ds3231SetMonth(month_t); month_t ds3231GetMonth(void); uint8_t ds3231SetYear(uint8_t); uint8_t ds3231GetYear(void); void ds3231SetCentury(uint8_t); uint8_t ds3231GetCentury(void); uint8_t ds3231SetFullDate(day_t, uint8_t, month_t, uint8_t, uint8_t); uint8_t ds3231SetTime(uint8_t, uint8_t, uint8_t, bool); // alarm functions uint8_t ds3231SetAlarm(const alarm_t *); uint8_t ds3231ClearAlarmFlag(alarm_number_t); uint8_t ds3231RemoveAlarm(alarm_number_t); // temperature functions void ds3231ForceTemperatureUpdate(void); int16_t ds3231GetTemperature(void); // oscillator functions uint8_t ds3231DisableOscillatorOnBattery(void); uint8_t ds3231EnableOscillatorOnBattery(void); bool ds3231HasOscillatorStopped(void); // 32KHz output pin functions uint8_t ds3231Enable32KHzOutput(void); uint8_t ds3231Disable32KhzOutput(void); // aging offset functions uint8_t ds3231SetAgingOffset(int8_t); int8_t ds3231GetAgingOffset(void); // other functions uint8_t ds3231EnableBBSQW(bbsqw_frequency_t); // utility functions uint8_t setRegisterPointer(uint8_t); uint8_t getRegisterValue(uint8_t); uint8_t writeValueThenStop(uint8_t, uint8_t); #ifdef __cplusplus } #endif #endif