From 7debda1b0ac4925c9e8226979685b3928547c7cd Mon Sep 17 00:00:00 2001 From: IOsetting Date: Sun, 10 Jul 2022 18:27:01 +0800 Subject: [PATCH] refactor: update ds3231 demo --- demo/i2c/ds3231/ds3231.c | 376 ++++++++++++++++++++++++++----- demo/i2c/ds3231/ds3231.h | 62 +++-- demo/i2c/ds3231/ds3231_stc8h3k.c | 39 +++- 3 files changed, 372 insertions(+), 105 deletions(-) diff --git a/demo/i2c/ds3231/ds3231.c b/demo/i2c/ds3231/ds3231.c index f2e1f62..a44960c 100755 --- a/demo/i2c/ds3231/ds3231.c +++ b/demo/i2c/ds3231/ds3231.c @@ -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]); } diff --git a/demo/i2c/ds3231/ds3231.h b/demo/i2c/ds3231/ds3231.h index 008c170..8c30962 100755 --- a/demo/i2c/ds3231/ds3231.h +++ b/demo/i2c/ds3231/ds3231.h @@ -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 diff --git a/demo/i2c/ds3231/ds3231_stc8h3k.c b/demo/i2c/ds3231/ds3231_stc8h3k.c index b00d625..bec12c5 100644 --- a/demo/i2c/ds3231/ds3231_stc8h3k.c +++ b/demo/i2c/ds3231/ds3231_stc8h3k.c @@ -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); }