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