refactor: update ds3231 demo

This commit is contained in:
IOsetting 2022-07-10 18:27:01 +08:00
parent 97ce5370d3
commit 7debda1b0a
3 changed files with 372 additions and 105 deletions

View File

@ -13,89 +13,343 @@
// limitations under the License.
#include "ds3231.h"
#include "string.h"
__XDATA uint8_t buff[7];
uint8_t DS3231_Write(uint8_t reg, uint8_t dat)
{
return I2C_Write(DS3231_I2C_ADDR, reg, &dat, 1);
}
uint8_t DS3231_MultipleRead(uint8_t reg, uint8_t *buf, uint8_t len)
{
return I2C_Read(DS3231_I2C_ADDR, reg, buf, len);
}
uint8_t DS3231_Hex2Bcd(uint8_t hex)
{
uint8_t i, j, k;
i = hex / 10; /* get tens place */
j = hex % 10; /* get ones place */
k = j + (i << 4); /* set bcd */
return k; /* return bcd */
return (hex % 10) + ((hex / 10) << 4);
}
uint8_t DS3231_Bcd2Hex(uint8_t val)
uint8_t DS3231_Bcd2Hex(uint8_t bcd)
{
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 */
return (bcd >> 4) * 10 + (bcd & 0x0F);
}
uint8_t DS3231_Init(void)
uint8_t DS3231_GetStatus(void)
{
I2C_Read(DS3231_I2C_ADDR, DS3231_REG_STATUS, buff, 1);
return buff[0];
}
uint8_t DS3231_GetTime(uint8_t *t)
{
uint8_t res;
uint8_t prev;
res = DS3231_MultipleRead(DS3231_REG_STATUS, (uint8_t *)&prev, 1); /* multiple_read */
if (res != HAL_OK) /* check result */
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_SECOND, buff, 7);
if (res != HAL_OK)
{
return res;
}
prev &= ~(1 << 7); /* clear config */
res = DS3231_Write(DS3231_REG_STATUS, prev); /* write status */
if (res != HAL_OK) /* check result */
t[0] = DS3231_Bcd2Hex(buff[6]) + ((buff[5] >> 7) & 0x01) * 100; // year
t[1] = DS3231_Bcd2Hex(buff[5] & 0x1F); // month
t[2] = DS3231_Bcd2Hex(buff[3]); // week
t[3] = DS3231_Bcd2Hex(buff[4]); // date
t[7] = (buff[2] >> 6) & 0x01; // 12h/24h
t[8] = (buff[2] >> 5) & 0x01; // am/pm
if (t[7] == DS3231_FORMAT_12H)
{
return res;
}
return HAL_OK;
}
uint8_t DS3231_ReadAll(uint8_t *buf)
{
return DS3231_MultipleRead(DS3231_REG_SECOND, buf, 19);
}
uint8_t DS3231_GetTime(DS3231_Time_t *t)
{
uint8_t res;
uint8_t buf[7];
memset(buf, 0, sizeof(uint8_t) * 7); /* clear the buffer */
res = DS3231_MultipleRead(DS3231_REG_SECOND, (uint8_t *)buf, 7); /* multiple_read */
if (res != HAL_OK) /* check result */
{
return res; /* return error */
}
t->year = DS3231_Bcd2Hex(buf[6]) + 1990 + ((buf[5] >> 7) & 0x01) * 100; /* get year */
t->month = DS3231_Bcd2Hex(buf[5]&0x1F); /* get month */
t->week = DS3231_Bcd2Hex(buf[3]); /* get week */
t->date = DS3231_Bcd2Hex(buf[4]); /* get date */
t->am_pm = (DS3231_AmPm_t)((buf[2] >> 5) & 0x01); /* get am pm */
t->format = (DS3231_HourFormat_t)((buf[2] >> 6) & 0x01); /* get format */
if (t->format == DS3231_FORMAT_12H) /* if 12H */
{
t->hour = DS3231_Bcd2Hex(buf[2] & 0x1F); /* get hour */
t[4] = DS3231_Bcd2Hex(buff[2] & 0x1F); // hour
}
else
{
t->hour = DS3231_Bcd2Hex(buf[2] & 0x3F); /* get hour */
t[4] = DS3231_Bcd2Hex(buff[2] & 0x3F); // hour
}
t->minute = DS3231_Bcd2Hex(buf[1]); /* get minute */
t->second = DS3231_Bcd2Hex(buf[0]); /* get second */
return HAL_OK; /* success return 0 */
t[5] = DS3231_Bcd2Hex(buff[1]); // minute
t[6] = DS3231_Bcd2Hex(buff[0]); // second
return HAL_OK;
}
/**
uint8_t year;
uint8_t month;
uint8_t week;
uint8_t date;
uint8_t hour;
uint8_t minute;
uint8_t second;
DS3231_HourFormat_t format;
DS3231_AmPm_t am_pm;
*/
uint8_t DS3231_SetTime(uint8_t *t)
{
uint8_t res, reg;
// Time validation
if (t[0] > 200) t[0] = 200; // year
if (t[1] == 0) t[1] = 1; // month
else if (t[1] > 12) t[1] = 12;
if (t[2] == 0) t[2] = 1; // week
else if (t[2] > 7) t[2] = 7;
if (t[3] == 0) t[3] = 1; // date
else if (t[3] > 31) t[3] = 31;
if (t[7] == DS3231_FORMAT_12H)
{
if (t[4] > 12) t[4] = 12; // hour
}
else if (t[7] == DS3231_FORMAT_24H)
{
if (t[4] > 23) t[4] = 23; // hour
}
if (t[5] > 59) t[5] = 59; // minute
if (t[6] > 59) t[6] = 59; // second
res = DS3231_Write(DS3231_REG_SECOND, DS3231_Hex2Bcd(t[6]));
if (res != HAL_OK) return res;
res = DS3231_Write(DS3231_REG_MINUTE, DS3231_Hex2Bcd(t[5]));
if (res != HAL_OK) return res;
if (t[7] == DS3231_FORMAT_12H)
{
reg = (uint8_t)((1 << 6) | (t[8] << 5) | DS3231_Hex2Bcd(t[4]));
}
else
{
reg = (0 << 6) | DS3231_Hex2Bcd(t[4]);
}
res = DS3231_Write(DS3231_REG_HOUR, reg);
if (res != HAL_OK) return res;
res = DS3231_Write(DS3231_REG_WEEK, DS3231_Hex2Bcd(t[2]));
if (res != HAL_OK) return res;
res = DS3231_Write(DS3231_REG_DATE, DS3231_Hex2Bcd(t[3]));
if (res != HAL_OK) return res;
if (t[0] >= 100)
{
res = DS3231_Write(DS3231_REG_MONTH, DS3231_Hex2Bcd(t[1]) | (1 << 7));
if (res != HAL_OK) return res;
return DS3231_Write(DS3231_REG_YEAR, DS3231_Hex2Bcd(t[0] - 100));
}
else
{
res = DS3231_Write(DS3231_REG_MONTH, DS3231_Hex2Bcd(t[1]));
if (res != HAL_OK) return res;
return DS3231_Write(DS3231_REG_YEAR, DS3231_Hex2Bcd(t[0]));
}
}
uint8_t DS3231_GetPin(DS3231_PinType_t *pin)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_CONTROL, buff, 1);
if (res != HAL_OK) return res;
*pin = (DS3231_PinType_t)((buff[0] >> 2) & 0x01);
return HAL_OK;
}
uint8_t DS3231_SetPin(DS3231_PinType_t *pin)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_CONTROL, buff, 1);
if (res != HAL_OK) return res;
buff[0] &= ~(1 << 2);
buff[0] |= (*pin) << 2;
return DS3231_Write(DS3231_REG_CONTROL, buff[0]);
}
uint8_t ds3231_GetSquareOutputState(HAL_State_t *state)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_CONTROL, buff, 1);
if (res != HAL_OK) return res;
*state = (HAL_State_t)((buff[0] >> 6) & 0x01);
return HAL_OK;
}
uint8_t DS3231_SetSquareOutputState(HAL_State_t state)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_CONTROL, buff, 1);
if (res != HAL_OK) return res;
buff[0] &= ~(1 << 6);
buff[0] |= state << 6;
return DS3231_Write(DS3231_REG_CONTROL, buff[0]);
}
uint8_t DS3231_GetAlarmInterrupt(DS3231_Alarm_t alarm, HAL_State_t *state)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_CONTROL, buff, 1);
if (res != HAL_OK) return res;
*state = (HAL_State_t)((buff[0] >> alarm) & 0x01);
return HAL_OK;
}
uint8_t DS3231_SetAlarmInterrupt(DS3231_Alarm_t alarm, HAL_State_t state)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_CONTROL, buff, 1);
if (res != HAL_OK) return res;
buff[0] &= ~(1 << alarm);
buff[0] |= state << alarm;
return DS3231_Write(DS3231_REG_CONTROL, buff[0]);
}
uint8_t DS3231_GetAlarm1(uint8_t *t, DS3231_Alarm1Mode_t *mode)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_ALARM1_SECOND, buff, 4);
if (res != HAL_OK) return res;
t[0] = 0; // year
t[1] = 0; // month
if (((buff[3] >> 6) & 0x01) != 0) // if week
{
t[2] = DS3231_Bcd2Hex(buff[3] & 0x0F); // week
t[3] = 0; // date
}
else // if date
{
t[2] = 0; // week
t[3] = DS3231_Bcd2Hex(buff[3] & 0x3F); // date
}
t[8] = ((buff[2] >> 5) & 0x01); // am/pm
t[7] = ((buff[2] >> 6) & 0x01); // 12h/24h
if (t[7] == DS3231_FORMAT_12H)
{
t[4] = DS3231_Bcd2Hex(buff[2]&0x1F);
}
else
{
t[4] = DS3231_Bcd2Hex(buff[2]&0x3F);
}
t[5] = DS3231_Bcd2Hex(buff[1] & 0x7F);
t[6] = DS3231_Bcd2Hex(buff[0] & 0x7F);
*mode = (DS3231_Alarm1Mode_t)(
((buff[0]>>7)&0x01)<<0 |
((buff[1]>>7)&0x01)<<1 |
((buff[2]>>7)&0x01)<<2 |
((buff[3]>>7)&0x01)<<3 |
((buff[3]>>6)&0x01)<<4
);
return HAL_OK;
}
uint8_t DS3231_SetAlarm1(uint8_t *t, DS3231_Alarm1Mode_t mode)
{
uint8_t res;
uint8_t reg;
res = DS3231_Write(DS3231_REG_ALARM1_SECOND, DS3231_Hex2Bcd(t[6]) | ((mode & 0x01) << 7));
if (res != HAL_OK) return res;
res = DS3231_Write(DS3231_REG_ALARM1_MINUTE, DS3231_Hex2Bcd(t[5]) | (((mode >> 1) & 0x01) << 7));
if (res != HAL_OK) return res;
if (t[7] == DS3231_FORMAT_12H)
{
reg = (uint8_t)((((mode >> 2) & 0x01) << 7) | (1 << 6) | (t[8] << 5) | DS3231_Hex2Bcd(t[4]));
}
else
{
reg = (((mode >> 2) & 0x01) << 7) | DS3231_Hex2Bcd(t[4]);
}
res = DS3231_Write(DS3231_REG_ALARM1_HOUR, reg);
if (res != HAL_OK) return res;
if (mode >= DS3231_ALARM1_MODE_WEEK_HOUR_MINUTE_SECOND_MATCH)
{
reg = (((mode >> 3) & 0x01) << 7) | (1 << 6) | DS3231_Hex2Bcd(t[2]);
}
else
{
reg = (((mode >> 3) & 0x01) << 7) | DS3231_Hex2Bcd(t[3]);
}
return DS3231_Write(DS3231_REG_ALARM1_WEEK, reg);
}
uint8_t DS3231_GetAlarm2(uint8_t *t, DS3231_Alarm2Mode_t *mode)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_ALARM2_MINUTE, buff, 3);
if (res != HAL_OK) return res;
t[0] = 0; // year
t[1] = 0; // month
if (((buff[2] >> 6) & 0x01) != 0) // if week
{
t[2] = DS3231_Bcd2Hex(buff[2] & 0x0F);
t[3] = 0;
}
else // if date
{
t[2] = 0;
t[3] = DS3231_Bcd2Hex(buff[2] & 0x3F);
}
t[8] = ((buff[1] >> 5) & 0x01); // am/pm
t[7] = ((buff[1] >> 6) & 0x01); // 12h/24h
if (t[7] == DS3231_FORMAT_12H)
{
t[4] = DS3231_Bcd2Hex(buff[1]&0x1F);
}
else
{
t[4] = DS3231_Bcd2Hex(buff[1]&0x3F);
}
t[5] = DS3231_Bcd2Hex(buff[0] & 0x7F);
t[6] = 0;
*mode = (DS3231_Alarm2Mode_t)(
((buff[0]>>7)&0x01)<<0 |
((buff[1]>>7)&0x01)<<1 |
((buff[2]>>7)&0x01)<<2 |
((buff[2]>>6)&0x01)<<4
);
return HAL_OK;
}
uint8_t DS3231_SetAlarm2(uint8_t *t, DS3231_Alarm2Mode_t mode)
{
uint8_t res;
uint8_t reg;
res = DS3231_Write(DS3231_REG_ALARM2_MINUTE, DS3231_Hex2Bcd(t[5]) | (((mode >> 0) & 0x01) << 7));
if (res != HAL_OK) return res;
if (t[7] == DS3231_FORMAT_12H)
{
reg = (uint8_t)((((mode >> 1) & 0x01) << 7) | (1 << 6) | (t[8] << 5) | DS3231_Hex2Bcd(t[4]));
}
else
{
reg = (((mode >> 1) & 0x01) << 7) | DS3231_Hex2Bcd(t[4]);
}
res = DS3231_Write(DS3231_REG_ALARM2_HOUR, reg);
if (res != HAL_OK) return res;
if (mode >= DS3231_ALARM2_MODE_WEEK_HOUR_MINUTE_MATCH)
{
reg = (((mode >> 2) & 0x01) << 7) | (1 << 6) | DS3231_Hex2Bcd(t[2]);
}
else
{
reg = (((mode >> 2) & 0x01) << 7) | DS3231_Hex2Bcd(t[3]);
}
return DS3231_Write(DS3231_REG_ALARM2_WEEK, reg);
}
uint8_t DS3231_ClearAlarm(DS3231_Alarm_t alarm)
{
uint8_t res;
res = I2C_Read(DS3231_I2C_ADDR, DS3231_REG_STATUS, buff, 1);
if (res != HAL_OK) return res;
buff[0] &= ~(1 << alarm);
return DS3231_Write(DS3231_REG_STATUS, buff[0]);
}

View File

@ -41,12 +41,6 @@
#define DS3231_REG_TEMPERATUREL 0x12 /**< temperature low register */
typedef enum
{
DS3231_BOOL_FALSE = 0x00, /**< disable function */
DS3231_BOOL_TRUE = 0x01, /**< enable function */
} DS3231_Bool_t;
typedef enum
{
DS3231_ALARM_1 = 0x00, /**< alarm 1 */
@ -96,35 +90,39 @@ typedef enum
DS3231_ALARM2_MODE_WEEK_HOUR_MINUTE_MATCH = 0x10, /**< interrupt week hour minute match */
} DS3231_Alarm2Mode_t;
typedef struct ds3231_time_s
{
uint16_t year; /**< year */
uint8_t month; /**< month */
uint8_t week; /**< week */
uint8_t date; /**< date */
uint8_t hour; /**< hour */
uint8_t minute; /**< minute */
uint8_t second; /**< second */
DS3231_HourFormat_t format; /**< hour format */
DS3231_AmPm_t am_pm; /**< am pm */
} DS3231_Time_t;
typedef struct ds3231_handle_s
{
uint8_t (*iic_init)(void); /**< point to a iic_init function address */
uint8_t (*iic_deinit)(void); /**< point to a iic_deinit function address */
uint8_t (*iic_write)(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len); /**< point to a iic_write function address */
uint8_t (*iic_read)(uint8_t addr, uint8_t reg, uint8_t *buf, uint16_t len); /**< point to a iic_read function address */
void (*debug_print)(const char *const fmt, ...); /**< point to a debug_print function address */
void (*receive_callback)(uint8_t type); /**< point to a receive_callback function address */
void (*delay_ms)(uint32_t ms); /**< point to a delay_ms function address */
uint8_t inited; /**< inited flag */
} ds3231_handle_t;
uint8_t DS3231_GetStatus(void);
/**
* @brief
*
* @param t format
* uint8_t year;
uint8_t month;
uint8_t week;
uint8_t date;
uint8_t hour;
uint8_t minute;
uint8_t second;
DS3231_HourFormat_t format;
DS3231_AmPm_t am_pm;
* @return uint8_t
*/
uint8_t DS3231_GetTime(uint8_t *t);
uint8_t DS3231_SetTime(uint8_t *t);
uint8_t DS3231_GetPin(DS3231_PinType_t *pin);
uint8_t DS3231_SetPin(DS3231_PinType_t *pin);
uint8_t DS3231_Init(void);
uint8_t DS3231_GetTime(DS3231_Time_t *t);
uint8_t DS3231_ReadAll(uint8_t *buf);
uint8_t ds3231_GetSquareOutputState(HAL_State_t *state);
uint8_t DS3231_SetSquareOutputState(HAL_State_t state);
uint8_t DS3231_GetAlarmInterrupt(DS3231_Alarm_t alarm, HAL_State_t *state);
uint8_t DS3231_SetAlarmInterrupt(DS3231_Alarm_t alarm, HAL_State_t state);
uint8_t DS3231_GetAlarm1(uint8_t *t, DS3231_Alarm1Mode_t *mode);
uint8_t DS3231_SetAlarm1(uint8_t *t, DS3231_Alarm1Mode_t mode);
uint8_t DS3231_GetAlarm2(uint8_t *t, DS3231_Alarm2Mode_t *mode);
uint8_t DS3231_SetAlarm2(uint8_t *t, DS3231_Alarm2Mode_t mode);
uint8_t DS3231_ClearAlarm(DS3231_Alarm_t alarm);
#endif

View File

@ -25,6 +25,8 @@
#include "fw_hal.h"
#include "ds3231.h"
__XDATA uint8_t time[9];
void I2C_Init(void)
{
// Master mode
@ -49,32 +51,45 @@ void GPIO_Init(void)
int main(void)
{
DS3231_Time_t t;
uint8_t i, buf[19];
SYS_SetClock();
// UART1 configuration: baud 115200 with Timer2, 1T mode, no interrupt
UART1_Config8bitUart(UART1_BaudSource_Timer2, HAL_State_ON, 115200);
GPIO_Init();
I2C_Init();
DS3231_Init();
time[0] = DS3231_GetStatus();
UART1_TxString("Status:");
UART1_TxHex(time[0]);
UART1_TxString("\r\n");
// Set time
time[7] = DS3231_FORMAT_24H;
time[0] = 2022 - 1990; // year
time[1] = 7; // month
time[2] = 7; // week day
time[3] = 10; // date
time[4] = 14; // hour
time[5] = 21; // minute
time[6] = 10; // second
DS3231_SetTime(time);
while(1)
{
DS3231_GetTime(&t);
UART1_TxHex(t.year >> 8);
UART1_TxHex(t.year & 0xFF);
DS3231_GetTime(time);
UART1_TxHex(time[0]);
UART1_TxChar('-');
UART1_TxHex(t.month);
UART1_TxHex(time[1]);
UART1_TxChar('-');
UART1_TxHex(t.date);
UART1_TxHex(time[3]);
UART1_TxChar(' ');
UART1_TxHex(t.hour);
UART1_TxHex(time[4]);
UART1_TxChar(':');
UART1_TxHex(t.minute);
UART1_TxHex(time[5]);
UART1_TxChar(':');
UART1_TxHex(t.second);
UART1_TxHex(time[6]);
UART1_TxChar(' ');
UART1_TxHex(time[7]);
UART1_TxChar(' ');
UART1_TxHex(time[8]);
UART1_TxString("\r\n");
SYS_Delay(1000);
}