S-35390A RTC芯片:高精度低功耗实时时钟的硬件设计与软件驱动实战
2026/8/7 6:05:20 网站建设 项目流程

1. 从“计时”到“守时”:S-35390A芯片的定位与价值

在嵌入式系统和物联网设备里,给设备一个“靠谱”的时间,这事儿听起来简单,做起来却处处是坑。你可能遇到过这样的场景:一个数据采集终端,断电重启后时间归零,导致采集的数据时间戳全乱;一个智能门锁,因为内置的RTC(实时时钟)精度太差,累计误差几个月后,定时开锁功能完全错乱;或者一个需要严格时间同步的工业控制器,因为计时芯片在低温下罢工,整个产线跟着停摆。这些问题的核心,往往都出在那个负责“守时”的芯片上——它不够准、不够稳、或者不够省电。

今天要聊的S-35390A,就是瑞萨电子(Renesas)旗下的一款高性能、低功耗的I2C接口实时时钟芯片。它不是那种只能简单计时的“玩具”,而是一个在-40°C到+85°C的工业级温度范围内,都能保持高精度、极低功耗运行的“时间守门员”。对于需要长时间离线运行、电池供电,且对时间准确性有苛刻要求的设备来说,比如智能水表、气表、资产追踪器、医疗设备、安防系统等,选对一颗RTC芯片,往往意味着产品可靠性的本质提升。

S-35390A的核心价值,在于它用极简的外围电路和极低的功耗成本,解决了嵌入式系统里“精准守时”这个基础却关键的难题。它内置了高精度的32.768kHz晶体振荡器,出厂时已经过频率调整,典型精度可以达到±5ppm(百万分之五)的水平。换算一下,这意味着它一个月的误差最多只有大约13秒。更重要的是,它内置了时钟数字调谐功能,允许我们通过软件对时钟频率进行微调,进一步校准因晶体个体差异、温度、老化等因素带来的偏差,这是很多低成本RTC不具备的能力。

2. 芯片功能深度拆解:不止于“走时”

很多开发者对RTC的理解还停留在“提供一个年月日时分秒”的层面,但S-35390A的功能远不止于此。理解它的每一个功能模块,才能在设计时物尽其用,避免后期因为功能不足而更换芯片的尴尬。

2.1 核心计时与日历功能

这是RTC的基本盘。S-35390A提供从秒到年、包括星期的完整计时和日历功能,支持2000年至2099年的闰年自动修正。这里有一个容易被忽略的细节:它的时间寄存器是BCD码格式。BCD码(Binary-Coded Decimal)用4位二进制数表示一个十进制数字(0-9)。例如,分钟寄存器存储“59”时,实际数据是0x59(二进制0101 1001),高4位0101代表十位的5,低4位1001代表个位的9。编程时,我们需要进行BCD码和十进制数之间的转换。虽然MCU通常有硬件或库函数支持,但在初始化和读取时间时,必须留意这个格式,直接赋值十进制数会导致时间错误。

注意:芯片的时钟运行依赖于一个独立的32.768kHz晶体。即使主控MCU进入深度睡眠或完全断电(仅保持对RTC的供电),S-35390A也能依靠其内置的振荡电路和这个晶体继续精准计时。这是它作为独立“守时”单元的关键。

2.2 闹钟与定时中断功能

S-35390A提供两组独立的闹钟寄存器(Alarm1和Alarm2)。闹钟可以设置为按“星期+时分秒”匹配,也可以设置为每天固定的“时分秒”匹配,非常灵活。当当前时间与闹钟设置时间匹配时,芯片的/INT引脚会输出一个低电平中断信号(可配置为脉冲或电平模式),唤醒处于睡眠状态的主控MCU。

这个功能是低功耗系统的核心。例如,一个环境传感器可以设定每小时唤醒一次进行采样和上传数据,其余时间MCU完全断电,仅靠S-35390A和它的晶体维持计时。当闹钟时间到,/INT引脚的电平变化可以连接到MCU的外部中断引脚,从而触发MCU上电、初始化、执行任务,任务完成后再次进入深度睡眠。通过合理利用闹钟中断,可以将系统的平均功耗降低到微安级别。

2.3 时间更新中断与频率输出

除了闹钟,它还有一个“时间更新中断”功能。可以配置为每秒、每分、每小时产生一次中断。这个功能常用于需要周期性执行的任务,或者作为系统的一个低频时基。例如,可以用它来驱动一个LED每秒闪烁一次作为系统运行指示,而无需MCU软件定时。

此外,芯片可以从/INT引脚或一个专用的/FOUT引脚输出可编程的方波信号,频率可以从1Hz到32.768kHz之间选择。这个功能可以作为其他外围芯片的时钟源,或者用于测试和校准。

2.4 至关重要的时钟校准功能

这是S-35390A区别于廉价RTC的杀手锏。芯片内部有一个“时钟调谐寄存器”,允许用户以大约0.953ppm的步进对时钟频率进行数字调整,调整范围约为-189.2ppm到 +204.6ppm。校准的原理是通过在固定周期内增加或跳过少量的时钟脉冲,来补偿晶体的频率偏差。

为什么需要这个?因为即使精度标称为±5ppm的晶体,在实际焊接、不同温度、不同批次下,其实际频率也会在一个范围内波动。通过在生产线上或产品安装后,用一个更精确的时钟源(如GPS秒脉冲、网络NTP时间)作为参考,测量S-35390A一段时间的累积误差,然后反向计算出一个校准值写入调谐寄存器,可以将其长期精度提升到±2ppm甚至更高。这对于生命周期长达数年、需要维持时间同步的物联网设备至关重要。

3. 硬件设计要点与避坑指南

把S-35390A用起来,第一步是画对原理图。别看它只有8个引脚,每个引脚的处理都关系到系统能否稳定可靠地运行。

3.1 电源与备份电源设计

S-35390A有VDD和VBAT两个电源引脚。VDD接主电源(如3.3V),VBAT接备份电池(如3V的纽扣电池CR2032)。当VDD电压低于VBAT约0.2V时,芯片会自动切换到VBAT供电,保证计时不间断。这是RTC的“生命线”。

关键设计点1:电源去耦。必须在VDD引脚附近(1cm以内)放置一个0.1μF的陶瓷电容到地,用于滤除高频噪声。如果主电源纹波较大,建议再并联一个10μF的钽电容或电解电容。VBAT引脚同样需要一颗0.1μF的去耦电容。许多计时不准或数据丢失的问题,根源就是电源噪声。

关键设计点2:电池选择与二极管。通常,VBAT通过一个二极管(如1N4148)连接到备份电池正极,电池负极接地。这个二极管的作用是防止主电源VDD向电池充电(对于不可充电的锂锰电池CR2032,充电是危险的)。二极管会产生约0.6V的压降,所以需要确保电池电压(减去压降后)仍在芯片的工作电压范围内(通常为1.6V至5.5V)。使用可充电电池或超级电容时,电路设计会有所不同。

关键设计点3:上电复位与初始值。芯片内部有上电复位电路,但首次上电或VDD从0V上升时,其内部寄存器状态是不确定的。因此,在MCU程序初始化时,必须先读取一个状态寄存器(如控制状态寄存器2),判断芯片是否经历了电源失效,如果是,则需要重新初始化时间日期。不能假设芯片里存着正确的时间。

3.2 晶体电路设计:精度与稳定的基石

S-35390A需要外接一个32.768kHz的晶体。其振荡电路设计是影响精度和起振可靠性的核心。

晶体选型:必须选择负载电容为12.5pF的晶体(这是芯片内部电路的匹配值)。常见的规格是“32.768kHz,12.5pF,±20ppm”。虽然芯片可校准,但为了获得最佳起点,应尽量选择精度高、质量好的品牌晶体。

负载电容计算与布局:芯片的X1和X2引脚连接晶体。通常需要在两个引脚到地之间各接一个负载电容(C_L1和C_L2)。其总值应匹配晶体要求的负载电容(CL)。公式为:CL = (C_L1 * C_L2) / (C_L1 + C_L2) + C_stray。其中C_stray是PCB走线带来的寄生电容,通常估计为2-5pF。假设晶体CL=12.5pF,C_stray估算为3pF,则所需的外接电容总和应为 (12.5 - 3) = 9.5pF。因此,通常选择两个相同的电容,C_L1 = C_L2 = 2 * 9.5 = 19pF。实际常用18pF或22pF的NPO陶瓷电容。布局上,晶体和这两个电容必须尽可能靠近芯片的X1/X2引脚,走线短而粗,并用地线包围进行屏蔽,远离数字信号线、电源线等噪声源。

踩坑实录:不起振或停振。这是最常见的问题。现象是芯片无法读写,或时间不走。排查步骤:1. 用示波器探头(请使用10X档位,以减小探头电容影响)测量X1或X2引脚,看是否有32.768kHz的正弦波(幅度很小,约200-500mV)。2. 如果没波形,检查晶体是否焊好、电容值是否正确、布局是否太远。3. 尝试更换一个晶体。有时晶体本身损坏或参数不匹配会导致不起振。4. 确保电源电压稳定,噪声小。

3.3 I2C总线与中断引脚处理

S-35390A通过I2C总线与MCU通信。SCL和SDA需要上拉电阻,阻值根据总线速度和布线长度选择,通常在4.7kΩ到10kΩ之间。对于长线或高速模式,可能需要更小的上拉电阻。

/INT(中断输出)引脚是开漏输出,必须外接一个上拉电阻(如10kΩ)到MCU的IO口电源。当闹钟或定时器触发时,该引脚被芯片内部拉低,从而向MCU申请中断。MCU端需要将该引脚配置为外部中断输入模式,并设置好边沿触发(通常为下降沿)。处理完中断后,需要通过I2C读取芯片的状态寄存器来清除中断标志,否则/INT引脚会一直保持低电平。

4. 软件驱动开发与实战代码解析

硬件搭好了,接下来就是让MCU和它对话。我们将基于通用的I2C驱动,构建一个稳健的S-35390A软件层。

4.1 寄存器映射与关键定义

首先,我们需要定义芯片的I2C从地址和核心寄存器地址。S-35390A的7位I2C从地址是固定的0x32(二进制0110010)。读写位由I2C协议控制。

以下是主要寄存器地址的宏定义(基于数据手册):

#define S35390A_I2C_ADDR 0x32 // 时间日期寄存器 (BCD格式) #define S35390A_REG_SEC 0x00 #define S35390A_REG_MIN 0x01 #define S35390A_REG_HOUR 0x02 #define S35390A_REG_WDAY 0x03 #define S35390A_REG_DAY 0x04 #define S35390A_REG_MONTH 0x05 #define S35390A_REG_YEAR 0x06 // 闹钟1寄存器 #define S35390A_REG_AL1_MIN 0x07 #define S35390A_REG_AL1_HOUR 0x08 #define S35390A_REG_AL1_WDAY 0x09 // 闹钟2寄存器 #define S35390A_REG_AL2_MIN 0x0A #define S35390A_REG_AL2_HOUR 0x0B #define S35390A_REG_AL2_WDAY 0x0C // 控制/状态寄存器 #define S35390A_REG_CTRL1 0x0F #define S35390A_REG_CTRL2 0x10 #define S35390A_REG_CTRL3 0x11 // 时钟调谐寄存器 #define S35390A_REG_OFFSET 0x12 // 状态标志位定义 (CTRL2寄存器) #define S35390A_FLAG_POC (1 << 0) // 电源掉电检测标志 #define S35390A_FLAG_BLD (1 << 1) // 电池低电压检测标志 #define S35390A_FLAG_INT1 (1 << 2) // 闹钟1中断标志 #define S35390A_FLAG_INT2 (1 << 3) // 闹钟2中断标志 #define S35390A_FLAG_24H (1 << 5) // 24小时制设置位

4.2 BCD码与十进制转换工具函数

由于所有时间数据都是BCD码,编写两个工具函数是必须的。

/** * @brief 十进制数转BCD码 * @param dec 十进制数 (0-99) * @return BCD码 */ static uint8_t dec_to_bcd(uint8_t dec) { return ((dec / 10) << 4) | (dec % 10); } /** * @brief BCD码转十进制数 * @param bcd BCD码 * @return 十进制数 */ static uint8_t bcd_to_dec(uint8_t bcd) { return ((bcd >> 4) * 10) + (bcd & 0x0F); }

4.3 初始化与状态检测流程

上电后,不能直接读写时间。必须先进行初始化检测。

/** * @brief 初始化S-35390A,检测并处理电源失效情况 * @param hdev: I2C设备句柄 * @return 0:成功, -1:通信失败, -2:需要重新设置时间(发生了电源失效) */ int s35390a_init(void *hdev) { uint8_t ctrl2_reg = 0; int ret; // 1. 读取控制状态寄存器2 ret = i2c_read_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_CTRL2, &ctrl2_reg, 1); if (ret != 0) { printf("S35390A I2C通信失败!\r\n"); return -1; } // 2. 检查电源掉电标志(POC) if (ctrl2_reg & S35390A_FLAG_POC) { printf("S35390A检测到电源失效,时间可能已丢失。\r\n"); // 清除POC标志(通过写入0) uint8_t clear_poc = ctrl2_reg & (~S35390A_FLAG_POC); i2c_write_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_CTRL2, &clear_poc, 1); // 返回需要重新设置时间的代码 return -2; } // 3. 可选:配置为24小时制 uint8_t ctrl1_reg; i2c_read_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_CTRL1, &ctrl1_reg, 1); ctrl1_reg |= S35390A_FLAG_24H; // 设置24小时模式 i2c_write_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_CTRL1, &ctrl1_reg, 1); printf("S35390A初始化成功。\r\n"); return 0; }

这个初始化函数是关键。它首先尝试与芯片通信,确保硬件连接正常。然后读取状态寄存器,检查POC标志。如果这个标志被置位,说明芯片经历了从VDD到VBAT的切换(即主电源完全断电后又上电),此时芯片内部的时间可能是随机的垃圾值。程序必须捕获这个状态,并提示上层应用或自动从备份存储(如Flash)中恢复时间,或者要求用户重新校时。忽略这个检查是产品中时间错乱的常见原因。

4.4 时间设置与读取函数

设置和读取时间需要处理BCD码转换和多个寄存器的连续读写。

typedef struct { uint8_t year; // 0-99 (对应2000-2099) uint8_t month; // 1-12 uint8_t day; // 1-31 uint8_t week; // 0-6 (通常0=周日,1=周一...) uint8_t hour; // 0-23 uint8_t minute; // 0-59 uint8_t second; // 0-59 } rtc_time_t; /** * @brief 设置RTC时间 */ int s35390a_set_time(void *hdev, rtc_time_t *time) { uint8_t data[7]; // 注意:写入时间寄存器时,需要确保芯片不在“时钟更新”期间。 // 简单做法:先读一下秒寄存器,如果最高位(时钟暂停标志)为0,则可写入。 // 更稳健的做法是等待两次读取的秒数相同。 uint8_t sec_reg; do { i2c_read_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_SEC, &sec_reg, 1); } while (sec_reg & 0x80); // 等待非更新周期 data[0] = dec_to_bcd(time->second); data[1] = dec_to_bcd(time->minute); data[2] = dec_to_bcd(time->hour); data[3] = dec_to_bcd(time->week); data[4] = dec_to_bcd(time->day); data[5] = dec_to_bcd(time->month); data[6] = dec_to_bcd(time->year); return i2c_write_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_SEC, data, 7); } /** * @brief 读取RTC时间 */ int s35390a_get_time(void *hdev, rtc_time_t *time) { uint8_t data[7]; int ret; // 连续读取7个时间寄存器 ret = i2c_read_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_SEC, data, 7); if (ret != 0) return ret; // 转换BCD码并填充结构体 time->second = bcd_to_dec(data[0] & 0x7F); // 屏蔽最高位(时钟暂停位) time->minute = bcd_to_dec(data[1] & 0x7F); // 屏蔽未使用位 time->hour = bcd_to_dec(data[2] & 0x3F); // 屏蔽24/12小时制和未使用位 time->week = bcd_to_dec(data[3] & 0x07); // 星期只有低3位有效 time->day = bcd_to_dec(data[4] & 0x3F); time->month = bcd_to_dec(data[5] & 0x1F); time->year = bcd_to_dec(data[6]); return 0; }

set_time函数中,有一个重要的细节:时钟更新周期。芯片在每秒的末尾会有一个极短的时间(小于1秒)用于更新所有时间寄存器。在此期间读取时间可能会得到不一致的数据(比如秒是59,分却是下一个分钟)。为了避免这个问题,标准的做法是连续读取两次时间,直到两次读取的秒数相同,确保读取发生在非更新周期。上面的设置函数里,我们通过检查秒寄存器的最高位(第7位)来判断,该位为0表示时钟正常运行且不在更新周期。这是一种简化的方法。

4.5 闹钟设置与中断处理实战

闹钟功能是实现定时唤醒的关键。我们以设置一个每天08:30:00的闹钟为例。

/** * @brief 设置闹钟1(每天固定时间触发) * @param hour: 小时 (0-23) * @param min: 分钟 (0-59) * @param sec: 秒 (0-59), 如果不需要秒匹配,可设为0xFF */ int s35390a_set_alarm1_daily(void *hdev, uint8_t hour, uint8_t min, uint8_t sec) { uint8_t data[3]; // 设置寄存器值,注意最高位是“忽略”位,设为1则忽略该字段的匹配 data[0] = (sec == 0xFF) ? 0x80 : dec_to_bcd(sec); // AL1_SEC data[1] = (min == 0xFF) ? 0x80 : dec_to_bcd(min); // AL1_MIN data[2] = (hour == 0xFF) ? 0x80 : dec_to_bcd(hour); // AL1_HOUR // 星期寄存器设置为0x80,表示忽略星期匹配,即每天触发 uint8_t week_ignore = 0x80; int ret = i2c_write_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_AL1_MIN, data, 3); if (ret == 0) { ret = i2c_write_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_AL1_WDAY, &week_ignore, 1); } if (ret == 0) { // 使能闹钟1中断 uint8_t ctrl2_reg; i2c_read_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_CTRL2, &ctrl2_reg, 1); ctrl2_reg |= (1 << 0); // 设置AL1_INT_EN位 (具体位需查手册,此处为示例) i2c_write_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_CTRL2, &ctrl2_reg, 1); } return ret; }

设置好闹钟后,当时间匹配时,/INT引脚会变低。MCU端的中断服务函数应该这样处理:

// 假设/INT引脚连接到MCU的GPIO_PIN_0 void EXTI0_IRQHandler(void) { if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET) { // 1. 清除MCU端的中断标志 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0); // 2. 读取S-35390A的状态寄存器,判断中断源并清除标志 uint8_t status_reg; i2c_read_reg(&hi2c1, S35390A_I2C_ADDR, S35390A_REG_CTRL2, &status_reg, 1); if (status_reg & S35390A_FLAG_INT1) { printf("闹钟1触发!\r\n"); // 执行唤醒后的任务,例如采集传感器数据并上传 do_wakeup_task(); // 清除芯片内的闹钟1中断标志(通过写0清除) status_reg &= ~S35390A_FLAG_INT1; i2c_write_reg(&hi2c1, S35390A_I2C_ADDR, S35390A_REG_CTRL2, &status_reg, 1); } // 可以继续检查其他中断源,如闹钟2(INT2) } }

这里有一个至关重要的步骤:必须在中断服务程序里读取芯片的状态寄存器来清除中断标志。如果只清除了MCU的GPIO中断标志,而没有清除S-35390A内部的标志位,那么/INT引脚会一直保持低电平,导致MCU无法再次进入睡眠,或者产生连续的中断。

5. 高级应用:时钟校准与长期精度保障

对于追求极致精度的应用,软件校准是必不可少的一环。校准的目标是测量出芯片在当前环境下的实际日误差,并通过写“时钟调谐寄存器”进行补偿。

5.1 校准原理与计算

S-35390A的时钟调谐寄存器(Offset Register)是一个8位有符号整数(二进制补码形式)。其值N与频率调整量Δf/f的关系由公式决定:Δf/f = - (N / 2^20) ≈ -N * 0.9537 ppm。N为正时,减慢时钟;N为负时,加快时钟。

校准步骤:

  1. 获取参考时间源:需要一个极其精确的时间源作为参考。可以是GPS模块的1PPS(每秒脉冲)信号、通过NTP同步的计算机网络时间、或者高精度的恒温晶振。
  2. 测量误差:让S-35390A和参考时间源同时运行一段较长的时间T(例如24小时或7天)。记录起始时刻两个时间的差值Δt_start,和结束时刻的差值Δt_end。
  3. 计算误差率:累计误差 Δerror = Δt_end - Δt_start。误差率 = Δerror / T。
  4. 计算调谐值N:N = - (误差率 * 2^20)。例如,如果测量24小时(86400秒)快了10秒,则误差率 = 10 / 86400 ≈ 115.74 ppm。N = -115.74 * 1048576 ≈ -121,300。由于N是8位有符号数,范围是-128到+127,对应的调整范围约为±122ppm。如果计算出的N超出此范围,说明晶体偏差太大,可能需要更换晶体。
  5. 写入寄存器:将计算出的N值(转换为二进制补码格式)写入0x12寄存器。

5.2 实战校准流程示例

假设我们通过串口从已联网的电脑获取精确的UTC时间作为参考。

// 简化版的校准函数,需在实际项目中完善错误处理 int s35390a_calibrate(void *hdev, int measured_error_seconds, int measurement_period_seconds) { // 1. 计算误差率 (ppm) // ppm = (误差秒数 / 测量总秒数) * 1,000,000 float error_ppm = ((float)measured_error_seconds / (float)measurement_period_seconds) * 1e6; // 2. 计算调谐寄存器值 N // N = -error_ppm * (2^20 / 1e6) = -error_ppm * 1.048576 float n_float = -error_ppm * 1.048576f; int8_t n = (int8_t)(n_float + 0.5f); // 四舍五入到最近的整数 // 3. 检查N是否在有效范围内(-128 ~ +127) if (n < -128 || n > 127) { printf("误差过大(%.2f ppm),超出芯片校准范围(±122 ppm)。请检查晶体或测量。\r\n", error_ppm); return -1; } // 4. 将N转换为二进制补码形式的uint8_t uint8_t offset_reg_value = (uint8_t)n; // 5. 写入时钟调谐寄存器 (地址0x12) int ret = i2c_write_reg(hdev, S35390A_I2C_ADDR, S35390A_REG_OFFSET, &offset_reg_value, 1); if (ret == 0) { printf("校准完成。写入Offset寄存器值: 0x%02X (十进制 %d)\r\n", offset_reg_value, n); printf("预期调整量: %.2f ppm\r\n", -n / 1.048576f); } return ret; }

在实际操作中,这个校准过程可以集成到产品的生产测试工装中,实现自动化校准。也可以在产品部署后,通过远程指令(如果设备有联网能力)触发自校准流程,以补偿晶体老化带来的长期漂移。

6. 低功耗系统设计整合与实测心得

将S-35390A融入一个超低功耗的电池供电系统,是它的典型应用场景。这里分享一个整合方案和实测中的关键点。

系统架构:

  • MCU:选用支持深度睡眠模式且唤醒源丰富的型号,如STM32L系列、ESP32(仅运行RTC协处理器时)。
  • 电源:主电源为3.3V LDO,备份电源为CR2032纽扣电池。
  • S-35390A:VDD接3.3V,VBAT通过1N4148二极管接CR2032。I2C上拉电阻接3.3V。/INT引脚接MCU的外部中断引脚(配置为下降沿触发)。
  • 传感器:采用同样支持低功耗模式的数字传感器,通过MCU的GPIO控制其电源开关。

工作流程:

  1. 系统上电或复位后,MCU初始化,读取S-35390A时间,检查是否需要从Flash恢复时间。
  2. MCU通过S-35390A设置一个唤醒闹钟(例如1小时后)。
  3. MCU关闭传感器电源,将自身所有外设关闭,进入“停机”或“待机”模式(Stop/Standby Mode)。此时MCU核心时钟停止,仅保留少量寄存器和SRAM内容,功耗可低至1μA以下。
  4. S-35390A依靠备份电池或主电源,以约0.5μA的电流(典型值)持续运行计时。
  5. 1小时后,闹钟时间到,S-35390A的/INT引脚输出下降沿。
  6. 这个下降沿触发MCU的外部中断,MCU从深度睡眠中唤醒。
  7. MCU重新初始化系统时钟和必要外设,读取当前时间,打开传感器电源采集数据,处理数据并通过LoRa/NB-IoT等模块上传。
  8. 任务完成后,MCU再次设置下一个闹钟,并进入深度睡眠。循环往复。

实测心得与避坑点:

  1. 中断引脚配置:务必确保MCU端将连接/INT的GPIO配置为外部中断模式,并设置为下降沿触发。同时,该引脚内部需要使能上拉,或者外部接一个上拉电阻(强烈建议外部上拉,如10kΩ)。在MCU进入深度睡眠前,必须确认该中断配置是有效的,并且不会被其他设置意外关闭。
  2. I2C总线状态:在MCU进入深度睡眠前,最好将I2C外设置于复位或禁用状态,并将SDA和SCL引脚设置为高阻输入或模拟输入模式,以避免从这些引脚漏电。唤醒后需要重新初始化I2C。
  3. 功耗测量:使用高精度的电流表(如Keysight的精密源表或专门的功耗分析仪)测量整个系统的睡眠电流。要区分“MCU单独睡眠”、“S-35390A单独供电”和“系统整体睡眠”的电流。实测中,我曾因为一个未使用的GPIO引脚配置为推挽输出低电平,而外部电路该引脚通过电阻上拉到了VCC,导致产生了数百微安的漏电流,使电池续航远低于预期。
  4. 电池寿命估算:假设CR2032电池容量为220mAh,S-35390A在备份模式下的典型电流为0.5μA,则理论续航时间为 220mAh / 0.0005mA = 440,000 小时,约50年。这看起来很长,但必须考虑电池的自放电(每年约1%)、MCU深度睡眠的漏电流(可能1-2μA)、以及电路板上其他元件的漏电流。实际设计中,整个系统的静态功耗应控制在5μA以内,才能实现数年的电池寿命。
  5. 时间保持验证:进行长时间老化测试。将设备断电(仅靠电池),放置一周或一个月,然后上电读取时间,与标准时间对比。这是验证电源切换电路、电池连接、芯片是否正常工作的最终手段。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询