From 1105733dc07562240bd061a1d8b0869c8c596805 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Thu, 09 Oct 2025 00:41:09 +0800
Subject: [PATCH] ISL1208 RTC示例程序

---
 Core/Src/board/isl1208.c |  343 +++++++++++++++++++++++++++++++++++++++++++++++++
 Core/Src/main.c          |   21 --
 Core/Src/board/isl1208.h |   46 ++++++
 3 files changed, 394 insertions(+), 16 deletions(-)

diff --git a/Core/Src/board/isl1208.c b/Core/Src/board/isl1208.c
new file mode 100644
index 0000000..054a92a
--- /dev/null
+++ b/Core/Src/board/isl1208.c
@@ -0,0 +1,343 @@
+/**********************************************************************
+ *   Copyright: (C)2024 LingYun IoT System Studio
+ *      Author: GuoWenxue<guowenxue@gmail.com>
+ *
+ * Description: ISL1208 RTC driver on ISKBoard
+ *
+ *   ChangeLog:
+ *        Version    Date       Author            Description
+ *        V1.0.0  2024.08.29    GuoWenxue      Release initial version
+ *
+ ***********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "isl1208.h"
+#include "i2c_bitbang.h"
+
+//#define CONFIG_DEBUG_RTC /* Enable ISL1208 RTC debug */
+
+#define ISL1208_CHIPADDR        0x6F      /* ISL1208 7-Bits Chip address */
+
+
+#ifdef  CONFIG_DEBUG_RTC
+#define rtc_print(format,args...) printf(format, ##args)
+#else
+#define rtc_print(format,args...) do{} while(0)
+#endif
+
+
+/*+--------------------------------------+
+ *|      RTC Chipset ISL1208 Register    |
+ *+--------------------------------------+*/
+
+/* rtc section */
+#define ISL1208_REG_SC          0x00
+#define ISL1208_REG_MN          0x01
+#define ISL1208_REG_HR          0x02
+#define ISL1208_REG_HR_MIL     (1<<7)   /* 24h/12h mode */
+#define ISL1208_REG_HR_PM      (1<<5)   /* PM/AM bit in 12h mode */
+#define ISL1208_REG_DT          0x03
+#define ISL1208_REG_MO          0x04
+#define ISL1208_REG_YR          0x05
+#define ISL1208_REG_DW          0x06
+#define ISL1208_RTC_SECTION_LEN 7 /* RTC Section register */
+#define REGS_RTC_SR_LEN         8 /* RTC Section and status register  */
+
+/* control/status section */
+#define ISL1208_REG_SR          0x07
+#define ISL1208_REG_SR_ARST    (1<<7)   /* auto reset */
+#define ISL1208_REG_SR_XTOSCB  (1<<6)   /* crystal oscillator */
+#define ISL1208_REG_SR_WRTC    (1<<4)   /* write rtc */
+#define ISL1208_REG_SR_EVT     (1<<3)   /* event */
+#define ISL1208_REG_SR_ALM     (1<<2)   /* alarm */
+#define ISL1208_REG_SR_BAT     (1<<1)   /* battery */
+#define ISL1208_REG_SR_RTCF    (1<<0)   /* rtc fail */
+#define ISL1208_REG_INT         0x08
+#define ISL1208_REG_INT_ALME   (1<<6)   /* alarm enable */
+#define ISL1208_REG_INT_IM     (1<<7)   /* interrupt/alarm mode */
+#define ISL1219_REG_EV          0x09
+#define ISL1219_REG_EV_EVEN    (1<<4)   /* event detection enable */
+#define ISL1219_REG_EV_EVIENB  (1<<7)   /* event in pull-up disable */
+#define ISL1208_REG_ATR         0x0a
+#define ISL1208_REG_DTR         0x0b
+
+/* alarm section */
+#define ISL1208_REG_SCA         0x0c
+#define ISL1208_REG_MNA         0x0d
+#define ISL1208_REG_HRA         0x0e
+#define ISL1208_REG_DTA         0x0f
+#define ISL1208_REG_MOA         0x10
+#define ISL1208_REG_DWA         0x11
+#define ISL1208_ALARM_SECTION_LEN 6
+
+/* user section */
+#define ISL1208_REG_USR1        0x12
+#define ISL1208_REG_USR2        0x13
+#define ISL1208_USR_SECTION_LEN 2
+
+#define ISL1208_REGS_MAX        0x13
+
+const char *weekday[7]={"Sun.","Mon.","Tue.","Wed.","Thu.","Fri.","Sat." };
+
+
+/*
+ *+----------------------------------+
+ *|     ISL1208 Low level API        |
+ *+----------------------------------+
+ */
+
+static int isl1208_i2c_read_regs(uint8_t regaddr, uint8_t *regs, uint8_t len)
+{
+    uint8_t        i;
+    int            rv = 0;
+    uint8_t        byte;
+    uint8_t        ack;
+
+    if( !regs || len<=0 )
+    {
+        rtc_print("ISL1208: Invalid input arguments\r\n");
+        return -1;
+    }
+
+    I2C_StartCondition();
+
+    if( (rv=I2C_SendAddress(I2C_WR)) < 0 )
+    {
+        rtc_print("ISL1208: Send chipset address[W] failure: rv=0x%02x\r\n", rv);
+        goto OUT;
+    }
+
+    if( (rv=I2C_WriteByte(regaddr)) < 0 )
+    {
+        rtc_print("ISL1208: Set register[0x%02x] failure: rv=0x%02x\r\n", regaddr, rv);
+        goto OUT;
+    }
+
+    I2C_StartCondition();
+
+    if( (rv=I2C_SendAddress( I2C_RD )) < 0 )
+    {
+        rtc_print("ISL1208: Send chipset address[W] failure: rv=0x%02x\r\n", rv);
+        goto OUT;
+    }
+
+    for (i=0; i<len; i++)
+    {
+         if( i == (len-1) )
+             ack = ACK_NONE;
+         else
+             ack = ACK;
+
+         if( (rv=I2C_ReadByte(&byte, ack, I2C_CLK_STRETCH_TIMEOUT)) < 0 )
+         {
+             rtc_print("ISL1208: Read register data failure: rv=0x%02x\r\n", rv);
+             goto OUT;
+         }
+
+         regs[i] = byte;
+    }
+
+OUT:
+    I2C_StopCondition();
+    return rv;
+}
+
+static int isl1208_i2c_write_regs(uint8_t regaddr, uint8_t *regs, uint8_t len)
+{
+    uint8_t        i = 0;
+    int            rv = 0;
+
+    I2C_StartCondition();
+
+    if( (rv=I2C_SendAddress(I2C_WR)) < 0 )
+    {
+        rtc_print("ISL1208: Send chipset address[W] failure: rv=0x%02x\r\n", rv);
+        goto OUT;
+    }
+
+    if( (rv=I2C_WriteByte(regaddr)) < 0 )
+    {
+        rtc_print("ISL1208: Set register[0x%02x] failure: rv=0x%02x\r\n", regaddr, rv);
+        goto OUT;
+    }
+
+    for (i=0; i<len; i++)
+    {
+        if( (rv=I2C_WriteByte(regs[i])) < 0 )
+        {
+            rtc_print("ISL1208: Write register data failure: rv=0x%02x\r\n", rv);
+            goto OUT;
+        }
+    }
+
+    rv = 0;
+
+OUT:
+    I2C_StopCondition();
+    return rv;
+}
+
+
+#define bcd2bin(x)    (((x) & 0x0f) + ((x) >> 4) * 10)
+#define bin2bcd(x)    ((((x) / 10) << 4) + (x) % 10)
+
+int set_hwclock(hwclock_t tm)
+{
+    int                     rv;
+    uint8_t                 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
+    uint8_t                 sr;
+
+    regs[ISL1208_REG_SC] = bin2bcd(tm.tm_sec);
+    regs[ISL1208_REG_MN] = bin2bcd(tm.tm_min);
+    regs[ISL1208_REG_HR] = bin2bcd(tm.tm_hour) | ISL1208_REG_HR_MIL;
+
+    regs[ISL1208_REG_DT] = bin2bcd(tm.tm_mday);
+    regs[ISL1208_REG_MO] = bin2bcd(tm.tm_mon);
+    regs[ISL1208_REG_YR] = bin2bcd(tm.tm_year - 2000);
+    //regs[ISL1208_REG_DW] = bin2bcd(tm.tm_wday & 7);
+
+    if( i2c_lock(ISL1208_CHIPADDR) < 0 )
+    {
+        rtc_print("ISL1208: Lock I2C bus failure!\r\n");
+        return -2;
+    }
+
+    rv = isl1208_i2c_read_regs(ISL1208_REG_SR, &sr, 1);
+    if( rv < 0 )
+    {
+        rtc_print("ISL1208: read Status Register failure, rv=%d!\r\n", rv);
+        rv = -3;
+        goto OUT;
+    }
+    sr |= ISL1208_REG_SR_WRTC;
+    rv = isl1208_i2c_write_regs(ISL1208_REG_SR, &sr, 1);
+    if( rv < 0 )
+    {
+        rtc_print("ISL1208: Set Status Register WRTC failure, rv=%d!\r\n", rv);
+        rv = -4;
+        goto OUT;
+    }
+
+    rv=isl1208_i2c_write_regs(ISL1208_REG_SC, regs, ISL1208_RTC_SECTION_LEN);
+    if(rv < 0 )
+    {
+        rtc_print("ISL1208: Set RTC section registeres failure, rv=%d!\r\n", rv);
+        rv = -5;
+        goto OUT;
+    }
+
+    sr &= (~ISL1208_REG_SR_WRTC);
+    rv = isl1208_i2c_write_regs(ISL1208_REG_SR, &sr, 1);
+    if( rv < 0 )
+    {
+        rtc_print("ISL1208: Clear Status Register WRTC failure, rv=%d!\r\n", rv);
+        rv = -6;
+        goto OUT;
+    }
+
+OUT:
+    i2c_free();
+    return rv;
+}
+
+int get_hwclock(hwclock_t *tm)
+{
+    int                                 rv = 0;
+    uint8_t                             regs[REGS_RTC_SR_LEN] = { 0, };
+
+    if( !tm )
+    {
+        rtc_print("ISL1208: Invalid input arugments!\r\n");
+        return -1;
+    }
+
+    if( i2c_lock(ISL1208_CHIPADDR) < 0 )
+    {
+        rtc_print("ISL1208: Initial I2C bus failure!\r\n");
+        return -2;
+    }
+
+    rv = isl1208_i2c_read_regs(ISL1208_REG_SC, regs, REGS_RTC_SR_LEN);
+    if (rv < 0)
+    {
+        rtc_print("ISL1208: read RTC_SECTION and SR registeres failure, rv=%d!\r\n", rv);
+        rv = -3;
+        goto OUT;
+    }
+
+    if( regs[ISL1208_REG_SR] & ISL1208_REG_SR_RTCF )
+    {
+        rtc_print("ISL1208: Initialize RTC time after power failure!\r\n");
+        rv = -4;
+        goto OUT;
+    }
+
+    tm->tm_sec = bcd2bin(regs[ISL1208_REG_SC]);
+    tm->tm_min = bcd2bin(regs[ISL1208_REG_MN]);
+
+    {
+        const uint8_t _hr = regs[ISL1208_REG_HR];
+
+        if (_hr & ISL1208_REG_HR_MIL)  /* 24H */
+        {
+            tm->tm_hour = bcd2bin(_hr & 0x3f);
+        }
+        else  /* 12H */
+        {
+            tm->tm_hour = bcd2bin(_hr & 0x1f);
+            if (_hr & ISL1208_REG_HR_PM)
+                tm->tm_hour += 12;
+        }
+    }
+
+    tm->tm_mday = bcd2bin(regs[ISL1208_REG_DT]);
+    tm->tm_mon  = bcd2bin(regs[ISL1208_REG_MO]);
+    tm->tm_year = bcd2bin(regs[ISL1208_REG_YR]) + 2000;
+    tm->tm_wday = bcd2bin(regs[ISL1208_REG_DW]);
+
+OUT:
+    i2c_free();
+    return rv;
+}
+
+int set_rtctime(char *time)
+{
+    hwclock_t       tm;
+
+    if( 6 != sscanf(time, "%d-%d-%d %d:%d:%d",
+                &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec))
+    {
+        return -1;
+    }
+
+    set_hwclock(tm);
+
+    return 0;
+}
+
+int get_rtctime(char *buf, int size)
+{
+    hwclock_t       tm;
+
+    memset(buf, 0, size);
+
+    if( get_hwclock(&tm) < 0 )
+        return -1;
+
+    snprintf(buf, size, "%04d-%02d-%02d %02d:%02d:%02d\r\n",
+        tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+    return 0;
+}
+
+void print_rtctime(void)
+{
+    hwclock_t       tm;
+
+    if( get_hwclock(&tm) < 0 )
+        return ;
+
+    printf("%04d-%02d-%02d %02d:%02d:%02d\r\n",
+        tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
diff --git a/Core/Src/board/isl1208.h b/Core/Src/board/isl1208.h
new file mode 100644
index 0000000..2fe532e
--- /dev/null
+++ b/Core/Src/board/isl1208.h
@@ -0,0 +1,46 @@
+/**********************************************************************
+ *   Copyright: (C)2024 LingYun IoT System Studio
+ *      Author: GuoWenxue<guowenxue@gmail.com>
+ *
+ * Description: ISL1208 RTC driver on ISKBoard
+ *
+ *   ChangeLog:
+ *        Version    Date       Author            Description
+ *        V1.0.0  2024.08.29    GuoWenxue      Release initial version
+ *
+ ***********************************************************************/
+
+#ifndef __ISL1208_H_
+#define __ISL1208_H_
+
+typedef struct hwclock_s
+{
+    int       tm_sec;   /* [0 ~ 59/60 ]  */
+    int       tm_min;   /* [0 ~ 59 ]     */
+    int       tm_hour;  /* [0 ~ 23 ]     */
+
+    int       tm_mday;  /* [1 ~ 31]      */
+    int       tm_mon;   /* [1 ~ 12]      */
+    int       tm_year;  /* [ 2000~2099 ] */
+
+    int       tm_wday;  /* [0 ~ 6 ]      */
+} hwclock_t;
+
+extern const char    *weekday[7];
+
+/* Set RTC time by struct $tm */
+extern int set_hwclock(hwclock_t tm);
+
+/* Get RTC time by struct $tm */
+extern int get_hwclock(hwclock_t *tm);
+
+/* Set RTC time by time string format: "2024-08-29 12:08:08" */
+extern int set_rtctime(char *time);
+
+/* Get RTC time by time string format: "2024-08-29 12:08:08" */
+extern int get_rtctime(char *buf, int size);
+
+/* Print RTC time by time string format: "2024-08-29 12:08:08" */
+extern void print_rtctime(void);
+
+#endif /* __ISL1208_H_ */
diff --git a/Core/Src/main.c b/Core/Src/main.c
index 5f8f55a..4e17432 100644
--- a/Core/Src/main.c
+++ b/Core/Src/main.c
@@ -28,8 +28,7 @@
 /* USER CODE BEGIN Includes */
 #include "miscdev.h"
 #include "sht20.h"
-#include "w25q.h"
-#include "hal_oled.h"
+#include "isl1208.h"
 /* USER CODE END Includes */
 
 /* Private typedef -----------------------------------------------------------*/
@@ -72,8 +71,7 @@
 {
 
   /* USER CODE BEGIN 1 */
-  int pos_x = 25;
-  int pos_y = 1;
+
   /* USER CODE END 1 */
 
   /* MCU Configuration--------------------------------------------------------*/
@@ -102,7 +100,8 @@
   /* USER CODE BEGIN 2 */
 
   beep_start(2, 300);
-  OLED_Init();
+  printf("ISKBoard ISL1208 RTC example.\r\n");
+  set_rtctime("2025-08-08 08:08:08");
 
   /* USER CODE END 2 */
 
@@ -110,17 +109,7 @@
   /* USER CODE BEGIN WHILE */
   while (1)
   {
-    OLED_Clear();
-    OLED_ShowString(pos_x, pos_y, "ISKBoard", OLED_FONT16);
-    HAL_Delay(1000);
-
-    OLED_Clear();
-    for(int i=0; i<HZK_LEN_LINGYUN; i++)
-        OLED_ShowChinese(Hzk_LingYun, pos_x+i*16, pos_y, i);
-    HAL_Delay(1000);
-
-    OLED_Clear();
-    OLED_DrawBMP(0,0, X_WIDTH,Y_WIDTH/2, bmp_logo);
+	print_rtctime();
     HAL_Delay(1000);
 
     /* USER CODE END WHILE */

--
Gitblit v1.9.1