You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1810 lines
98 KiB
1810 lines
98 KiB
6 months ago
|
/**
|
||
|
* Copyright (c) 2015 - present LibDriver All rights reserved
|
||
|
*
|
||
|
* The MIT License (MIT)
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in all
|
||
|
* copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
* SOFTWARE.
|
||
|
*
|
||
|
* @file driver_ds3231.c
|
||
|
* @brief driver ds3231 source file
|
||
|
* @version 2.0.0
|
||
|
* @author Shifeng Li
|
||
|
* @date 2021-03-15
|
||
|
*
|
||
|
* <h3>history</h3>
|
||
|
* <table>
|
||
|
* <tr><th>Date <th>Version <th>Author <th>Description
|
||
|
* <tr><td>2021/03/15 <td>2.0 <td>Shifeng Li <td>format the code
|
||
|
* <tr><td>2020/11/30 <td>1.0 <td>Shifeng Li <td>first upload
|
||
|
* </table>
|
||
|
*/
|
||
|
|
||
|
#include "driver_ds3231.h"
|
||
|
|
||
|
/**
|
||
|
* @brief chip information definition
|
||
|
*/
|
||
|
#define CHIP_NAME "Maxim Integrated DS3231" /**< chip name */
|
||
|
#define MANUFACTURER_NAME "Maxim Integrated" /**< manufacturer name */
|
||
|
#define SUPPLY_VOLTAGE_MIN 2.3f /**< chip min supply voltage */
|
||
|
#define SUPPLY_VOLTAGE_MAX 5.5f /**< chip max supply voltage */
|
||
|
#define MAX_CURRENT 0.65f /**< chip max current */
|
||
|
#define TEMPERATURE_MIN -40.0f /**< chip min operating temperature */
|
||
|
#define TEMPERATURE_MAX 85.0f /**< chip max operating temperature */
|
||
|
#define DRIVER_VERSION 2000 /**< driver version */
|
||
|
|
||
|
/**
|
||
|
* @brief chip register definition
|
||
|
*/
|
||
|
#define DS3231_REG_SECOND 0x00 /**< second register */
|
||
|
#define DS3231_REG_MINUTE 0x01 /**< minute register */
|
||
|
#define DS3231_REG_HOUR 0x02 /**< hour register */
|
||
|
#define DS3231_REG_WEEK 0x03 /**< week register */
|
||
|
#define DS3231_REG_DATE 0x04 /**< date register */
|
||
|
#define DS3231_REG_MONTH 0x05 /**< month register */
|
||
|
#define DS3231_REG_YEAR 0x06 /**< year register */
|
||
|
#define DS3231_REG_ALARM1_SECOND 0x07 /**< alarm1 second register */
|
||
|
#define DS3231_REG_ALARM1_MINUTE 0x08 /**< alarm1 minute register */
|
||
|
#define DS3231_REG_ALARM1_HOUR 0x09 /**< alarm1 hour register */
|
||
|
#define DS3231_REG_ALARM1_WEEK 0x0A /**< alarm1 week register */
|
||
|
#define DS3231_REG_ALARM2_MINUTE 0x0B /**< alarm2 minute register */
|
||
|
#define DS3231_REG_ALARM2_HOUR 0x0C /**< alarm2 hour register */
|
||
|
#define DS3231_REG_ALARM2_WEEK 0x0D /**< alarm2 week register */
|
||
|
#define DS3231_REG_CONTROL 0x0E /**< control register */
|
||
|
#define DS3231_REG_STATUS 0x0F /**< status register */
|
||
|
#define DS3231_REG_XTAL 0x10 /**< xtal register */
|
||
|
#define DS3231_REG_TEMPERATUREH 0x11 /**< temperature high register */
|
||
|
#define DS3231_REG_TEMPERATUREL 0x12 /**< temperature low register */
|
||
|
|
||
|
/**
|
||
|
* @brief chip address definition
|
||
|
*/
|
||
|
#define DS3231_ADDRESS 0x68 /**< iic device address */
|
||
|
|
||
|
/**
|
||
|
* @brief write one byte
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] reg is the iic register address
|
||
|
* @param[in] data is the write data
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 write failed
|
||
|
* @note none
|
||
|
*/
|
||
|
static uint8_t a_ds3231_iic_write(ds3231_handle_t *handle, uint8_t reg, uint8_t data)
|
||
|
{
|
||
|
if (handle->iic_write(DS3231_ADDRESS, reg, &data, 1) != 0) /* write data */
|
||
|
{
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief read multiple bytes
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] reg is the iic register address
|
||
|
* @param[out] *buf points to a data buffer
|
||
|
* @param[in] len is the data buffer length
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 read failed
|
||
|
* @note none
|
||
|
*/
|
||
|
static uint8_t a_ds3231_iic_multiple_read(ds3231_handle_t *handle, uint8_t reg, uint8_t *buf, uint8_t len)
|
||
|
{
|
||
|
if (handle->iic_read(DS3231_ADDRESS, reg, buf, len) != 0) /* read data */
|
||
|
{
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
else
|
||
|
{ /* success return 0 */
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief hex to bcd
|
||
|
* @param[in] val is the hex data
|
||
|
* @return bcd data
|
||
|
* @note none
|
||
|
*/
|
||
|
static uint8_t a_ds3231_hex2bcd(uint8_t val)
|
||
|
{
|
||
|
uint8_t i, j, k;
|
||
|
|
||
|
i = val / 10; /* get tens place */
|
||
|
j = val % 10; /* get ones place */
|
||
|
k = j + (i << 4); /* set bcd */
|
||
|
|
||
|
return k; /* return bcd */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief bcd to hex
|
||
|
* @param[in] val is the bcd data
|
||
|
* @return hex data
|
||
|
* @note none
|
||
|
*/
|
||
|
static uint8_t a_ds3231_bcd2hex(uint8_t val)
|
||
|
{
|
||
|
uint8_t temp;
|
||
|
|
||
|
temp = val & 0x0F; /* get ones place */
|
||
|
val = (val >> 4) & 0x0F; /* get tens place */
|
||
|
val = val * 10; /* set tens place */
|
||
|
temp = temp + val; /* get hex */
|
||
|
|
||
|
return temp; /* return hex */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief set the current time
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] *t points to a time structure
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set time failed
|
||
|
* - 2 handle or time is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* - 4 time is invalid
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_time(ds3231_handle_t *handle, ds3231_time_t *t)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t reg;
|
||
|
uint8_t century;
|
||
|
uint16_t year;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (t == NULL) /* check time */
|
||
|
{
|
||
|
handle->debug_print("ds3231: time is null.\n"); /* time is null */
|
||
|
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
if ((t->year < 1990) || (t->year > 2190)) /* check year */
|
||
|
{
|
||
|
handle->debug_print("ds3231: year can't be over 2190 or less than 1990.\n"); /* year can't be over 2190 or less than 1990 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if ((t->month == 0) || (t->month > 12)) /* check month */
|
||
|
{
|
||
|
handle->debug_print("ds3231: month can't be zero or over than 12.\n"); /* month can't be zero or over than 12 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if ((t->week == 0) || (t->week > 7)) /* check week */
|
||
|
{
|
||
|
handle->debug_print("ds3231: week can't be zero or over than 7.\n"); /* week can't be zero or over than 7 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if ((t->date == 0) || (t->date > 31)) /* check data */
|
||
|
{
|
||
|
handle->debug_print("ds3231: date can't be zero or over than 31.\n"); /* date can't be zero or over than 31 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if ((t->hour < 1) || (t->hour > 12)) /* check hour */
|
||
|
{
|
||
|
handle->debug_print("ds3231: hour can't be over than 12 or less 1.\n"); /* hour can't be over than 12 or less 1 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if (t->minute > 59) /* check minute */
|
||
|
{
|
||
|
handle->debug_print("ds3231: minute can't be over than 59.\n"); /* minute can't be over than 59 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if (t->second > 59) /* check second */
|
||
|
{
|
||
|
handle->debug_print("ds3231: second can't be over than 59.\n"); /* second can't be over than 59 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
}
|
||
|
else if (t->format == DS3231_FORMAT_24H) /* if 24H */
|
||
|
{
|
||
|
if ((t->year < 1990) || (t->year > 2190)) /* check year */
|
||
|
{
|
||
|
handle->debug_print("ds3231: year can't be over 2190 or less than 1990.\n"); /* year can't be over 2190 or less than 1990 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if ((t->month == 0) || (t->month > 12)) /* check month */
|
||
|
{
|
||
|
handle->debug_print("ds3231: month can't be zero or over than 12.\n"); /* month can't be zero or over than 12 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if ((t->week == 0) || (t->week > 7)) /* check week */
|
||
|
{
|
||
|
handle->debug_print("ds3231: week can't be zero or over than 7.\n"); /* week can't be zero or over than 7 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if ((t->date == 0) || (t->date > 31)) /* check data */
|
||
|
{
|
||
|
handle->debug_print("ds3231: date can't be zero or over than 31.\n"); /* date can't be zero or over than 31 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if (t->hour > 23) /* check hour */
|
||
|
{
|
||
|
handle->debug_print("ds3231: hour can't be over than 23.\n"); /* hour can't be over than 23 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if (t->minute > 59) /* check minute */
|
||
|
{
|
||
|
handle->debug_print("ds3231: minute can't be over than 59.\n"); /* minute can't be over than 59 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
if (t->second > 59) /* check second */
|
||
|
{
|
||
|
handle->debug_print("ds3231: second can't be over than 59.\n"); /* second can't be over than 59 */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
handle->debug_print("ds3231: format is invalid.\n"); /* format is invalid */
|
||
|
|
||
|
return 4; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_SECOND, a_ds3231_hex2bcd(t->second)); /* write second */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write second failed.\n"); /* write second failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_MINUTE, a_ds3231_hex2bcd(t->minute)); /* write minute */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write minute failed.\n"); /* write minute failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
reg = (uint8_t)((1 << 6) | (t->am_pm << 5) | a_ds3231_hex2bcd(t->hour)); /* set hour in 12H */
|
||
|
}
|
||
|
else /* if 24H */
|
||
|
{
|
||
|
reg = (0 << 6) | a_ds3231_hex2bcd(t->hour); /* set hour in 24H */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_HOUR, reg); /* write hour */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write hour failed.\n"); /* write hour failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_WEEK, a_ds3231_hex2bcd(t->week)); /* write week */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write week failed.\n"); /* write week failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_DATE, a_ds3231_hex2bcd(t->date)); /* write data */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write date failed.\n"); /* write date failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
year = t->year - 1990; /* year -1990 */
|
||
|
if (year >= 100) /* check year */
|
||
|
{
|
||
|
century = 1; /* set century */
|
||
|
year -= 100; /* year -= 100 */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
century = 0; /* set century 0 */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_MONTH, a_ds3231_hex2bcd(t->month) | (century << 7)); /* write month and century */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write century and month failed.\n"); /* write century and month failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_YEAR, a_ds3231_hex2bcd((uint8_t)year)); /* write year */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write year failed.\n"); /* write year failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the current time
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *t points to a time structure
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get time failed
|
||
|
* - 2 handle or time is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_time(ds3231_handle_t *handle, ds3231_time_t *t)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t buf[7];
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (t == NULL) /* check time */
|
||
|
{
|
||
|
handle->debug_print("ds3231: time is null.\n"); /* time is null */
|
||
|
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
|
||
|
memset(buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_SECOND, (uint8_t *)buf, 7); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: multiple read failed.\n"); /* multiple read failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
t->year = a_ds3231_bcd2hex(buf[6]) + 1990 + ((buf[5] >> 7) & 0x01) * 100; /* get year */
|
||
|
t->month = a_ds3231_bcd2hex(buf[5]&0x1F); /* get month */
|
||
|
t->week = a_ds3231_bcd2hex(buf[3]); /* get week */
|
||
|
t->date = a_ds3231_bcd2hex(buf[4]); /* get date */
|
||
|
t->am_pm = (ds3231_am_pm_t)((buf[2] >> 5) & 0x01); /* get am pm */
|
||
|
t->format = (ds3231_format_t)((buf[2] >> 6) & 0x01); /* get format */
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
t->hour = a_ds3231_bcd2hex(buf[2] & 0x1F); /* get hour */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
t->hour = a_ds3231_bcd2hex(buf[2] & 0x3F); /* get hour */
|
||
|
}
|
||
|
t->minute = a_ds3231_bcd2hex(buf[1]); /* get minute */
|
||
|
t->second = a_ds3231_bcd2hex(buf[0]); /* get second */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief set the alarm1 time
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] *t points to a time structure
|
||
|
* @param[in] mode is the alarm1 interrupt mode
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set alarm1 failed
|
||
|
* - 2 handle or time is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_alarm1(ds3231_handle_t *handle, ds3231_time_t *t, ds3231_alarm1_mode_t mode)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t reg;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (t == NULL) /* check time */
|
||
|
{
|
||
|
handle->debug_print("ds3231: time is null.\n"); /* time is null */
|
||
|
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
if ((t->week == 0) || (t->week > 7)) /* check week */
|
||
|
{
|
||
|
handle->debug_print("ds3231: week can't be zero or over than 7.\n"); /* week can't be zero or over than 7 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if ((t->date == 0) || (t->date > 31)) /* check data */
|
||
|
{
|
||
|
handle->debug_print("ds3231: date can't be zero or over than 31.\n"); /* date can't be zero or over than 31 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if ((t->hour < 1) || (t->hour > 12)) /* check hour */
|
||
|
{
|
||
|
handle->debug_print("ds3231: hour can't be over than 12 or less 1.\n"); /* hour can't be over than 12 or less 1 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->minute > 59) /* check minute */
|
||
|
{
|
||
|
handle->debug_print("ds3231: minute can't be over than 59.\n"); /* minute can't be over than 59 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->second > 59) /* check second */
|
||
|
{
|
||
|
handle->debug_print("ds3231: second can't be over than 59.\n"); /* second can't be over than 59 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
}
|
||
|
else if (t->format == DS3231_FORMAT_24H) /* if 24H */
|
||
|
{
|
||
|
if ((t->week == 0) || (t->week > 7)) /* check week */
|
||
|
{
|
||
|
handle->debug_print("ds3231: week can't be zero or over than 7.\n"); /* week can't be zero or over than 7 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if ((t->date == 0) || (t->date > 31)) /* check data */
|
||
|
{
|
||
|
handle->debug_print("ds3231: date can't be zero or over than 31.\n"); /* date can't be zero or over than 31 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->hour > 23) /* check hour */
|
||
|
{
|
||
|
handle->debug_print("ds3231: hour can't be over than 23.\n"); /* hour can't be over than 23 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->minute > 59) /* check minute */
|
||
|
{
|
||
|
handle->debug_print("ds3231: minute can't be over than 59.\n"); /* minute can't be over than 59 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->second > 59) /* check second */
|
||
|
{
|
||
|
handle->debug_print("ds3231: second can't be over than 59.\n"); /* second can't be over than 59 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
handle->debug_print("ds3231: format is invalid.\n"); /* format is invalid */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_ALARM1_SECOND, a_ds3231_hex2bcd(t->second) | ((mode & 0x01) << 7)); /* write second */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write alarm1 second failed.\n"); /* write alarm1 second failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_ALARM1_MINUTE, a_ds3231_hex2bcd(t->minute) | (((mode >> 1) & 0x01) << 7)); /* write minute */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write alarm1 minute failed.\n"); /* write alarm1 minute failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
reg = (uint8_t)((((mode >> 2) & 0x01) << 7) | (1 << 6) | (t->am_pm << 5) | a_ds3231_hex2bcd(t->hour)); /* set hour in 12H */
|
||
|
}
|
||
|
else /* if 24H */
|
||
|
{
|
||
|
reg = (((mode >> 2) & 0x01) << 7) | a_ds3231_hex2bcd(t->hour); /* set hour in 24H */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_ALARM1_HOUR, reg); /* write hour */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write alarm1 hour failed.\n"); /* write alarm1 hour failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (mode >= DS3231_ALARM1_MODE_WEEK_HOUR_MINUTE_SECOND_MATCH) /* if week */
|
||
|
{
|
||
|
reg = (((mode >> 3) & 0x01) << 7) | (1 << 6) | a_ds3231_hex2bcd(t->week); /* set data in week */
|
||
|
}
|
||
|
else /* if day */
|
||
|
{
|
||
|
reg = (((mode >> 3) & 0x01) << 7) | a_ds3231_hex2bcd(t->date); /* set data in date */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_ALARM1_WEEK, reg); /* write week */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write alarm1 week failed.\n"); /* write alarm1 week failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the alarm1 time
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *t points to a time structure
|
||
|
* @param[out] *mode points to an alarm1 interrupt mode buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get alarm1 failed
|
||
|
* - 2 handle or time is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_alarm1(ds3231_handle_t *handle, ds3231_time_t *t, ds3231_alarm1_mode_t *mode)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t buf[4];
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (t == NULL) /* check time */
|
||
|
{
|
||
|
handle->debug_print("ds3231: time is null.\n"); /* time is null */
|
||
|
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
|
||
|
memset(buf, 0, sizeof(uint8_t) * 4); /* clear the buffer */
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_ALARM1_SECOND, (uint8_t *)buf, 4); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: multiple read failed.\n"); /* multiple read failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
t->year = 0; /* get year */
|
||
|
t->month = 0; /* get month */
|
||
|
if (((buf[3] >> 6) & 0x01) != 0) /* if week */
|
||
|
{
|
||
|
t->week = a_ds3231_bcd2hex(buf[3] & 0x0F); /* get week */
|
||
|
t->date = 0; /* get data */
|
||
|
}
|
||
|
else /* if data */
|
||
|
{
|
||
|
t->week = 0; /* get week */
|
||
|
t->date = a_ds3231_bcd2hex(buf[3] & 0x3F); /* get data */
|
||
|
}
|
||
|
t->am_pm = (ds3231_am_pm_t)((buf[2] >> 5) & 0x01); /* get am pm */
|
||
|
t->format = (ds3231_format_t)((buf[2] >> 6) & 0x01); /* get format */
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
t->hour = a_ds3231_bcd2hex(buf[2]&0x1F); /* get hour */
|
||
|
}
|
||
|
else /* if 24H */
|
||
|
{
|
||
|
t->hour = a_ds3231_bcd2hex(buf[2]&0x3F); /* get hour */
|
||
|
}
|
||
|
t->minute = a_ds3231_bcd2hex(buf[1] & 0x7F); /* get minute */
|
||
|
t->second = a_ds3231_bcd2hex(buf[0] & 0x7F); /* get second */
|
||
|
*mode = (ds3231_alarm1_mode_t)(((buf[0]>>7)&0x01)<<0 | ((buf[1]>>7)&0x01)<<1 | ((buf[2]>>7)&0x01)<<2 | ((buf[3]>>7)&0x01)<<3 |
|
||
|
((buf[3] >> 6)&0x01)<<4
|
||
|
); /* get mode */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief set the alarm2 time
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] *t points to a time structure
|
||
|
* @param[in] mode is the alarm2 interrupt mode
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set alarm2 failed
|
||
|
* - 2 handle or time is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_alarm2(ds3231_handle_t *handle, ds3231_time_t *t, ds3231_alarm2_mode_t mode)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t reg;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (t == NULL) /* check time */
|
||
|
{
|
||
|
handle->debug_print("ds3231: time is null.\n"); /* time is null */
|
||
|
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
if ((t->week == 0) || (t->week > 7)) /* check week */
|
||
|
{
|
||
|
handle->debug_print("ds3231: week can't be zero or over than 7.\n"); /* week can't be zero or over than 7 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if ((t->date == 0) || (t->date > 31)) /* check data */
|
||
|
{
|
||
|
handle->debug_print("ds3231: date can't be zero or over than 31.\n"); /* date can't be zero or over than 31 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if ((t->hour < 1) || (t->hour > 12)) /* check hour */
|
||
|
{
|
||
|
handle->debug_print("ds3231: hour can't be over than 12 or less 1.\n"); /* hour can't be over than 12 or less 1 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->minute > 59) /* check minute */
|
||
|
{
|
||
|
handle->debug_print("ds3231: minute can't be over than 59.\n"); /* minute can't be over than 59 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
}
|
||
|
else if (t->format == DS3231_FORMAT_24H) /* if 24H */
|
||
|
{
|
||
|
if ((t->week == 0) || (t->week > 7)) /* check week */
|
||
|
{
|
||
|
handle->debug_print("ds3231: week can't be zero or over than 7.\n"); /* week can't be zero or over than 7 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if ((t->date == 0) || (t->date > 31)) /* check data */
|
||
|
{
|
||
|
handle->debug_print("ds3231: date can't be zero or over than 31.\n"); /* date can't be zero or over than 31 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->hour > 23) /* check hour */
|
||
|
{
|
||
|
handle->debug_print("ds3231: hour can't be over than 23.\n"); /* hour can't be over than 23 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->minute > 59) /* check minute */
|
||
|
{
|
||
|
handle->debug_print("ds3231: minute can't be over than 59.\n"); /* minute can't be over than 59 */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
handle->debug_print("ds3231: format is invalid.\n"); /* format is invalid */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_ALARM2_MINUTE, a_ds3231_hex2bcd(t->minute) | (((mode >> 0) & 0x01) << 7)); /* write minute */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write alarm2 minute failed.\n"); /* write alarm2 minute failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
reg = (uint8_t)((((mode >> 1) & 0x01) << 7) | (1 << 6) | (t->am_pm << 5) | a_ds3231_hex2bcd(t->hour)); /* set hour in 12H */
|
||
|
}
|
||
|
else /* if 24H */
|
||
|
{
|
||
|
reg = (((mode >> 1) & 0x01) << 7) | a_ds3231_hex2bcd(t->hour); /* set hour in 24H */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_ALARM2_HOUR, reg); /* write hour */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write alarm2 hour failed.\n"); /* write alarm2 hour failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (mode >= (uint8_t)DS3231_ALARM1_MODE_WEEK_HOUR_MINUTE_SECOND_MATCH) /* if week */
|
||
|
{
|
||
|
reg = (((mode >> 2) & 0x01) << 7) | (1 << 6) | a_ds3231_hex2bcd(t->week); /* set data in week */
|
||
|
}
|
||
|
else /* if day */
|
||
|
{
|
||
|
reg = (((mode >> 2) & 0x01) << 7) | a_ds3231_hex2bcd(t->date); /* set data in date */
|
||
|
}
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_ALARM2_WEEK, reg); /* write week */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write alarm2 week failed.\n"); /* write alarm2 week failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the alarm2 time
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *t points to a time structure
|
||
|
* @param[out] *mode points to an alarm2 interrupt mode buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get alarm2 failed
|
||
|
* - 2 handle or time is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_alarm2(ds3231_handle_t *handle, ds3231_time_t *t, ds3231_alarm2_mode_t *mode)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t buf[3];
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (t == NULL) /* check time */
|
||
|
{
|
||
|
handle->debug_print("ds3231: time is null.\n"); /* time is null */
|
||
|
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
|
||
|
memset(buf, 0, sizeof(uint8_t) * 3); /* clear the buffer */
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_ALARM2_MINUTE, (uint8_t *)buf, 3); /* multiple read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: multiple read failed.\n"); /* multiple read failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
t->year = 0; /* get year */
|
||
|
t->month = 0; /* get month */
|
||
|
if (((buf[2] >> 6) & 0x01) != 0) /* if week */
|
||
|
{
|
||
|
t->week = a_ds3231_bcd2hex(buf[2] & 0x0F); /* get week */
|
||
|
t->date = 0; /* get data */
|
||
|
}
|
||
|
else /* if data */
|
||
|
{
|
||
|
t->week = 0; /* get week */
|
||
|
t->date = a_ds3231_bcd2hex(buf[2] & 0x3F); /* get data */
|
||
|
}
|
||
|
t->am_pm = (ds3231_am_pm_t)((buf[1] >> 5) & 0x01); /* get am pm */
|
||
|
t->format = (ds3231_format_t)((buf[1] >> 6) & 0x01); /* get format */
|
||
|
if (t->format == DS3231_FORMAT_12H) /* if 12H */
|
||
|
{
|
||
|
t->hour = a_ds3231_bcd2hex(buf[1]&0x1F); /* get hour */
|
||
|
}
|
||
|
else /* if 24H */
|
||
|
{
|
||
|
t->hour = a_ds3231_bcd2hex(buf[1]&0x3F); /* get hour */
|
||
|
}
|
||
|
t->minute = a_ds3231_bcd2hex(buf[0] & 0x7F); /* get minute */
|
||
|
t->second = 0; /* get second */
|
||
|
*mode = (ds3231_alarm2_mode_t)(((buf[0]>>7)&0x01)<<0 | ((buf[1]>>7)&0x01)<<1 | ((buf[2]>>7)&0x01)<<2 | ((buf[2]>>6)&0x01)<<4); /* get mode */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief enable or disable the oscillator
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] enable is a bool value
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set oscillator failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_oscillator(ds3231_handle_t *handle, ds3231_bool_t enable)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
prev &= ~ (1 << 7); /* clear config */
|
||
|
prev |= (!enable) << 7; /* set enable */
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_CONTROL, prev); /* write control */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write control failed.\n"); /* write control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the chip oscillator status
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *enable points to a bool value buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get oscillator failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_oscillator(ds3231_handle_t *handle, ds3231_bool_t *enable)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
*enable = (ds3231_bool_t)(!((prev >> 7) & 0x01)); /* get enable */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief enable or disable the alarm interrupt
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] alarm is the alarm number
|
||
|
* @param[in] enable is a bool value
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set alarm interrupt failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_alarm_interrupt(ds3231_handle_t *handle, ds3231_alarm_t alarm, ds3231_bool_t enable)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
prev &= ~(1 << alarm); /* clear config */
|
||
|
prev |= enable << alarm; /* set enable */
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_CONTROL, prev); /* write control */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write control failed.\n"); /* write control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the alarm interrupt status
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] alarm is the alarm number
|
||
|
* @param[out] *enable points to a bool value buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get alarm interrupt failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_alarm_interrupt(ds3231_handle_t *handle, ds3231_alarm_t alarm, ds3231_bool_t *enable)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
*enable = (ds3231_bool_t)((prev >> alarm) & 0x01); /* get enable */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief set the chip pin function
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] pin is the pin's function
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set pin failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_pin(ds3231_handle_t *handle, ds3231_pin_t pin)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
prev &= ~(1 << 2); /* clear config */
|
||
|
prev |= pin << 2; /* set pin */
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_CONTROL, prev); /* write control */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write control failed.\n"); /* write control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the chip pin function
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *pin points to a pin's function buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get pin failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_pin(ds3231_handle_t *handle, ds3231_pin_t *pin)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
*pin = (ds3231_pin_t)((prev >> 2) & 0x01); /* get pin */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief enable or disable the square wave output
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] enable is a bool value
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set square wave failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_square_wave(ds3231_handle_t *handle, ds3231_bool_t enable)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
prev &= ~(1 << 6); /* clear config */
|
||
|
prev |= enable << 6; /* set enable */
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_CONTROL, prev); /* write control */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write control failed.\n"); /* write control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the square wave output status
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *enable points to a bool value buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get square wave failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_square_wave(ds3231_handle_t *handle, ds3231_bool_t *enable)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
*enable = (ds3231_bool_t)((prev >> 6) & 0x01); /* get enable */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the chip temperature
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *raw points to a raw temperature buffer
|
||
|
* @param[out] *s points to a converted temperature buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get temperature failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_temperature(ds3231_handle_t *handle, int16_t *raw, float *s)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
uint32_t times;
|
||
|
uint8_t buf[2];
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
memset(buf, 0, sizeof(uint8_t) * 2); /* clear the buffer */
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_CONTROL, (uint8_t *)&prev, 1); /* multiple read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read control failed.\n"); /* read control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
prev &= ~(1 << 5); /* clear config */
|
||
|
prev |= 1 << 5; /* set enable */
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_CONTROL, prev); /* write control */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write control failed.\n"); /* write control failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
times = 500; /* set 5s */
|
||
|
while (times != 0) /* check times */
|
||
|
{
|
||
|
handle->delay_ms(10); /* delay 10 ms */
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_STATUS, (uint8_t *)&prev, 1); /* read status */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read status failed.\n"); /* read status failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
if (((prev >> 2) & 0x01) == 0) /* check result */
|
||
|
{
|
||
|
break; /* break */
|
||
|
}
|
||
|
times--; /* times-- */
|
||
|
}
|
||
|
if (times == 0) /* if zero */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read timeout.\n"); /* read timeout */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_TEMPERATUREH, (uint8_t *)buf, 2); /* read temperature */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read temperature failed.\n"); /* read temperature failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
*raw = (int16_t)(((uint16_t)buf[0]) << 8) | buf[1]; /* set raw temperature */
|
||
|
*raw = (*raw) >> 6; /* right shift */
|
||
|
if (((*raw) & 0x0200) != 0) /* set negative value */
|
||
|
{
|
||
|
*raw = (*raw) | 0xFC00U; /* set negative part */
|
||
|
}
|
||
|
*s = (float)(*raw) * 0.25f; /* set converted temperature */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the chip status
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *status points to a chip status buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get status failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_status(ds3231_handle_t *handle, uint8_t *status)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_STATUS, (uint8_t *)status, 1); /* multiple read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read status failed.\n"); /* read status failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief set the chip aging offset
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] offset is time aging offset
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set aging offset failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_aging_offset(ds3231_handle_t *handle, int8_t offset)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_XTAL, offset); /* write offset */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write offset failed.\n"); /* write offset failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the chip aging offset
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *offset points to a time aging offset buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get aging offset failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_aging_offset(ds3231_handle_t *handle, int8_t *offset)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_XTAL, (uint8_t *)offset, 1); /* read offset */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read offset failed.\n"); /* read offset failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief convert a aging offset value to a register raw data
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] offset is a converted aging offset value
|
||
|
* @param[out] *reg points to a register raw buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_aging_offset_convert_to_register(ds3231_handle_t *handle, float offset, int8_t *reg)
|
||
|
{
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
*reg = (int8_t)(offset / 0.12f); /* convert real data to register data */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief convert a register raw data to a converted aging offset data
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] reg is the register raw data
|
||
|
* @param[out] *offset points to a converted aging offset buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_aging_offset_convert_to_data(ds3231_handle_t *handle, int8_t reg, float *offset)
|
||
|
{
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
*offset = (float)(reg) * 0.12f; /* convert raw data to real data */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief irq handler
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 run failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_irq_handler(ds3231_handle_t *handle)
|
||
|
{
|
||
|
uint8_t res, prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_STATUS, (uint8_t *)&prev, 1); /* multiple read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read status failed.\n"); /* read status failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
} /* if oscillator stop */
|
||
|
if ((prev & DS3231_STATUS_ALARM_2) != 0) /* if alarm 2 */
|
||
|
{
|
||
|
if (handle->receive_callback != NULL) /* if receive callback */
|
||
|
{
|
||
|
handle->receive_callback(DS3231_STATUS_ALARM_2); /* run callback */
|
||
|
}
|
||
|
}
|
||
|
if ((prev & DS3231_STATUS_ALARM_1) != 0) /* if alarm 1 */
|
||
|
{
|
||
|
if (handle->receive_callback != NULL) /* if receive callback */
|
||
|
{
|
||
|
handle->receive_callback(DS3231_STATUS_ALARM_1); /* run callback */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief initialize the chip
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 iic initialization failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 linked functions is NULL
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_init(ds3231_handle_t *handle)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->debug_print == NULL) /* check debug_print */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (handle->iic_init == NULL) /* check iic_init */
|
||
|
{
|
||
|
handle->debug_print("ds3231: iic_init is null.\n"); /* iic_init is null */
|
||
|
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (handle->iic_deinit == NULL) /* check iic_deinit */
|
||
|
{
|
||
|
handle->debug_print("ds3231: iic_deinit is null.\n"); /* iic_deinit is null */
|
||
|
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (handle->iic_write == NULL) /* check iic_write */
|
||
|
{
|
||
|
handle->debug_print("ds3231: iic_write is null.\n"); /* iic_write is null */
|
||
|
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (handle->iic_read == NULL) /* check iic_read */
|
||
|
{
|
||
|
handle->debug_print("ds3231: iic_read is null.\n"); /* iic_read is null */
|
||
|
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (handle->delay_ms == NULL) /* check delay_ms */
|
||
|
{
|
||
|
handle->debug_print("ds3231: delay_ms is null.\n"); /* delay_ms is null */
|
||
|
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
if (handle->receive_callback == NULL) /* check receive_callback */
|
||
|
{
|
||
|
handle->debug_print("ds3231: receive_callback is null.\n"); /* receive_callback is null */
|
||
|
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
if (handle->iic_init() != 0) /* iic init */
|
||
|
{
|
||
|
handle->debug_print("ds3231: iic init failed.\n"); /* iic init failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_STATUS, (uint8_t *)&prev, 1); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read status failed.\n"); /* read status failed */
|
||
|
(void)handle->iic_deinit(); /* iic deinit */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
prev &= ~(1 << 7); /* clear config */
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_STATUS, prev); /* write status */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write status failed.\n"); /* write status failed */
|
||
|
(void)handle->iic_deinit(); /* iic deinit */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
handle->inited = 1; /* flag finish initialization */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief close the chip
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 iic deinit failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_deinit(ds3231_handle_t *handle)
|
||
|
{
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
if (handle->iic_deinit() != 0) /* iic deinit */
|
||
|
{
|
||
|
handle->debug_print("ds3231: iic deinit failed.\n"); /* iic deinit failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
handle->inited = 0; /* flag close */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief clear the alarm flag
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] alarm is the alarm number
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 alarm clear failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_alarm_clear(ds3231_handle_t *handle, ds3231_alarm_t alarm)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_STATUS, (uint8_t *)&prev, 1); /* multiple_read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read status failed.\n"); /* read status failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
prev &= ~(1 << alarm); /* clear config */
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_STATUS, prev); /* write status */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write status failed.\n"); /* write status failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief enable or disable the 32KHz output
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] enable is a bool value
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 set 32khz output failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_32khz_output(ds3231_handle_t *handle, ds3231_bool_t enable)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_STATUS, (uint8_t *)&prev, 1); /* multiple read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read status failed.\n"); /* read status failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
prev &= ~(1 << 3); /* clear config */
|
||
|
prev |= enable << 3; /* set enable */
|
||
|
res = a_ds3231_iic_write(handle, DS3231_REG_STATUS, prev); /* write status */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: write status failed.\n"); /* write status failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the 32KHz output status
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[out] *enable points to a bool value buffer
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 get 32khz output failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_32khz_output(ds3231_handle_t *handle, ds3231_bool_t *enable)
|
||
|
{
|
||
|
uint8_t res;
|
||
|
uint8_t prev;
|
||
|
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
res = a_ds3231_iic_multiple_read(handle, DS3231_REG_STATUS, (uint8_t *)&prev, 1); /* multiple read */
|
||
|
if (res != 0) /* check result */
|
||
|
{
|
||
|
handle->debug_print("ds3231: read status failed.\n"); /* read status failed */
|
||
|
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
*enable = (ds3231_bool_t)((prev >> 3) & 0x01); /* get enable */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief set the chip register
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] reg is the iic register address
|
||
|
* @param[in] *buf points to a data buffer
|
||
|
* @param[in] len is the data buffer length
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 write failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_set_reg(ds3231_handle_t *handle, uint8_t reg, uint8_t *buf, uint16_t len)
|
||
|
{
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
if (handle->iic_write(DS3231_ADDRESS, reg, buf, len) != 0) /* write data */
|
||
|
{
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get the chip register
|
||
|
* @param[in] *handle points to a ds3231 handle structure
|
||
|
* @param[in] reg is the iic register address
|
||
|
* @param[out] *buf points to a data buffer
|
||
|
* @param[in] len is the data buffer length
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 1 read failed
|
||
|
* - 2 handle is NULL
|
||
|
* - 3 handle is not initialized
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_get_reg(ds3231_handle_t *handle, uint8_t reg, uint8_t *buf, uint16_t len)
|
||
|
{
|
||
|
if (handle == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
if (handle->inited != 1) /* check handle initialization */
|
||
|
{
|
||
|
return 3; /* return error */
|
||
|
}
|
||
|
|
||
|
if (handle->iic_read(DS3231_ADDRESS, reg, buf, len) != 0) /* read data */
|
||
|
{
|
||
|
return 1; /* return error */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0; /* success return 0 */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief get chip's information
|
||
|
* @param[out] *info points to a ds3231 info structure
|
||
|
* @return status code
|
||
|
* - 0 success
|
||
|
* - 2 handle is NULL
|
||
|
* @note none
|
||
|
*/
|
||
|
uint8_t ds3231_info(ds3231_info_t *info)
|
||
|
{
|
||
|
if (info == NULL) /* check handle */
|
||
|
{
|
||
|
return 2; /* return error */
|
||
|
}
|
||
|
|
||
|
memset(info, 0, sizeof(ds3231_info_t)); /* initialize ds3231 info structure */
|
||
|
strncpy(info->chip_name, CHIP_NAME, 32); /* copy chip name */
|
||
|
strncpy(info->manufacturer_name, MANUFACTURER_NAME, 32); /* copy manufacturer name */
|
||
|
strncpy(info->interface, "IIC", 8); /* copy interface name */
|
||
|
info->supply_voltage_min_v = SUPPLY_VOLTAGE_MIN; /* set minimal supply voltage */
|
||
|
info->supply_voltage_max_v = SUPPLY_VOLTAGE_MAX; /* set maximum supply voltage */
|
||
|
info->max_current_ma = MAX_CURRENT; /* set maximum current */
|
||
|
info->temperature_max = TEMPERATURE_MAX; /* set minimal temperature */
|
||
|
info->temperature_min = TEMPERATURE_MIN; /* set maximum temperature */
|
||
|
info->driver_version = DRIVER_VERSION; /* set driver version */
|
||
|
|
||
|
return 0; /* success return 0 */
|
||
|
}
|