你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

NUCLEO-H5E5ZJ 移植 ST7735 SPI LCD 驱动

[复制链接]
lugl 发布时间:2026-10-16 22:02
NUCLEO-H5E5ZJ 移植 ST7735 SPI LCD 驱动
日期:2026-10-16Zephyr 版本:v4.4.0目标板:NUCLEO-H5E5ZJ(STM32H5E5ZJT6)移植产物:D:\STM32\STM32H5E5\NUCLEO_H5E5ZJ\apps\lcd_demo

* D# j- m- c6 L5 L" n4 ]
0. 效果
LCD 显示黑底三行文字(NUCLEO-H5E5ZJ / ST7735 160x128 / SPI4 10MHz OK),下半屏每秒循环刷红→绿→蓝→白色块;串口同步打印进度。已在实物上验证通过。
1. 硬件分析1.1 LCD 扩展板
  • 屏幕:1.8" ST7735,128×160,RGB565,SPI 模式 0,10 MHz;
  • 驱动为裸 SPI 时序(lcd_bare.c),初始化序列:SWRESET → SLPOUT → COLMOD(0x05) → MADCTL(0x60,rotation 3 横屏 160×128) → DISPON,列偏移 1、行偏移 2;
  • CS、DC 为软件 GPIO 控制;背光 LEDA 硬件常亮(+5V 经 220Ω),RST 接板级复位线,软件均无需控制;
  • 扩展板插在 Arduino 排针上,占用 D8(DC)、D10(CS)、D11~D13(SPI)。

    ) L0 b  e8 q0 v; f5 \/ \) M
1.2 确定 H5E5ZJ 的 Arduino 引脚:看原理图,别看 UM 表格
UM3601 的 Arduino 表格是双栏排版,PDF 文本提取后行列错位无法直接使用,因此直接渲染 MB2129 原理图第 5 页(Connectors)确认:
mb2129_connectors_p5.png
放大 CN5(Arduino D8~D15)/ CN9(D0~D7)区域:
mb2129_arduino_cn5_cn9.png
读图结果(左侧青色为 Arduino 丝印,右侧为 MCU 引脚与复用功能):
Arduino 位H5E5ZJ 引脚复用功能
  X8 M! s0 k# h% }1 D  CD13 (SCK)PE12SPI4_SCK
0 b  K" }3 q) t4 ?- q: hD12 (MISO)PE13SPI4_MISO
3 ]; H9 m  T' A$ i, c  yD11 (MOSI)PE14SPI4_MOSI
# x6 r! C2 ~) O+ S2 s+ |: d9 }" CD10 (NSS)PE11SPI4_NSS& ^) |0 Y' U0 E4 Q) Y9 L: o
D9PF4TIM2_CH4
: q0 v$ E/ K1 ]5 D+ D0 C( {: YD8PA9TIM1_CH22 p5 U3 S! B- l7 Z3 w# z; A1 x
D7PE9TIM1_CH17 B2 E& W' v6 ^  }% g
D6PF3TIM2_CH3
结论:H5E5ZJ 的 Arduino SPI 是 SPI4(PE12/PE13/PE14)。LCD CS 用 D10=PE11(GPIO 软件控制),DC 用 D8=PA9(GPIO)。
1.3 pinctrl 可行性与资源冲突核对
在 hal_stm32 模块的 dts/st/h5/stm32h5e5zjtx-pinctrl.dtsi 中确认四个 SPI4 引脚节点都存在:
spi4_sck_pe12 / spi4_miso_pe13 / spi4_mosi_pe14 / spi4_nss_pe11
同时确认无资源冲突:已移植的以太网(RMII)占用 PA1/PA2/PA5/PB12/PC1/PC4/PC5/PD1/PG12,与 SPI4 引脚、PE11、PA9 均无交叠。
2. 逐步实现第 1 步:准备驱动源码
应用目录 apps/lcd_demo/ 结构如下:
apps/lcd_demo/8 l# Q) N+ o5 ]! m% }3 i) U
├── CMakeLists.txt0 G% p- y$ E* @# J1 e' ^$ O7 R
├── prj.conf3 K) }9 r1 V% n4 ^' g& m4 A/ r
├── boards/
( @- @( g$ J- P. L$ I. [│   └── nucleo_h5e5zj.overlay
& }. [& ~- M8 J( k! `; s3 D; J├── dts/bindings/display/% I6 e$ O: d& U; @
│   ├── uniknect,lcd-bare.yaml      # display shim 绑定! U3 S9 L  f; m
│   └── uniknect,lcd-io.yaml        # DC/CS GPIO 绑定(见第 3 步)! b. W7 x& s4 e6 U: Y7 s1 c
└── src/
+ t" h- ]2 `* r- t: Y    ├── main.c                      # 演示:刷屏 + 文字
! [5 ?$ A, G; ?6 B    ├── lcd_bare.c / lcd_bare.h     # ST7735 裸 SPI 驱动3 J; Z. P; t9 O" a  i, l3 w: p
    ├── display_bare.c              # 包装成 Zephyr display API 的 shim(供 LVGL)9 [8 Y8 \9 `2 d4 T+ t- _/ E
    └── font_petme128_8x8.h         # 8×8 字库第 2 步:写板级 overlay(boards/nucleo_h5e5zj.overlay)/ {5 Q$ s1 r5 V/ C( C5 H* r
    chosen {8 S- R4 w5 t' d
        zephyr,display = &lcd_bare;- o) S' p, T( A9 u$ r* }
    };
$ G+ w- O4 f% o​2 U6 ?2 g! Y; S
    /* display shim:供 LVGL */1 L) h% z6 a) _% Z' S& e: G
    lcd_bare: lcd-bare {
. m# }/ H8 z" u# |/ B        compatible = "uniknect,lcd-bare";% x& U4 i, z3 }) z- m
        width = <160>;
4 ~7 j( m$ H& ?# O$ c& q; g        height = <128>;% j0 I6 d) q! F$ F
        status = "okay";. }: p! O! F( q9 E4 S' Q
    };
) L+ S; Y3 y5 h+ T8 K+ \​4 Q- S3 \# H* i# R4 a
    /* lcd_bare 驱动的板级 IO 配置 */
% x& X( }( l' {) p5 f# g  k    lcd_io: lcd-io {
0 m+ z% u6 F$ @+ b8 T& Q# }        compatible = "uniknect,lcd-io";
- T2 z. `% v# c% h8 s: G$ }# ~        dc-gpios = <&gpioa 9 GPIO_ACTIVE_HIGH>;   /* Arduino D8 */
# C" P. J/ }. S        cs-gpios = <&gpioe 11 GPIO_ACTIVE_LOW>;   /* Arduino D10 */) z9 Y& G: n8 Q
    };3 k5 ^( V$ I( J- _! ?, F
​* I- h- C9 V* k( ]5 m* [8 p1 F  o" v
    aliases {
# p1 I5 T& W/ d- m$ S' `2 N        lcd-spi = &spi4;1 Y( \, K+ t! c0 k8 U6 M) ]8 F2 s
    };9 R4 @  n  v. z* O
};$ l! e2 Q3 S$ ]1 d3 J+ J
​
* v$ F1 ]/ ~4 E3 Y/ p6 d/* Arduino SPI(D11~D13),本板为 SPI4 */& w7 _; t; x9 e6 d$ ]
&spi4 {
* t5 r* W1 G& [0 }& t    pinctrl-0 = <&spi4_sck_pe12 &spi4_miso_pe13 &spi4_mosi_pe14>;
) u2 C0 [( i) }+ o9 k. I8 M) {    pinctrl-names = "default";
# y/ T5 j9 L2 q9 w    status = "okay";
: ~3 n. f* D0 H2 ]# `};第 3 步:驱动通过设备树取资源(板级无关设计)
驱动不硬编码任何引脚/总线,全部从设备树读取:
static const struct device *const spi_dev = DEVICE_DT_GET(DT_ALIAS(lcd_spi));& W/ g, L$ H% V# Z
static const struct gpio_dt_spec lcd_dc = GPIO_DT_SPEC_GET(DT_NODELABEL(lcd_io), dc_gpios);
3 t2 S+ x' [  V! o, u( Rstatic const struct gpio_dt_spec lcd_cs = GPIO_DT_SPEC_GET(DT_NODELABEL(lcd_io), cs_gpios);
GPIO 操作用 gpio_pin_set_dt(&lcd_dc, x) 这类按逻辑电平的 API:cs-gpios 声明为 GPIO_ACTIVE_LOW 后,set_dt(1) 即"选中",语义清晰。以后换板子只改 overlay,驱动一行不动。
第 4 步:自定义节点必须配绑定文件(踩坑点)
第一次编译报错:
error: 'DT_N_S_lcd_io_P_dc_gpios_IDX_0_VAL_pin' undeclared
原因:lcd-io 节点若没有绑定文件,devicetree 对 <&gpioa 9 GPIO_ACTIVE_HIGH> 这种带宏的属性值无法猜出类型,GPIO_DT_SPEC_GET 需要的 VAL_pin 宏就不会生成。
修复:新建 dts/bindings/display/uniknect,lcd-io.yaml(Zephyr 会自动把应用源码目录下的 dts/bindings 加入绑定搜索路径):
description: UniKnect bare LCD IO config (SPI alias + DC/CS GPIOs)- m+ G" x9 r" ~/ f
compatible: "uniknect,lcd-io"
: Z) U. d4 n. c$ r$ v+ p0 ?7 c/ iproperties:7 Z5 R( {% Q; d% y7 J" C' s- F
  dc-gpios:
- O5 {8 a8 l4 p3 h7 S$ d3 R7 j' D& P    type: phandle-array
+ u0 j) Z) z$ {$ E    required: true
% v; k0 d8 _; x' G0 Z& ~& A  cs-gpios:
! R+ O, p2 C& Y; u: e    type: phandle-array
  I! D5 n" b2 p. _5 ]  R: k    required: true
并在节点上加 compatible = "uniknect,lcd-io";。经验:自定义节点的 GPIO 属性必须在绑定里声明 type: phandle-array,不能依赖类型猜测。
第 5 步:应用骨架
prj.conf:
CONFIG_GPIO=y
+ r2 a  a1 b+ _CONFIG_SPI=y+ w6 O3 v1 h  e0 i) x
CONFIG_DISPLAY=y
CMakeLists.txt:
cmake_minimum_required(VERSION 3.20.0)) o1 u% M: l$ ]  `( y
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5 e% N0 c8 E( A/ ^2 oproject(lcd_demo)& h0 G6 j) T0 V& \4 r- G  L
target_sources(app PRIVATE src/main.c src/lcd_bare.c src/display_bare.c)
main.c 演示逻辑:display shim 在 POST_KERNEL 阶段自动完成 LCD 初始化(display_bare_init → lcd_bare_init),main 延时 500 ms 后直接调 lcd_bare_fill / lcd_bare_text / lcd_bare_fill_rect 刷屏和写文字。
第 6 步:编译、烧录、验证cd /d/luglZephyrproject& k$ x2 P3 c8 f1 F1 D! N. G
export ZEPHYR_SDK_INSTALL_DIR=/d/luglZephyrproject/zephyr-sdk-1.0.1/zephyr-sdk-1.0.1' I9 v5 B- _! X" e
​1 F( }/ P- X9 p' `+ Y
west build -b nucleo_h5e5zj /d/STM32/STM32H5E5/NUCLEO_H5E5ZJ/apps/lcd_demo \
( W( F* j. F0 S) f5 ~  -d build_h5e5_lcd -p always -- -DBOARD_ROOT=D:/STM32/STM32H5E5/NUCLEO_H5E5ZJ
" y8 U  E2 Y+ \) u7 s* owest flash -d build_h5e5_lcd
实测结果:LCD 正常点亮,文字与四色刷屏显示正确,SPI4 @ 10 MHz 工作正常,串口日志同步输出 lcd_demo: fill RED/GREEN/BLUE/WHITE。
3. 引脚速查表LCD 信号Arduino 位H5E5ZJ 引脚外设, ^! ?! v& B6 I2 h, }4 A( ]7 F$ v
SPI_SCKD13PE12SPI4_SCK
/ O# E5 f+ M5 ~( r* m+ OSPI_MISOD12PE13SPI4_MISO
) Q0 E* ^5 d4 l/ u# L+ [+ g* H( uSPI_MOSID11PE14SPI4_MOSI
- E( }  Y: x1 `4 GLCD CSD10PE11GPIO(软件控制)7 v* X$ V5 I* p5 F4 i
LCD DCD8PA9GPIO% ?/ _* g8 y3 M. U6 i
背光—硬件常亮无需控制3 s) Z& Y9 a: M# c/ B6 M& ?3 l& N7 C
RST—板级复位线无需控制4. 经验总结
  • 扩展板移植按 Arduino 位号对接,不要按 MCU 引脚名硬套——不同 Nucleo 的同一位号可能落在不同 SPI 外设上;
  • UM 的 Arduino 表格不可信(双栏 PDF 提取错位),以原理图连接器页为准,必要时渲染成图片读图;
  • 驱动里的设备引用全部下沉到设备树(alias + 自定义节点 + GPIO_DT_SPEC_GET),换板只改 overlay;
  • 自定义 dts 节点的 GPIO 属性必须写绑定(type: phandle-array),否则带宏的属性值类型猜测失败,GPIO_DT_SPEC_GET 编译报 undeclared;
  • pinctrl 节点名以 hal_stm32 模块中本芯片的 *-pinctrl.dtsi 为准,写 overlay 前先确认节点存在。
    + e- }4 i; n' j- o6 `- X5 l
5.附件,工程源码 nucleo_h5e5zj_lcd_demo.zip (11.16 KB, 下载次数: 0)
赞 收藏 评论0 发布时间:2026-10-16 22:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版