# 工单 WO-07:完善日期功能 (年/月/日/星期) **优先级**:中 **状态**:待处理 --- ## 问题列表 1. 软时钟(`App/clock.c`)只有时/分/秒,没有年、月、日、星期。 2. `PCF8563_ReadTime`/`PCF8563_WriteTime` 只读写时分秒三个寄存器,芯片本身支持的日/星期/月/年寄存器(0x05~0x08)从没被用过。 3. `set_clock_app` 只能调小时和分钟,没有日期可调。 4. HOME APP 和时间设置界面上显示的"星期 日-月"是写死的占位字符串 `"VEN 10-07"`/`"FRI 10-07"`,不是真实日期。 --- ## 实现思路 ### 1. 驱动层:`Drivers/pcf8563.c`/`.h` PCF8563 的秒/分/时/日/星期/月/年寄存器地址是连续的(0x02~0x08,共 7 字节),可以一次 I2C 连续读写全部拿到/写入,不用分开多次收发: - 新增 `PCF8563_ReadDateTime(u8 *hour, u8 *min, u8 *sec, u8 *day, u8 *month, u8 *year)`:从 0x02 开始连续读 7 字节,`day` 掩码 `0x3F`(BCD),`month` 掩码 `0x1F`(BCD,忽略 bit7 世纪位),`year` 直接 BCD 转十进制(0~99,代表 2000~2099)。 - 新增 `PCF8563_WriteDateTime(u8 hour, u8 min, u8 sec, u8 day, u8 month, u8 year, u8 weekday)`:从 0x02 开始连续写 7 字节,包含星期(0x06,取值 0~6,不需要 BCD 转换,直接写数值)。 - 旧的 `PCF8563_ReadTime`/`PCF8563_WriteTime` 保留,内部改成调用新函数并丢弃日期部分,避免改动现有调用点(`app_home.c`/`app_set_clock.c`)。 - 世纪位(月寄存器 bit7)不处理,固定按 2000~2099 年处理,这个产品的使用年限内不用考虑跨世纪。 ### 2. 软时钟层:`App/clock.c`/`.h` - 新增全局变量 `u8 current_day`、`u8 current_month`、`u8 current_year`(0~99,代表 2000~2099)、`u8 current_weekday`(0~6,周日=0 或周一=0,需要定一个约定,建议跟 Zeller 公式的定义保持一致)。 - `Clock_IncMS()` 现有的时/分/小时进位链条(秒→分→时)后面继续接上日/月/年进位:小时满 24 归零时,`current_day++`;根据"每月天数表"(`{31, 28或29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}`,2 月按闰年规则(能被 4 整除且(不能被 100 整除或能被 400 整除),2000~2099 区间内简化成"能被 4 整除"即可)判断是否要月进位、年进位(99 → 0,不处理世纪)。 - 日期发生变化(不管是自然进位还是手动调节)时,用 Zeller 公式或类似算法重新计算 `current_weekday`,不依赖 PCF8563 自己的星期寄存器自增(避免手动改日期后星期跟着错乱);写入 RTC 时把算出来的星期一起写进去,保持芯片内部数据一致。 - `HomeApp_OnStart()`/相关读取 RTC 的地方,从 `PCF8563_ReadTime` 换成 `PCF8563_ReadDateTime`,一并读回日期。 ### 3. 界面层:`App/ui.c`/`.h` - 新增星期缩写字符串表(法语/英语),参照现有占位文案风格:`LUN/MAR/MER/JEU/VEN/SAM/DIM` 对应 `MON/TUE/WED/THU/FRI/SAT/SUN`,放进 `App/strings.h` 的 `WRISTBAND_STRING_LIST`。 - `UI_ShowClockPage()`/`UI_ShowSetTimePage()` 里原来直接 `Lang_Get(STR_CLOCK_DATE)` 显示死文案的地方,改成拼接"星期缩写 + 日-月两位数字"的动态字符串,用真实的 `current_weekday`/`current_day`/`current_month` 现算现拼。 ### 4. 时间设置 App:`App/app_set_clock.c` - `time_edit_field` 从 1~2(时/分)扩展到 1~5(时/分/日/月/年),长按 CONFIRM 依次循环切换。 - 上下键调节日/月/年时要做合理的范围限制和循环(日 1~当月最大天数、月 1~12、年 0~99),月份变化时如果当前日超过新月份的最大天数要做截断处理(比如从 31 号切到 2 月要变成 28/29 号)。 - 局部刷新沿用 WO-06 刚做的模式,不要整屏重绘:日/月/年每个字段各自对应屏幕上一小块数字区域,只刷新当前正在调节的那一块。 - 保存(短按 CONFIRM)时用新的 `PCF8563_WriteDateTime()`,同时把算好的 `current_weekday` 一起写入。 ### 5. 需要确认的点 - 星期数值约定(0=周日 还是 0=周一)以及对应的 Zeller 公式实现需要仔细算一遍避免算错,建议实现后用几个已知日期(比如今天)手动核对星期是否正确。 - 日期显示格式沿用现有"星期 日-月"(如 "MON 03-08")这种顺序,不显示年份(屏幕位置有限);如果需要年份显示,要另外找位置或者做成可选切换。