一、项目描述
本项目基于 MAX32655FTHR 开发板,搭配一块彩色 LCD 屏幕,实现了对芯片内部供电电压的实时采集,并成功将 LVGL 图形库移植到该平台上,在屏幕上直观地显示采样数据。系统利用开发板内置的 ADC 模块完成电压采样,通过 LVGL 构建简洁的用户界面,使测量结果可视化,便于调试与监控。
二、硬件介绍
主控采用MX32655。MAX32655FTHR 是一款快速开发平台,可帮助工程师使用MAX32655 Arm© Cortex®-M4F和Bluetooth® 5.2低功耗(LE)快速实施超低功耗无线解决方案。该电路板还包括MAX20303 PMIC以实现电池和电源管理。0.9 x 2.6英寸小尺寸双排接头与Adafruit Feather Wing外设扩展板兼容。该电路板包括各种外设,如数字麦克风、低功耗立体声音频编解码器、128MB QSPI闪存、micro SD卡连接器、RGB指示器LED和按钮。MAX32655FTHR提供功率优化的灵活平台,以便进行快速概念验证和早期软件开发。
屏幕采用1.9寸TFT液晶显示屏彩色模块。其驱动芯片为 ST7789,分辨率为 170×320,通过 SPI 接口与 MCU通信。该屏幕具有色彩丰富、响应较快和接口简单等优点,适合在资源受限的嵌入式系统中实现图形化界面。

三、软件介绍
1.开发环境
本项目的主控芯片采用ADI推出的 MAX32655 微控制器。开发环境基于 Windows 操作系统,使用官方提供的 MAX32655 Software Development Kit(MSDK)作为底层驱动和中间件支持,并结合 Visual Studio Code 作为代码编辑与调试工具。该开发方式兼顾了开发效率与硬件控制能力,便于实现外设配置、ADC 数据采集。
2.移植LVGL
本项目采用 LVGL 9作为图形显示框架。LVGL 9 提供了更优化的渲染性能和更丰富的 UI 组件,适用于资源受限的嵌入式平台。通过适配 SPI 接口驱动 ST7789 屏幕,并结合 MAX32655 的硬件资源,项目实现了电压数据的实时可视化界面,包括数值显示、状态提示等基本交互功能。
移植 LVGL v9 的主要步骤如下:
1.获取源码
从 GitHub 下载 LVGL v9 源码(release/v9 分支)。
2.配置 lv_conf.h
复制 lv_conf_template.h 为 lv_conf.h,启用所需功能(如控件、颜色深度、缓冲区大小等)。
#define LV_COLOR_DEPTH 16
3.实现系统滴答(Tick)
在定时器中断中调用 lv_tick_inc(1),为 LVGL 提供毫秒级时间基准。
4.移植显示驱动(Display)
实现 disp_flush 回调函数,将 LVGL 像素数据写入屏幕。
void my_flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map)
{
uint16_t * buf16 = (uint16_t *)px_map; /* Let's say it's a 16 bit (RGB565) display */
int32_t x, y;
for(y = area->y1; y <= area->y2; y++) {
for(x = area->x1; x <= area->x2; x++) {
//put_px(x, y, *buf16);
LCD_DrawPoint(x,y,*buf16);
buf16++;
}
}
lv_display_flush_ready(display);
}
。
5.主程序初始化与轮询
调用 lv_init() 初始化 LVGL。
初始化上述移植层。
在主循环中定期调用 lv_timer_handler()。
6.编译链接
MSDK使用makefile来构建工程,要在project.mk中将 LVGL 源文件加入工程,并正确设置头文件路径。
IPATH += lvgl
IPATH += lvgl/src
VPATH += lvgl/src
include ./lvgl/lvgl.mk
3.软件设计
软件整体运行流程如下:系统上电后,首先完成硬件和软件模块的初始化,包括彩色 LCD 屏幕的配置、LVGL的初始化,并创建控件进行绘图,以及 MAX32655 内部 ADC 模块的设置。初始化完成后,程序进入主循环,在每次循环中通过 ADC 采集目标芯片的电压数据,并将采样结果传递给 LVGL 界面进行实时更新。,将采集到的AD值直观地呈现在屏幕上。

本项目中,MCU 与屏幕通过软件 SPI 通信。屏幕初始化主要包括以下步骤:配置相关 GPIO 进行硬件复位、开启背光,并按 ST7789 数据手册要求发送初始化指令序列。完成初始化后,便可通过软件 SPI 向屏幕写入像素数据,实现内容显示。
调用lv_init();函数初始化LVGl
lv_display_t * display = lv_display_create(TFT_HOR_RES,TFT_VER_RES );
static uint8_t buf1[TFT_HOR_RES * TFT_VER_RES / 10 * BYTES_PER_PIXEL];
static uint8_t buf2[TFT_HOR_RES * TFT_VER_RES / 10 * BYTES_PER_PIXEL];
lv_display_set_buffers(display, buf1, buf2, sizeof(buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_flush_cb(display, my_flush_cb);
在 MSDK 中,ADC 的初始化只需调用一个函数即可完成,简化了配置流程。该函数内部已封装好时钟、通道和采样参数等设置,用户如果不需要特殊配置,便可快速启用 ADC 模块进行采集。
MXC_ADC_Init();
接着创建所需的 LVGL 控件,包括多个容器,和用于显示 ADC 采集到数据的标签。这些控件通过 LVGL 的 API 进行配置和布局,并在主循环中根据实时采样值动态更新,实现直观的界面反馈
con1 = lv_obj_create(lv_scr_act());
con2_1 = lv_obj_create(con1);
con2_2 = lv_obj_create(con1);
label1 = lv_label_create(con2_1);
label2 = lv_label_create(con2_2);
adc1 = lv_label_create(con2_1);
adc2 = lv_label_create(con2_2);
最后,在主循环中周期性地读取 ADC 采集的数值,并将结果更新到 LVGL 界面上对应的控件中,实时显示。
value1 = MXC_ADC_StartConversion(MXC_ADC_CH_VDDIO);
value2 = MXC_ADC_StartConversion(MXC_ADC_CH_VDDIOH);
sprintf(arr1," %d ",value1);
sprintf(arr2," %d ",value2);
lv_label_set_text(adc1,arr1);
lv_label_set_text(adc2,arr2);
四、结果展示
结果如下图,

两个ADC通道分别采集的是芯片内部的电压VDDIO和VDDIOH,在数据手册查得电压和计算公式如下图,其中ADC参考电压为默认的内部参考1.22V;


经过计算371/1023*1.22*4=1.77 699/1023*1.22*4=3.33 可知结果正确。
五、遇到的困难及心得
本次项目的主要难点在于 LVGL 的移植。一方面,我对 LVGL 的架构和驱动模型,如显示缓冲区配置、flush_cb 回调函数等不够熟悉,初期在对接屏幕驱动时走了不少弯路;另一方面,对 MSDK 的 Makefile 结构和 GCC 编译流程掌握不足,导致在集成 LVGL 源码时频繁遇到路径、宏定义和链接问题。
通过查阅官方文档和参考示例工程,逐步理清了构建逻辑,最终成功将 LVGL 9 移植到 MAX32655 平台并实现数据显示。
这次活动项目让我认识到,在嵌入式开发中,除了硬件驱动能力,构建系统和第三方库的集成同样关键,也促使我今后更加重视模块化验证和前期技术调研。