项目名称:Funpack5-4 -基于 FRDM-MCXN236 的电子时钟系统设计与实现
1. 项目概述
本项目基于 NXP FRDM-MCXN236 开发板,设计实现了一套具备双显示与按键交互功能的电子时钟。系统以 MCXN236 片内 RTC 为时间基准,通过硬件 LPI2C 总线驱动 SSD1306 OLED 显示屏本地显示时间,同时通过 UART 串口将时间数据同步输出至上位机;用户可通过板载 SW2、SW3 两颗按键完成时间的校准设置。项目完整覆盖了嵌入式系统中时钟外设、串行通信、人机交互等核心知识点。
2. 硬件平台与方案介绍
- 主控:NXP MCXN236(Arm Cortex-M33,主频 150MHz),片内集成独立 RTC 模块,支持外部 32.768kHz 晶振输入。
- 显示模块:0.96寸 OLED(SSD1306 驱动),分辨率 128×64,I2C 接口,7 位从机地址 0x3C。
- 按键:板载 SW2(PIO0_20,主循环轮询)、SW3(PIO0_6,下降沿中断)。
- 调试接口:板载 MCU-Link 调试器,提供 UART 串口通信。
2.1.方案框图

2.2项目设计思路介绍
- 总体架构选型:系统任务数量少、实时性要求适中,采用 "前后台(超循环)+ 状态机" 架构,无需引入 RTOS 即可获得结构清晰、易于调试的代码。中断服务只承担 "最快通知" 职责(如 SW3 仅置位标志),耗时业务全部下沉到主循环处理,避免了中断嵌套与共享资源竞争问题。
- 时间基准设计:选用片内 IRTC 而非纯软件计数作为时间基准,配合外部 32.768kHz 晶振提供稳定走时,保证掉电或复位后时间不丢失,也简化了日历运算;主循环仅做 "读取 — 输出",负载极低。
- 显示与通信设计:OLED 采用 I2C 接口(两线制、占用引脚少),使用硬件 LPI2C2 外设而非 GPIO 模拟,400kHz 总线速率保证时序可靠、CPU 开销小;同时通过 UART 将时间同步到上位机,形成 "本地显示 + 远端监视" 双通道,既便于调试,也直观展示串行通信知识点。
- 人机交互设计:将调时流程抽象为四个模式的状态机(显示→时→分→秒→保存返回),以
g_local_dt作为唯一数据缓存,设置期间在本地即时刷新、退出时一次性写回 RTC,避免频繁写 RTC;SW3 负责状态迁移,SW2 负责字段增减,并通过对短按 / 长按的区分兼顾单步精度与连续调速效率。
3. 软件设计方案
系统采用前后台架构 + 状态机设计:

(1)时间模式状态机
typedef enum _time_mode {
MODE_DISPLAY, // 正常显示
MODE_SET_HOUR, // 调小时
MODE_SET_MIN, // 调分钟
MODE_SET_SEC // 调秒
} time_mode_t;
g_mode 为全局状态变量,由 SW3 短按驱动状态迁移,循环顺序为:显示→小时→分钟→秒→(保存并返回)显示。
(2)SW3 处理逻辑(KEY_SW3_Process)
- 中断服务函数
BOARD_SW_IRQ_HANDLER仅置位g_SW3_Press标志; - 主循环中检测到标志后:先 50ms 消抖 → 等待按键释放 → 再次 50ms 确认 → 执行模式切换;
- 若当前为 MODE_DISPLAY,则先从 RTC 读取当前时间到
g_local_dt缓存,再进入 MODE_SET_HOUR; - 若在设置模式中按 SW3,则按顺序切到下一模式;若当前为 MODE_SET_SEC,则将
g_local_dt写回 RTC 并回到显示模式。
(3)SW2 处理逻辑(SW2_Process)
- 采用边沿检测 + 计时器实现长短按区分:
- 短按(按住 < 200ms 后释放):调用
IncrementCurrentField()对当前字段 +1; - 长按(按住 ≥ 200ms):进入连续递增模式,
auto_increment_timer每累计 50ms 触发一次 +1,实现快速调时。
- 短按(按住 < 200ms 后释放):调用
IncrementCurrentField()根据g_mode决定递增 hour / minute / second,并对 24 或 60 取模,同时调用OLED_RefreshTime()实时刷新屏幕。
(4)双显示同步
主循环中,每当检测到 RTC 秒数变化且处于 MODE_DISPLAY 时:
PRINTF("%02d:%02d:%02d\r\n", ...); // 串口输出
OLED_RefreshTime(hour, minute, second); // OLED 刷新
OLED 显示布局:
- 第 0 页:标题 "RTC Clock"
- 第 2 页起:大字体时间
HH:MM:SS - 第 4 页起:当前状态字符串("normal display" / "SET hour" / "SET min" / "SET sec")
4. 关键代码与驱动实现
(1)LPI2C2 硬件初始化
CLOCK_SetClkDiv(kCLOCK_DivFlexcom2Clk, 1u);
CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2);
LPI2C_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Hz = 400000U;
LPI2C_MasterInit(LPI2C2, &masterConfig,
CLOCK_GetLPFlexCommClkFreq(2u));
引脚 PIO4_0/PIO4_1 在 pin_mux 中配置为 ALT2(LPI2C2_SCL/SDA),并使能内部上拉。
(2)SSD1306 写命令 / 写数据
// 写命令:控制字节 0x00 + cmd
// 写数据:控制字节 0x40 + data
// 每次传输:LPI2C_MasterStart → LPI2C_MasterSend × 2 → LPI2C_MasterStop
OLED 初始化序列严格遵循 SSD1306 数据手册,包含电荷泵开启、扫描方向、对比度等 20 余条命令。
(3)RTC 有效性检查
上电后通过 IRTC_IsTimeValid() 读取 RTC 状态寄存器,若时间无效则写入默认时间(2026-08-05 15:45:00),避免每次上电都从零点开始。
5. 调试过程与技术难点
(1)LPI2C 引脚冲突与链接错误
初版代码未将 fsl_lpi2c.c 加入工程,导致 LPI2C_MasterInit 等符号未定义;同时 PIO4_0/1 默认未配置为 I2C 功能。通过在 pin_mux 中调用 LPI2C2_InitPins() 完成 ALT2 复用,并将驱动文件加入编译,问题解决。
(2)OLED 无反应排查
- 先用 I2C 扫描确认从机地址:通过
LPI2C_MasterStart(LPI2C2, 0x3C, kLPI2C_Write)测试,串口打印 "OLED found at 0x3C" 确认通信正常; - 上电延时从 100ms 延长至 200ms,确保 SSD1306 内部复位完成;
- 最终 OLED 稳定显示。
(3)按键消抖与长按判定
SW3 采用"中断置标志 + 主循环消抖等待释放"的方案,彻底消除机械抖动;SW2 通过 press_ms 计数器区分短按/长按,长按后每 50ms 触发一次递增,兼顾了精度与速度。
6. 功能概述
系统上电后:
- OLED 第 0 页显示 "RTC Clock",第 2 页大字体显示当前时间,第 4 页显示 "normal display";
- 串口助手以 1Hz 频率打印
HH:MM:SS; - 短按 SW3 进入设置模式,OLED 状态行相应变为 "SET hour" / "SET min" / "SET sec";
- 在设置模式下,SW2 短按使当前字段 +1,长按则快速递增;
- 第四次按 SW3 保存时间到 RTC 并返回正常显示。

7. 项目心得
本项目从需求分析、硬件选型、驱动编写到整机联调,完整走过了嵌入式产品开发的全流程。最大的收获有三点:
- MCUXpresso 生态的成熟:Config Tools 图形化配置时钟和引脚,SDK 提供了完善的 LPI2C、IRTC 驱动,大幅降低底层开发难度;
- 状态机是人机交互的利器:将"显示/调时"抽象为四种状态,配合 SW3 的循环切换和 SW2 的加减操作,代码逻辑清晰且易扩展;
- 调试思维的提升:从链接错误、I2C 无应答到按键抖动,每一个 Bug 的解决都建立在对芯片手册和时序图的深入理解之上。
后续可扩展方向:加入 UART 命令解析实现电脑端校时、增加 DS18B20 温度传感器显示环境温度、或通过蓝牙模块实现手机 App 控制。