嵌入式应用程序是本项目的核心,其入口点为 main/main.c
。它负责初始化系统、驱动UI、并在一个主循环中处理所有事件。其设计核心是平台无关性,通过CMake和C预处理器宏,实现了PC与ARM平台的代码复用。
应用程序启动流程
程序启动后,严格遵循以下初始化顺序:
LVGL核心初始化:
lv_init()
: 初始化LVGL库。lv_log_register_print_cb()
: 注册日志回调,以便在printf
中看到LVGL的内部日志。lv_fs_posix_init()
: 初始化基于Posix的文件系统接口,供LVGL使用。
平台特定初始化 (Platform-Specific Init):
- 时间同步 (仅ARM): 在ARM平台上,会调用
sync_time_on_startup()
函数,通过执行ntpd
等shell命令来同步网络时间并更新硬件时钟(RTC)。 - HAL初始化 (
hal_init
): 这是平台适配的关键。内部通过#if USE_SDL
宏来判断:- PC平台: 调用
sdl_init()
并注册SDL的显示和输入(鼠标、键盘)驱动。 - ARM平台: 调用
fbdev_init()
和evdev_init()
并注册Linux Framebuffer显示驱动和evdev触摸/鼠标输入驱动。
- PC平台: 调用
- 时间同步 (仅ARM): 在ARM平台上,会调用
服务与模块初始化 (Services & Modules Init):
lv_png_init()
: 初始化LVGL的PNG图片解码器。hardware_init()
: 初始化硬件抽象层,打开/dev/Led
等设备文件。restore_persisted_states()
: 关键步骤。调用state_store
模块的load函数,读取上次保存的状态,并立即通过control_led/buzzer
函数将硬件恢复到该状态。mqtt_client_start()
: 启动MQTT客户端,使其在后台线程开始连接并处理网络消息。
UI加载与主循环:
demo_dashboard()
: 调用此函数来创建并显示初始界面(仪表盘)。- 进入主循环: 程序进入
while(1)
无限循环,在循环中以5毫秒的间隔不断调用lv_timer_handler()
。这是LVGL的心跳,负责驱动所有UI渲染、动画和事件处理。