保姆级教程:在Petalinux下为ZYNQ Zybo板添加SPI LCD屏并运行LVGL
1. 项目概述与硬件准备
Zybo开发板搭载的ZYNQ7000系列芯片,凭借ARM Cortex-A9双核处理器与可编程逻辑的完美结合,成为嵌入式视觉应用的理想平台。本教程将实现一个完整的SPI LCD显示方案,从硬件配置到LVGL图形界面部署,特别适合需要快速验证产品原型或完成毕业设计的开发者。
硬件需求清单:
- Zybo Z7-20开发板(基于ZYNQ7020)
- 240x320分辨率SPI接口LCD模块(以ST7789V驱动芯片为例)
- MicroSD卡(建议≥8GB Class10)
- USB转UART调试器
硬件连接关键点:
- LCD的SPI接口连接至Zybo的SPI0端口
- Reset和DC控制引脚分别接入EMIO54和EMIO55
- 确保开发板供电充足(建议使用5V/2A电源适配器)
提示:不同型号LCD的初始化参数可能有所差异,建议提前查阅具体屏幕的数据手册。
2. Vivado硬件平台配置
2.1 创建基础工程
在Vivado 2018.3中新建项目时选择Zybo-Z7-20板型预设配置。关键步骤包括:
create_project zybo_lcd ./zybo_lcd -part xc7z020clg400-1 set_property board_part digilentinc.com:zybo-z7-20:part0:1.0 [current_project]2.2 处理系统外设使能
在Block Design中配置ZYNQ7 Processing System时,需要特别注意:
- 启用SPI0控制器(Full模式)
- 分配EMIO用于LCD控制信号
- 使能SD0接口用于启动介质
关键参数对比表:
| 外设接口 | 配置参数 | 备注 |
|---|---|---|
| SPI0 | Standard Mode | 时钟频率建议≤32MHz |
| EMIO | 54-55引脚 | 用于Reset和DC控制线 |
| SD0 | 4-bit模式 | 支持高速SD卡 |
2.3 生成硬件描述文件
完成设计后执行:
- Generate Output Products
- Create HDL Wrapper
- Generate Bitstream
- Export Hardware(包含bitstream)
3. Petalinux系统定制
3.1 工程初始化
在Ubuntu环境中(建议18.04 LTS):
source /opt/pkg/petalinux/2018.3/settings.sh petalinux-create -t project --template zynq -n zybo_lcd cd zybo_lcd petalinux-config --get-hw-description=<hdf文件目录>3.2 内核驱动配置
进入内核配置菜单后重点关注:
Device Drivers → Staging drivers → Support for small TFT LCD display modules → <*> FB driver for ST7789V displays [*] Enable debugging设备树关键修改(system-user.dtsi):
&spi0 { status = "okay"; st7789v@0 { compatible = "sitronix,st7789v"; reg = <0>; spi-max-frequency = <32000000>; rotate = <270>; buswidth = <8>; reset-gpios = <&gpio0 55 GPIO_ACTIVE_HIGH>; dc-gpios = <&gpio0 54 GPIO_ACTIVE_LOW>; debug = <0>; }; };3.3 根文件系统定制
添加LVGL运行所需的依赖包:
petalinux-config -c rootfs在菜单中启用:
- libsdl2
- fb-test
- evtest
- lvgl-demo
4. LVGL移植与适配
4.1 源码获取与配置
下载LVGL v8.3核心库及演示程序:
wget https://github.com/lvgl/lvgl/archive/refs/tags/v8.3.0.tar.gz tar -zxvf v8.3.0.tar.gz -C /usr/local/关键编译参数:
CFLAGS += -I/usr/local/lvgl-8.3.0 \ -DLV_COLOR_DEPTH=16 \ -DLV_USE_FBDEV=14.2 帧缓冲设备适配
创建自定义的fbdev接口实现:
static void fbdev_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) { struct fbdev_priv *priv = drv->user_data; int offset = area->y1 * priv->fb_fix.line_length + area->x1 * 2; for(int y = area->y1; y <= area->y2; y++) { memcpy(priv->fb_ptr + offset, color_p, (area->x2 - area->x1 + 1) * 2); offset += priv->fb_fix.line_length; color_p += (area->x2 - area->x1 + 1); } lv_disp_flush_ready(drv); }4.3 输入设备集成
针对触摸或按钮输入,建议采用以下事件处理框架:
void input_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { static int last_x = 0; static int last_y = 0; struct input_event ev; while(read(priv->input_fd, &ev, sizeof(ev)) == sizeof(ev)) { if(ev.type == EV_ABS && ev.code == ABS_X) { last_x = ev.value; } else if(ev.type == EV_ABS && ev.code == ABS_Y) { last_y = ev.value; } else if(ev.type == EV_KEY && ev.code == BTN_TOUCH) { >petalinux-build -c kernel6. 进阶应用示例
6.1 创建自定义UI组件
实现一个温湿度监控界面:
lv_obj_t *create_temp_humid_panel(lv_obj_t *parent) { lv_obj_t *panel = lv_obj_create(parent); lv_obj_set_size(panel, 200, 120); lv_obj_t *temp_label = lv_label_create(panel); lv_label_set_text(temp_label, "Temperature: --°C"); lv_obj_align(temp_label, LV_ALIGN_TOP_LEFT, 10, 10); lv_obj_t *humid_label = lv_label_create(panel); lv_label_set_text(humid_label, "Humidity: --%"); lv_obj_align(humid_label, LV_ALIGN_TOP_LEFT, 10, 40); return panel; }6.2 多页面管理
使用LVGL的页面管理器实现场景切换:
static void btn_event_handler(lv_event_t *e) { lv_obj_t *btn = lv_event_get_target(e); uint32_t id = lv_btnmatrix_get_selected_btn(btn); switch(id) { case 0: lv_scr_load(main_screen); break; case 1: lv_scr_load(settings_screen); break; } }实际部署中发现,当SPI时钟超过40MHz时,虽然逻辑分析仪显示信号正常,但屏幕可能出现随机噪点。这通常与LCD模块的信号建立时间要求有关,建议通过降低时钟频率或缩短布线距离来解决。