DS3231 Extremely Accurate I2C-Integrated RTC/TCXO/Crystal.
DS3231.cpp
- Committer:
- mcm
- Date:
- 2017-12-20
- Revision:
- 3:0226d018fdcb
- Parent:
- 2:3710775b1864
File content as of revision 3:0226d018fdcb:
/** * @brief DS3231.cpp * @details Extremely Accurate I2C-Integrated RTC/TCXO/Crystal. * Function file. * * * @return NA * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN. * @warning NaN * @pre This code belongs to AqueronteBlog ( http://unbarquero.blogspot.com ). */ #include "DS3231.h" DS3231::DS3231 ( PinName sda, PinName scl, uint32_t addr, uint32_t freq ) : _i2c ( sda, scl ) , _DS3231_Addr ( addr ) { _i2c.frequency( freq ); } DS3231::~DS3231() { } /** * @brief DS3231_ReadTemperature ( DS3231_vector_data_t* ) * * @details It gets the temperature. * * @param[in] NaN * * @param[out] myTemperature: Temperature data. * * * @return Status of DS3231_ReadTemperature. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre The temperature registers are updated after each user-initiated conversion and on every 64-second conversion. * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_ReadTemperature ( DS3231_vector_data_t* myTemperature ) { char cmd[] = { DS3231_MSB_TEMPERATURE, 0 }; uint32_t aux = 0; // It gets the temperature aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); // Parse the data // 1. Check if the Temperature is positive or negative if ( ( cmd[0] & 0b10000000 ) == 0b00000000 ) myTemperature->Temperature = cmd[0]; // Positive value else myTemperature->Temperature = -1.0 * ( ( ~cmd[0] ) + 1 ); // Negative value // 2. Decimal part. 0.25°C resolution switch( cmd[1] ) { // x.00°C default: case 0b00000000: break; // x.25°C case 0b01000000: myTemperature->Temperature += 0.25; break; // x.50°C case 0b10000000: myTemperature->Temperature += 0.50; break; // x.75°C case 0b11000000: myTemperature->Temperature += 0.75; break; } if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_ReadRawTemperature ( DS3231_vector_data_t* ) * * @details It gets the raw temperature. * * @param[in] NaN * * @param[out] myRawTemperature: Raw Temperature data. * * * @return Status of DS3231_ReadTemperature. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre The temperature registers are updated after each user-initiated conversion and on every 64-second conversion. * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_ReadRawTemperature ( DS3231_vector_data_t* myRawTemperature ) { char cmd[] = { DS3231_MSB_TEMPERATURE, 0 }; uint32_t aux = 0; // It gets the temperature aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); // Parse the data myRawTemperature->MSBTemperature = cmd[0]; myRawTemperature->LSBTemperature = cmd[1]; if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_StartNewConvertTemperature ( void ) * * @details It triggers a new temperature conversion. * * @param[in] NaN. * * @param[out] NaN. * * * @return Status of DS3231_StartNewConvertTemperature. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_StartNewConvertTemperature ( void ) { char cmd[] = { DS3231_CONTROL_STATUS, 0 }; uint32_t aux = 0; uint32_t ii = 0; // BSY MUST be checked before triggering a new temperature conversion do { aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); ii++; } while ( ( ( cmd[1] & STATUS_BUSY_MASK ) != STATUS_BUSY_NOBUSY ) && ( ii < DS3231_TIMEOUT ) ); // if something went wrong, there will not be a new temperature conversion cmd[0] = DS3231_CONTROL; if ( ii < DS3231_TIMEOUT ) { // It triggers a new temperature conversion // It reads CONTROL register aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); // Start a new temperature conversion cmd[1] |= CONTROL_STATUS_CONVERT_TEMPERATURE_ENABLED; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); // Wait until the temperature conversion is completed ii = 0; do { aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); ii++; } while ( ( ( cmd[1] & CONTROL_STATUS_CONVERT_TEMPERATURE_MASK ) != CONTROL_STATUS_CONVERT_TEMPERATURE_DISABLED ) && ( ii < DS3231_TIMEOUT ) ); } // If TIMEOUT happens, something went wrong! if ( ii >= DS3231_TIMEOUT ) aux = I2C_FAILURE; if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_ReadRawAging ( DS3231_vector_data_t* ) * * @details It gets the raw aging. * * @param[in] NaN * * @param[out] myRawAging: Raw Aging data. * * * @return Status of DS3231_ReadRawAging. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_ReadRawAging ( DS3231_vector_data_t* myRawAging ) { char cmd = DS3231_AGING_OFFSET; uint32_t aux = 0; // It gets the raw aging value aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myRawAging->RawAging = cmd; if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_Status32kHzPin ( DS3231_status_enable_32khz_output_t ) * * @details It enables/disables the 32kHz output pin. * * @param[in] my32kHzPin: 32kHz pin enabled/disabled. * * @param[out] NaN. * * * @return Status of DS3231_Status32kHzPin. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_Status32kHzPin ( DS3231_status_enable_32khz_output_t my32kHzPin ) { char cmd[] = { DS3231_CONTROL_STATUS, 0 }; uint32_t aux = 0; // It reads the status register to parse the data aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); cmd[1] &= ~STATUS_ENABLE_32KHZ_OUTPUT_MASK; cmd[1] |= my32kHzPin; // Update the register aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_ClearAlarmFlag ( DS3231_status_alarm1_flag_t , DS3231_status_alarm2_flag_t ) * * @details It clears alarm flags. * * @param[in] myA1F: Reset/Mask alarm 1 flag. * @param[in] myA2F: Reset/Mask alarm 2 flag. * * @param[out] NaN. * * * @return Status of DS3231_ClearAlarmFlag. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_ClearAlarmFlag ( DS3231_status_alarm1_flag_t myA1F, DS3231_status_alarm2_flag_t myA2F ) { char cmd[] = { DS3231_CONTROL_STATUS, 0 }; uint32_t aux = 0; // It reads the status register to parse the data aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); cmd[1] &= ~( STATUS_ALARM1_FLAG_MASK | STATUS_ALARM2_FLAG_MASK ); cmd[1] |= ( myA1F | myA2F ); // Update the register aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_SetAlarm1 ( DS3231_alarm1_register_t ) * * @details It sets the alarm 1. * * @param[in] myAlarm1: Alarm 1 options. * * @param[out] NaN. * * * @return Status of DS3231_SetAlarm1. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_SetAlarm1 ( DS3231_alarm1_register_t myAlarm1 ) { char cmd[] = { 0, 0 }; uint32_t aux = 0; uint32_t Alarm1SecondAux = 0; // A1M1 uint32_t Alarm1MinuteAux = 0; // A1M2 uint32_t Alarm1HourAux = 0; // A1M3 uint32_t Alarm1DayDateAux = 0; // A1M4 & DYDT // Read all the registers involved in the alarm1 // A1M1 cmd[0] = DS3231_ALARM_1_SECONDS; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); Alarm1SecondAux = ( cmd[1] & ~ALARM1_A1M1_MASK ); // A1M2 cmd[0] = DS3231_ALARM_1_MINUTES; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); Alarm1MinuteAux = ( cmd[1] & ~ALARM1_A1M2_MASK ); // A1M3 cmd[0] = DS3231_ALARM_1_HOURS; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); Alarm1HourAux = ( cmd[1] & ~ALARM1_A1M3_MASK ); // A1M4 & DY/#DT cmd[0] = DS3231_ALARM_1_DAY_DATE; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); Alarm1DayDateAux = ( cmd[1] & ~( ALARM1_A1M4_MASK | ALARM1_DYDT_MASK ) ); // Set all ( A1M1, A1M2, A1M3 A1M4 and DY/#DT ) to 0 cmd[0] = DS3231_ALARM_1_SECONDS; cmd[1] = Alarm1SecondAux; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); cmd[0] = DS3231_ALARM_1_MINUTES; cmd[1] = Alarm1MinuteAux; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); cmd[0] = DS3231_ALARM_1_HOURS; cmd[1] = Alarm1HourAux; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); cmd[0] = DS3231_ALARM_1_DAY_DATE; cmd[1] = Alarm1DayDateAux; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); // Update the Alarm 1 rate switch ( myAlarm1 ) { case ALARM1_ALARM_ONCE_PER_SECOND: cmd[0] = DS3231_ALARM_1_SECONDS; cmd[1] = ( Alarm1SecondAux | ALARM1_A1M1_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); case ALARM1_WHEN_SECONDS_MATCH: cmd[0] = DS3231_ALARM_1_MINUTES; cmd[1] = ( Alarm1MinuteAux | ALARM1_A1M2_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); case ALARM1_WHEN_MINUTES_AND_SECONDS_MATCH: cmd[0] = DS3231_ALARM_1_HOURS; cmd[1] = ( Alarm1HourAux | ALARM1_A1M3_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); case ALARM1_WHEN_HOURS_MINUTES_AND_SECONDS_MATCH: cmd[0] = DS3231_ALARM_1_DAY_DATE; cmd[1] = ( Alarm1DayDateAux | ALARM1_A1M4_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); break; default: case ALARM1_WHEN_DATE_HOURS_MINUTES_AND_SECONDS_MATCH: break; case ALARM1_WHEN_DAY_HOURS_MINUTES_AND_SECONDS_MATCH: cmd[0] = DS3231_ALARM_1_DAY_DATE; cmd[1] = ( Alarm1DayDateAux | ALARM1_DYDT_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); break; } if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_SetAlarm2 ( DS3231_alarm2_register_t ) * * @details It sets the alarm 2. * * @param[in] myAlarm1: Alarm 2 options. * * @param[out] NaN. * * * @return Status of DS3231_SetAlarm2. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_SetAlarm2 ( DS3231_alarm2_register_t myAlarm2 ) { char cmd[] = { 0, 0 }; uint32_t aux = 0; uint32_t Alarm2MinuteAux = 0; // A2M2 uint32_t Alarm2HourAux = 0; // A2M3 uint32_t Alarm2DayDateAux = 0; // A2M3 & DYDT // Read all the registers involved in the alarm2 // A2M2 cmd[0] = DS3231_ALARM_2_MINUTES; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); Alarm2MinuteAux = ( cmd[1] & ~ALARM2_A2M2_MASK ); // A2M3 cmd[0] = DS3231_ALARM_2_HOURS; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); Alarm2HourAux = ( cmd[1] & ~ALARM2_A2M3_MASK ); // A2M4 & DY/#DT cmd[0] = DS3231_ALARM_2_DAY_DATE; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); Alarm2DayDateAux = ( cmd[1] & ~( ALARM2_A2M4_MASK | ALARM2_DYDT_MASK ) ); // Set all ( A2M2, A2M3 A2M4 and DY/#DT ) to 0 cmd[0] = DS3231_ALARM_2_MINUTES; cmd[1] = Alarm2MinuteAux; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); cmd[0] = DS3231_ALARM_2_HOURS; cmd[1] = Alarm2HourAux; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); cmd[0] = DS3231_ALARM_2_DAY_DATE; cmd[1] = Alarm2DayDateAux; aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); // Update the Alarm 2 rate switch ( myAlarm2 ) { case ALARM2_ALARM_ONCE_PER_MINUTE: cmd[0] = DS3231_ALARM_2_MINUTES; cmd[1] = ( Alarm2MinuteAux | ALARM2_A2M2_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); case ALARM2_WHEN_MINUTES_MATCH: cmd[0] = DS3231_ALARM_2_HOURS; cmd[1] = ( Alarm2HourAux | ALARM2_A2M3_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); case ALARM2_WHEN_HOURS_MINUTES_MATCH: cmd[0] = DS3231_ALARM_2_DAY_DATE; cmd[1] = ( Alarm2DayDateAux | ALARM2_A2M4_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); break; default: case ALARM2_WHEN_DATE_HOURS_AND_MINUTES_MATCH: break; case ALARM2_WHEN_DAY_HOURS_AND_MINUTES_MATCH: cmd[0] = DS3231_ALARM_2_DAY_DATE; cmd[1] = ( Alarm2DayDateAux | ALARM2_DYDT_MASK ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); break; } if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_SetAlarmsInterrupt ( DS3231_control_status_alarm1_t , DS3231_control_status_alarm2_t ) * * @details It enables/disable alarm interrupts. * * @param[in] myAlarm1: Enable/Disable Alarm1 interrupt. * @param[in] myAlarm2: Enable/Disable Alarm2 interrupt. * * @param[out] NaN. * * * @return Status of DS3231_SetAlarmsInterrupt. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_SetAlarmsInterrupt ( DS3231_control_status_alarm1_t myAlarm1, DS3231_control_status_alarm2_t myAlarm2 ) { char cmd[] = { DS3231_CONTROL, 0 }; uint32_t aux = 0; // Read the Control Register aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); // Parse the data cmd[1] &= ~( CONTROL_STATUS_ALARM1_MASK | CONTROL_STATUS_ALARM2_MASK ); cmd[1] |= ( myAlarm1 | myAlarm2 ); // If both alarms are off then, disables the alarm interrupts, enables them otherwise. if ( ( myAlarm1 == CONTROL_STATUS_ALARM1_DISABLED ) && ( myAlarm2 == CONTROL_STATUS_ALARM2_DISABLED ) ) cmd[1] &= ~CONTROL_STATUS_INTERRUPT_CONTROL_MASK; else cmd[1] |= CONTROL_STATUS_INTERRUPT_CONTROL_INT; // Update the register aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_SetSquareWaveOutput ( DS3231_control_status_rate_select_t ) * * @details It enables/disable the square-wave output. * * @param[in] myRate: Square-wave output frequency. * * @param[out] NaN. * * * @return Status of DS3231_SetSquareWaveOutput. * * * @author Manuel Caballero * @date 19/December/2017 * @version 19/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_SetSquareWaveOutput ( DS3231_control_status_rate_select_t myRate ) { char cmd[] = { DS3231_CONTROL, 0 }; uint32_t aux = 0; // Read the Control Register aux = _i2c.write ( _DS3231_Addr, &cmd[0], 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd[1], 1 ); // Parse the data cmd[1] &= ~CONTROL_STATUS_RATE_SELECT_MASK; cmd[1] |= myRate; // Enable the square-wave output. cmd[1] &= ~CONTROL_STATUS_INTERRUPT_CONTROL_MASK; // Update the register aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_GetDate ( DS3231_vector_date_time_t* ) * * @details It gets the date. * * @param[in] myDate: Current Date. * * @param[out] NaN. * * * @return Status of DS3231_GetDate. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_GetDate ( DS3231_vector_date_time_t* myDate ) { char cmd = 0; uint32_t aux = 0; // Read Date Register cmd = DS3231_DATE; aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myDate->Date = _MYBCD_TO_DECIMAL( cmd ); // Read Month Register cmd = DS3231_MONTH_CENTURY; aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myDate->Month = _MYBCD_TO_DECIMAL( cmd & MONTH_MONTH_MASK ); myDate->Century = _MYBCD_TO_DECIMAL( cmd & MONTH_CENTURY_MASK ); // Read Year Register cmd = DS3231_YEAR; aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myDate->Year = _MYBCD_TO_DECIMAL( cmd ); // Read Day of the Week Register cmd = DS3231_DAY; aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myDate->DayOfWeek = _MYBCD_TO_DECIMAL( cmd ); if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_SetDate ( DS3231_vector_date_time_t ) * * @details It sets the date. * * @param[in] myTime: Date to store. * * @param[out] NaN. * * * @return Status of DS3231_SetDate. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_SetDate ( DS3231_vector_date_time_t myDate ) { char cmd[] = { 0, 0 }; uint32_t aux = 0; // Update Date Register cmd[0] = DS3231_DATE; cmd[1] = _MYDECIMAL_TO_BCD( myDate.Date ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); // Update Month Register cmd[0] = DS3231_MONTH_CENTURY; cmd[1] = _MYDECIMAL_TO_BCD( myDate.Month | myDate.Century ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); // Update Year Register cmd[0] = DS3231_YEAR; cmd[1] = _MYDECIMAL_TO_BCD( myDate.Year ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); // Update Day Register cmd[0] = DS3231_DAY; cmd[1] = _MYDECIMAL_TO_BCD( myDate.DayOfWeek ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_GetTime ( DS3231_vector_date_time_t* ) * * @details It gets the time in decimal. * * @param[in] myTime: Current Time. * * @param[out] NaN. * * * @return Status of DS3231_GetTime. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_GetTime ( DS3231_vector_date_time_t* myTime ) { char cmd = 0; uint32_t aux = 0; // Read Hours Register cmd = DS3231_HOURS; aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myTime->Hours = _MYBCD_TO_DECIMAL( ( cmd & ~( HOURS_nAM_PM_MASK | HOURS_12_n24_MASK ) ) ); myTime->Mode_nAM_PM = ( cmd & HOURS_nAM_PM_MASK ); myTime->Mode_12_n24 = ( cmd & HOURS_12_n24_MASK ); // Read Minutes Register cmd = DS3231_MINUTES; aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myTime->Minutes = _MYBCD_TO_DECIMAL( cmd ); // Read Seconds Register cmd = DS3231_SECONDS; aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myTime->Seconds = _MYBCD_TO_DECIMAL( cmd ); if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_SetTime ( DS3231_vector_date_time_t ) * * @details It sets the time in BCD. * * @param[in] myTime: Time to store. * * @param[out] NaN. * * * @return Status of DS3231_SetTime. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_SetTime ( DS3231_vector_date_time_t myTime ) { char cmd[] = { 0, 0 }; uint32_t aux = 0; // Update Hours Register cmd[0] = DS3231_HOURS; cmd[1] = ( _MYDECIMAL_TO_BCD( myTime.Hours ) | myTime.Mode_12_n24 | myTime.Mode_nAM_PM ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); // Update Minutes Register cmd[0] = DS3231_MINUTES; cmd[1] = _MYDECIMAL_TO_BCD( myTime.Minutes ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); // Update Seconds Register cmd[0] = DS3231_SECONDS; cmd[1] = _MYDECIMAL_TO_BCD( myTime.Seconds ); aux = _i2c.write ( _DS3231_Addr, &cmd[0], 2, false ); if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; } /** * @brief DS3231_GetControlStatusRegister ( DS3231_vector_data_t* ) * * @details It gets the Control/Status register. * * @param[in] myControlStatusReg: Current value of the Register. * * @param[out] NaN. * * * @return Status of DS3231_GetControlStatusRegister. * * * @author Manuel Caballero * @date 20/December/2017 * @version 20/December/2017 The ORIGIN * @pre NaN * @warning NaN. */ DS3231::DS3231_status_t DS3231::DS3231_GetControlStatusRegister ( DS3231_vector_data_t* myControlStatusReg ) { char cmd = DS3231_CONTROL_STATUS; uint32_t aux = 0; // Read Control/Status Register aux = _i2c.write ( _DS3231_Addr, &cmd, 1, true ); aux = _i2c.read ( _DS3231_Addr, &cmd, 1 ); myControlStatusReg->Control_Status_Register = cmd; if ( aux == I2C_SUCCESS ) return DS3231_SUCCESS; else return DS3231_FAILURE; }