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

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

3 `2 F8 P6 G( c+ p* I* S: ^
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)。
      A1 N* `2 Y; p7 [( p- o2 b
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 引脚复用功能6 Y  |6 R! }! T0 \, s
D13 (SCK)PE12SPI4_SCK
' b, S+ m7 `2 m- |D12 (MISO)PE13SPI4_MISO3 D* m) D7 p" F6 s% A2 H% `$ C; E
D11 (MOSI)PE14SPI4_MOSI: k. D* ?4 e: G, p- g: V# n, M
D10 (NSS)PE11SPI4_NSS0 o+ x% [, G' e# _- @
D9PF4TIM2_CH4/ [5 y  k; C/ z9 s4 i
D8PA9TIM1_CH25 g! @' F0 ^: U- A
D7PE9TIM1_CH1" b: u% v; \2 d  B8 g& o1 e* ?* d
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/+ S. c5 R6 O- @) O( K
├── CMakeLists.txt
" _- G9 \/ R3 X4 u7 C) x├── prj.conf) `7 Z) L! V3 f! R6 }/ z7 I
├── boards/# V# e1 U% ~# |+ ]+ ^. n
│   └── nucleo_h5e5zj.overlay
8 T: \% l5 n, ~' T# m1 T, O, Y├── dts/bindings/display/# \5 x/ T: k1 I) J
│   ├── uniknect,lcd-bare.yaml      # display shim 绑定; a6 B' X7 e9 t# a/ m9 a) a  ?  U+ f
│   └── uniknect,lcd-io.yaml        # DC/CS GPIO 绑定(见第 3 步)
" r( ~; {+ y$ s8 o" v5 V* @└── src/
& M- v+ F0 ^& G+ o  a    ├── main.c                      # 演示:刷屏 + 文字
" m5 ^5 N7 M! k  U8 z: y    ├── lcd_bare.c / lcd_bare.h     # ST7735 裸 SPI 驱动, P0 s  H' }; P+ ?* ~' _9 o5 S
    ├── display_bare.c              # 包装成 Zephyr display API 的 shim(供 LVGL), v, h9 w0 J& [2 h
    └── font_petme128_8x8.h         # 8×8 字库第 2 步:写板级 overlay(boards/nucleo_h5e5zj.overlay)/ {
/ }# l4 z$ ]! b$ G) `    chosen {
! ?$ r  Q# M$ u! l' @$ q! H. A* D, Y* J& S        zephyr,display = &lcd_bare;
+ {0 _, [: W- R    };0 `- n% ]  Q5 m& o
​, R+ d: k. r; _/ L; w
    /* display shim:供 LVGL */
" E$ T3 v- x, K) K( U    lcd_bare: lcd-bare {& _( Q! _2 }+ ?: H0 a( N
        compatible = "uniknect,lcd-bare";& g( u* d5 ^7 w2 {! X- p# ]; b" ^
        width = <160>;
1 E  u4 _2 w& ?( [        height = <128>;( C, t  g# g/ y& Q! h. E
        status = "okay";
: J- d0 p' O8 P' E0 V* u- D    };
9 t6 a! m9 M2 A: i! r/ p2 @​
8 C( r# d1 o5 N* {9 M3 s    /* lcd_bare 驱动的板级 IO 配置 */
+ j. B) _9 _, h6 C    lcd_io: lcd-io {
% Z  B: ?/ s  C% S( o        compatible = "uniknect,lcd-io";' b+ x: J- y3 j
        dc-gpios = <&gpioa 9 GPIO_ACTIVE_HIGH>;   /* Arduino D8 */
- `5 I% m: w0 j3 k5 \6 q$ }        cs-gpios = <&gpioe 11 GPIO_ACTIVE_LOW>;   /* Arduino D10 */
9 B0 A& o8 K- ^4 M3 l    };$ f0 j; c; K; A! [! a
​- x  s. F# X( @4 S; q
    aliases {! x3 r$ W8 ?; r7 C
        lcd-spi = &spi4;) [) q+ O4 c' |! F! G1 Z
    };
" F$ S. C0 n' @9 S& m9 D};: b! O8 c' E1 ]& Y
​% G$ @0 Z9 ?! b6 \# d. O5 S
/* Arduino SPI(D11~D13),本板为 SPI4 */4 @/ ?( N  b" @% D) T( s" ?
&spi4 {
: ~# C; O: d1 M* c$ W; U& D    pinctrl-0 = <&spi4_sck_pe12 &spi4_miso_pe13 &spi4_mosi_pe14>;
2 E. g9 t7 M) k' v    pinctrl-names = "default";
' D4 g% z7 w; F, u! q7 I8 O    status = "okay";6 }. t$ M/ _- |
};第 3 步:驱动通过设备树取资源(板级无关设计)
驱动不硬编码任何引脚/总线,全部从设备树读取:
static const struct device *const spi_dev = DEVICE_DT_GET(DT_ALIAS(lcd_spi));
& U. l0 C2 _" Z# R. m: t: x: x2 |static const struct gpio_dt_spec lcd_dc = GPIO_DT_SPEC_GET(DT_NODELABEL(lcd_io), dc_gpios);: x1 |0 y/ ^; R0 i9 q1 R
static 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)2 ?4 l1 l% n6 e6 O, D1 r5 m
compatible: "uniknect,lcd-io"
4 d2 j, d% U% H$ [, [properties:
( B! G! \9 l5 \9 T& f! g# [5 b  dc-gpios:
3 N5 \. u7 k  r( T4 a: V; |0 t    type: phandle-array% o# Y3 c6 m* y4 U/ U7 P
    required: true: K. g8 ^2 @# w; O! }1 A1 s7 r
  cs-gpios:8 u+ v8 A+ l. f6 G. q  s2 _
    type: phandle-array
4 \# N( Z# u8 `$ f    required: true
并在节点上加 compatible = "uniknect,lcd-io";。经验:自定义节点的 GPIO 属性必须在绑定里声明 type: phandle-array,不能依赖类型猜测。
第 5 步:应用骨架
prj.conf:
CONFIG_GPIO=y, d3 [8 \  O- _8 J- L! x$ O
CONFIG_SPI=y# a: u* }, ^7 m. C
CONFIG_DISPLAY=y
CMakeLists.txt:
cmake_minimum_required(VERSION 3.20.0)
' X5 Q7 }2 C$ B9 B2 Z6 Zfind_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
+ u% L4 S5 ~$ }) Iproject(lcd_demo)
0 a% l2 b+ G/ y2 E' [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
) l. G7 k5 V7 d- x, Sexport ZEPHYR_SDK_INSTALL_DIR=/d/luglZephyrproject/zephyr-sdk-1.0.1/zephyr-sdk-1.0.1/ c; i% ~6 x2 t3 C
​
7 t5 A4 O" }7 d; J( Q$ xwest build -b nucleo_h5e5zj /d/STM32/STM32H5E5/NUCLEO_H5E5ZJ/apps/lcd_demo \
: E: V# G* W6 d6 [  -d build_h5e5_lcd -p always -- -DBOARD_ROOT=D:/STM32/STM32H5E5/NUCLEO_H5E5ZJ% h# L9 I$ {" q, S/ I
west flash -d build_h5e5_lcd
实测结果:LCD 正常点亮,文字与四色刷屏显示正确,SPI4 @ 10 MHz 工作正常,串口日志同步输出 lcd_demo: fill RED/GREEN/BLUE/WHITE。
3. 引脚速查表LCD 信号Arduino 位H5E5ZJ 引脚外设; b- C! J. J; k9 K$ F/ q
SPI_SCKD13PE12SPI4_SCK
, m, C3 @% J+ H( [* j5 A' [SPI_MISOD12PE13SPI4_MISO6 ]. L$ `% D, V6 |
SPI_MOSID11PE14SPI4_MOSI
9 g' h# d$ |# f; z  _LCD CSD10PE11GPIO(软件控制)
# \8 r. ?* R4 v- X" ?1 h2 c2 B9 nLCD DCD8PA9GPIO
0 v7 q# F, Q2 [背光—硬件常亮无需控制6 H( p, K! }. Z' J( {! y
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 前先确认节点存在。

    9 G& a! S3 v1 E. X
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 手机版