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 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 343 insertions(+), 0 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); +} -- Gitblit v1.9.1