本文代码绝大部分都通过 AI 完成
基于 ESP-IDF 框架和 LVGL 图形库开发的 ESP32-S3 智能时钟,集成了网络对时、温湿度检测和电池电量显示等功能。下载链接:https://higa.teracloud.jp/share/11e2ac0228256c16
功能特点
- 实时时钟显示:使用等宽字体显示时间(时:分: 秒 年 - 月 - 日)
- 网络对时:通过 GPIO18 按键触发 WiFi 连接,使用 SNTP 协议从 NTP 服务器同步时间,同步完成后自动断开 WiFi 节省电量
- 温湿度监测:通过 SHTC3 温湿度传感器实时监测环境温度和湿度,并在界面顶部显示
- 电池电量显示:通过 ADC 采样电池电压,计算并显示电量百分比,配有电池图标

硬件平台
- 主控芯片:ESP32-S3
- 显示屏:电阻式 LCD(RLCD),分辨率 400×300,黑白双色
- 温湿度传感器:SHTC3,I2C 接口(SDA=GPIO14,SCL=GPIO13)
- 功能按键:GPIO18(触发网络对时)
- 电池电压检测:ADC 通道采样
项目结构
1 | demo/ |
代码原理详解
程序启动流程 (main.cpp)
1 | app_main() |
LVGL 界面布局 (user_app.cpp)
屏幕分辨率为 400×300,使用 6 个 lv_label 标签组成界面:
1 | ┌─────────────────────────────────────────────────┐ |
| 标签 | 位置 | 说明 |
|---|---|---|
status_label | (10, 10) | WiFi 状态(WiFi off/Connecting/Syncing/Sync done) |
temp_label | (120, 10) | 温度显示(SHTC3 读取) |
humi_label | (220, 10) | 湿度显示(SHTC3 读取) |
battery_label | (310, 10) | 电量 + 电池图标(LV_SYMBOL_BATTERY_FULL) |
time_label | 居中 | 时间显示(Courier 等宽字体 50px) |
date_label | (0, 160) | 日期显示(居中) |
时钟更新机制
使用 LVGL 定时器 lv_timer_create() 每秒执行一次回调 clock_update_cb:
1 | // 1s周期触发 |
回调函数内部逻辑:
- 调用
time()获取系统时间戳 →localtime_r()解析为时分秒年月日 snprintf()格式化字符串后写入各lv_label- 读取 SHTC3 传感器 → 更新温湿度标签
- ADC 采样 → 更新电池电量(附带
LV_SYMBOL_BATTERY_FULL图标) - 按键检查 → 网络对时状态机
按键触发网络对时流程(状态机)
核心设计原则:WiFi 按需连接,同步完成立即断开以降低功耗。
1 | GPIO18按键按下 |

SNTP 配置(sntp_time_sync):
- NTP 服务器:
ntp.aliyun.com(阿里云国内节点) - 时区:
CST-8(东八区 北京时间) - 模式:
SNTP_OPMODE_POLL(轮询模式)
WiFi 驱动设计 (esp_wifi_bsp.c)
采用 两阶段初始化 分离初始化和连接:
| 函数 | 作用 | 是否耗电 |
|---|---|---|
espwifi_Init() | 初始化 NVS/Netif/WiFi 协议栈,写入 SSID + 密码 | 初始化阶段运行 |
espwifi_Connect() | 调用 esp_wifi_start() 启动射频并连接 AP | 开启射频(耗电) |
espwifi_Disconnect() | 调用 esp_wifi_stop() 关闭射频 | 关闭射频(省电) |
WiFi 状态通过事件回调 event_handler 维护:
IP_EVENT_STA_GOT_IP→wifi_connected = trueWIFI_EVENT_STA_DISCONNECTED→wifi_connected = false
SHTC3 温湿度读取 (i2c_equipment.cpp)
SHTC3 通过 I2C 通信,设备地址 0x70,时钟速度 400kHz:
1 | 读取流程: |
电池电量检测
通过 ADC 采样电池电压,Adc_GetBatteryLevel() 内部将 ADC 采样值映射为百分比。
界面显示时使用 LVGL 内置符号 LV_SYMBOL_BATTERY_FULL 作为电池图标前缀:
1 | snprintf(battery_buf, sizeof(battery_buf), |
显示驱动与 LVGL 渲染
- 显示屏类型:电阻式 LCD(RLCD),黑白双色
- 颜色转换:LVGL 输出的 RGB565 颜色值通过阈值
0x7fff二值化(< 0x7fff为黑色,否则为白色) - 渲染流程:
- LVGL 内部将界面渲染到
color_map缓冲区 Lvgl_FlushCallback遍历像素 → 调用RLCD_SetPixel()写入屏内缓存RLCD_Display()一次性刷新整屏 →lv_disp_flush_ready()通知 LVGL 完成
- LVGL 内部将界面渲染到
字体说明
项目使用自定义等宽字体 cour.c:
- 来源:Courier New(等宽字体,适合时间显示,数字宽度一致避免抖动)
- 尺寸:50px
- 位深:1 bpp(黑白,匹配 RLCD 双色屏,最小化 Flash 占用)
- 字符范围:ASCII 32-127(空格到~,覆盖数字、字母、标点)
- 生成参数:
--bpp 1 --size 50 --no-compress --stride 1 --align 1
编译与烧录
1 | # 配置ESP-IDF环境 |
低功耗优化
- WiFi 按需连接:只有按键触发才启动射频,同步完成后立即
esp_wifi_stop()关闭 - SNTP 单次同步:使用 POLL 模式而非持续监听,避免周期性唤醒
- I2C 按需读取:每秒读取一次 SHTC3,而非持续采样
- 1bpp 字体:最小化 Flash 占用和渲染开销
下步目标
利用股票和天气 api 获取信息并显示
通过 WiFi 或者蓝牙与附近通信,更新同步信息