1. 项目概述:一块IPS LCD屏在嵌入式Linux里到底要“唤醒”几次?
你手头刚拿到一块标着“5.0英寸、800×480、RGB接口、IPS面板”的LCD模组,芯片方案写着RK3328,配套的开发板跑的是Buildroot定制的Linux 3.10内核。你兴冲冲把屏接上,烧好镜像,通电——黑的。不是背光不亮那种黑,是彻底没信号、没初始化、连个雪花点都没有的“哲学黑”。这时候翻手册,发现驱动代码里一堆lcdc,dtsi,panel-simple,mipi_dsi,rgb,timing,vcc-lcd,vcc-iovcc……术语像雪片一样砸过来。别急,这不是你水平问题,而是嵌入式Linux驱动LCD这件事,本质上是一场多层协议握手+时序校准+电源协同+硬件抽象匹配的系统工程。它不像Windows下装个显卡驱动点几下就完事,而更像给一台老式机械钟表调校游丝、摆轮、擒纵叉——差0.1毫米,整点就不响。
我做过不下二十块不同尺寸、不同接口(RGB/MIPI DSI/LVDS)、不同厂商(群创/友达/天马/京东方)的LCD屏在ARM平台上的适配,从全志H3到瑞芯微RK3566,再到NXP i.MX8MP。最常被低估的,就是“驱动一块IPS LCD”这七个字背后的真实工作量:它绝不是复制粘贴一段设备树就能点亮的“功能开关”,而是一个需要你同时理解硬件电气特性、显示控制器寄存器映射、Linux DRM/KMS子系统抽象模型、面板时序参数物理意义、以及Bootloader与Kernel启动阶段资源移交机制的综合实践。尤其IPS屏,它的视角宽、色彩好,但对VCOM电压、Gamma曲线、时序容限比TN屏更敏感,一个hbp(水平后沿)参数设错5个像素,整屏就花屏;vfp(垂直前肩)少2行,开机LOGO就切掉一半。这篇文章,就是把我踩过的所有坑、记下的所有参数换算公式、调试时必开的三个日志开关、以及如何用示波器和逻辑分析仪交叉验证信号质量的经验,全部摊开讲透。适合正在调试LCD却卡在“黑屏/白屏/闪屏/偏色/触摸不同步”的嵌入式开发者、高校电子类课程设计学生,以及想真正搞懂Linux显示子系统底层逻辑的固件工程师。核心关键词:CLP嵌入式Linux、IPS LCD驱动、RGB接口、设备树dts、RK3328、LCD时序、DRM/KMS、背光控制、panel-simple。
2. 整体设计思路拆解:为什么不能直接抄别人dts?三层抽象必须对齐
很多初学者一上来就去GitHub搜“rk3328 lcd dts”,找到一个看似匹配的设备树片段,改几个引脚号就烧写,结果失败。根本原因在于,他们忽略了嵌入式Linux显示驱动的三层抽象模型,而这三层,必须严丝合缝地对齐,缺一不可。这不是软件配置,而是软硬协同的“协议栈”。
2.1 第一层:硬件物理层——你的屏到底长什么样?
这是所有工作的起点,也是最容易被跳过的一步。你拿到的“IPS LCD模组”,它不是一个黑盒子,而是一个由多个子模块组成的系统:
- 显示面板(Panel):决定分辨率、刷新率、色彩位深(通常是18-bit或24-bit RGB)、是否支持局部刷新。
- 时序控制器(TCON):有些模组把TCON集成在板上,有些则由SoC内部LCD控制器(LCDC)承担。RK3328的LCDC是典型的“RGB并口输出型”,它不带MIPI PHY,所以必须走RGB接口。
- 背光单元(Backlight):LED灯条 + 恒流驱动IC(如LP5523),由PWM或DC调光控制。
- 电源管理(Power Sequencing):IPS屏对上电时序极其敏感。典型顺序是:先上
VCC_IO(1.8V)→ 等待VCC_CORE(3.3V)稳定 → 再上VCC_LCD(5V或12V)→ 最后发复位信号(RESET#)。这个顺序错半毫秒,屏可能永久锁死,必须靠硬件电路(RC延时)或软件延时(在dts中配置reset-gpios和enable-gpios的linux,phandle)来保证。
我见过太多人因为没看懂模组背面的丝印,把VCC_LCD当成VCC_IO接到3.3V上,结果烧毁TCON芯片。所以第一步,永远是:拍下模组正反面高清图,对照规格书(Datasheet)逐字确认每个焊盘定义、电压范围、电流需求、复位极性(高有效还是低有效)、背光控制方式(PWM频率要求多少Hz?占空比范围?)。没有规格书?立刻联系供应商索要,没有它,后面全是蒙眼开车。
2.2 第二层:SoC驱动层——RK3328的LCDC控制器怎么干活?
RK3328的显示子系统叫VOP(Video Output Path),它包含两个独立的VOP单元(VOPB/VOPM),支持RGB、LVDS、eDP输出。我们用的是RGB模式,其核心寄存器组包括:
GRF_SOC_CON:全局复位和时钟门控寄存器,控制VOP时钟使能。VOP_REG_CFG:主配置寄存器,设置输出格式(RGB666/RGB888)、数据极性(CLK/DE/HSYNC/VSYNC的上升沿/下降沿采样)。VOP_DSP_BKGD:背景色寄存器,开机未初始化时显示的颜色,可用来快速判断VOP是否已启动。VOP_DSP_HACT_ST/END:水平有效区域起始/结束位置,直接对应hactive(有效像素数)。VOP_DSP_VACT_ST/END:垂直有效区域起始/结束位置,对应vactive。
关键点在于:VOP本身不理解“800×480”这个分辨率,它只认“一行多少像素、一帧多少行、每行之间间隔多少像素、每帧之间间隔多少行”这些时序参数。这些参数,就是我们常说的timing,它必须和LCD模组规格书里的HSYNC,VSYNC,DE时序图完全一致。比如规格书说HSYNC脉宽是48像素,那么hsw(horizontal sync width)就必须设为48;如果VSYNC脉宽是3行,vsw(vertical sync width)就是3。这些值不是估算的,是示波器实测出来的铁证。
2.3 第三层:Linux内核抽象层——DRM/KMS与panel-simple的博弈
Linux内核从3.19开始,逐步将旧的fbdev框架迁移到DRM(Direct Rendering Manager)/KMS(Kernel Mode Setting)框架。这对LCD驱动意味着什么?简单说:fbdev是“我给你一块内存,你画什么我不管”,而DRM/KMS是“我管你画在哪、怎么画、画多快、谁来画”。它引入了drm_panel、drm_connector、drm_crtc、drm_encoder等对象,形成一个标准的面向对象驱动模型。
panel-simple正是这个模型下的一个通用驱动,它不针对某一款屏,而是通过设备树描述屏的物理参数,由内核动态生成drm_panel实例。它的优势是代码简洁、维护成本低;劣势是灵活性差,无法处理需要复杂初始化序列(如MIPI DSI的多条write命令)的高端屏。对于RGB接口的IPS屏,panel-simple恰恰是最优解——因为RGB接口本身就是一个“即插即用”的并行总线,只要时序对了,屏就会自己解析数据。
所以,整个设计思路就清晰了:硬件层提供准确的电气与时序参数 → SoC层用VOP寄存器精确生成符合该时序的RGB信号 → 内核层用panel-simple驱动,通过设备树将硬件参数注入DRM框架,完成抽象匹配。任何一层脱节,都会导致“黑屏”。这也是为什么不能直接抄别人dts——别人的屏,hbp可能是46,你的屏是52;别人的背光PWM周期是50000ns,你的要求是100000ns。参数差一点,结果就是天壤之别。
3. 核心细节解析与实操要点:设备树里每一行都在说什么?
设备树(Device Tree)是连接硬件与内核的桥梁,对LCD驱动而言,它就是一份“屏的说明书”。下面我以一块典型的800×480 IPS RGB屏为例,逐行拆解rk3328-clp-lcd.dtsi中的关键节点,并解释每一行背后的物理意义和实操陷阱。
3.1 背光节点(backlight):别让PWM烧了你的LED
&backlight { status = "okay"; brightness-levels = <0 12 25 38 50 63 75 88 100 113 125 138 150 163 175 188 200 213 225 238 250 263 275 288 300 313 325 338 350 363 375 388 400 413 425 438 450 463 475 488 500>; default-brightness-level = <30>; power-supply = <&vcc_lcd>; };brightness-levels:这是一个极易被误解的数组。它不是亮度百分比,而是pwm-codes,即PWM占空比的离散化编码值。内核会把这个数组映射到0~255的brightnesssysfs接口。例如,当你echo 100 > /sys/class/backlight/backlight/brightness,内核会查表,找到最接近100的brightness-levels索引(这里是第10个,值为113),然后把这个113作为PWM duty-cycle的数值写入PWM寄存器。所以,这个数组的长度决定了你能调节多少级亮度,数值的分布决定了亮度调节是否线性。我实测过,如果数组是等差的(如<0 10 20 ... 250>),人眼感知的亮度变化是“开头很暗,中间突变,结尾很亮”,必须按伽马校正曲线来设计,比如用pow(i, 2.2)生成非线性数组。default-brightness-level = <30>:这里填的是数组的索引号,不是亮度值!<30>代表取数组中第30个元素(即400),而不是亮度400。很多新手填成<400>,结果开机背光全灭,因为索引400超出了数组长度(只有40个元素)。power-supply = <&vcc_lcd>:这行强制要求背光的供电必须和LCD面板共用同一个电源域。如果背光单独接了一个LDO,而vcc_lcd是另一个LDO,这里就必须改成<&vcc_bl>,并在根节点定义vcc_bl。否则,内核在关闭背光时,会错误地切断整个LCD电源。
提示:调试背光时,务必先用万用表直流档测量
BL_EN引脚电压。如果status = "okay"但电压为0,说明backlight节点没被正确加载,检查&backlight前面的/ { ... };是否闭合,以及rockchip,rk3328.dtsi中是否已包含backlight: backlight@ff410000的原始定义。
3.2 LCD控制器节点(vopb):时序参数的物理翻译
&vopb { status = "okay"; rockchip,output_type = <VOP_OUTPUT_RGB>; rockchip,output_mode = <VOP_OUTPUT_MODE_P888>; rockchip,rgb-mode = <VOP_RGB_RBG>; rockchip,rgb-lane = <24>; };rockchip,output_type:明确告诉VOP,我要走RGB接口,不是LVDS或eDP。填错会导致VOP内部数据通路切换错误,输出乱码。rockchip,output_mode:P888代表Pixel Format 888,即R/G/B各8位,共24-bit真彩色。如果你的屏只支持18-bit(R6G6B6),这里必须改成P666,否则VOP会把高位数据强行塞进低位,造成严重偏色。rockchip,rgb-mode:RBG是Rockchip的特有命名,指RGB数据线的物理排列顺序。R6G6B6表示R信号占D0-D5,G占D6-D11,B占D12-D17。如果接线时把R和B线接反了,这里就得改成BRG。这个参数必须和PCB走线100%一致,否则颜色全错。
3.3 面板节点(panel):panel-simple的灵魂所在
&panel { status = "okay"; compatible = "simple-panel"; #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; panel_in: endpoint { remote-endpoint = <&vopb_out>; }; }; display-timings { native-mode = <&timing0>; timing0: timing@0 { clock-frequency = <33300000>; /* 33.3MHz */ hactive = <800>; vactive = <480>; hfront-porch = <40>; hback-porch = <60>; hsync-len = <48>; vfront-porch = <13>; vback-porch = <32>; vsync-len = <3>; hsync-active = <0>; vsync-active = <0>; de-active = <1>; pixelclk-active = <0>; }; }; power-supply = <&vcc_lcd>; enable-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; reset-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; backlight = <&backlight>; };这是整个驱动的核心。我们重点看display-timings:
clock-frequency:这是像素时钟(Pixel Clock),单位Hz。它决定了屏幕刷新速度。计算公式是:PCLK = (hactive + hfront-porch + hback-porch + hsync-len) × (vactive + vfront-porch + vback-porch + vsync-len) × fps。例如,800×480@60Hz,若时序和上面一样,则PCLK = (800+40+60+48) × (480+13+32+3) × 60 ≈ 33.3MHz。这个值必须和规格书一致,误差超过±0.5%,屏就可能拒绝同步。hfront-porch/vfront-porch:前肩(Front Porch),即DE(Data Enable)信号在HSYNC/VSYNC之后、有效像素之前的一段空白时间。它给TCON留出建立时间。设太小,第一列像素就花;设太大,屏幕右边出现黑边。hsync-len/vsync-len:同步脉冲宽度。必须和规格书的HSYNC Width/VSYNC Width完全相等。我曾因把vsync-len从3错写成1,导致开机LOGO顶部被切掉两行,排查了三天才发现是这里。hsync-active/vsync-active:同步信号的极性。<0>代表低电平有效,<1>代表高电平有效。这个必须用示波器实测HSYNC引脚的波形来确定。很多规格书写的“TTL Level”,其实是指电平范围,不是极性,极性得自己抓波形。
注意:
enable-gpios和reset-gpios的GPIO_ACTIVE_HIGH/LOW必须和模组的复位电路设计一致。常见错误是:模组要求RESET#低电平复位,但电路设计成高电平复位,此时reset-gpios必须写GPIO_ACTIVE_HIGH,否则一上电就复位,屏永远起不来。
4. 实操过程与核心环节实现:从编译到点亮的完整流水线
现在,我们把所有理论知识,变成一条可执行的、零容错的实操流水线。整个过程分为四个阶段:环境准备 → 设备树编写与编译 → 内核配置与编译 → 系统烧写与调试。我会给出每一步的精确命令、预期输出、以及最关键的“现场记录”。
4.1 环境准备:工具链与源码版本的硬性约束
你必须使用与RK3328官方SDK严格匹配的工具链和内核版本。我推荐的黄金组合是:
- 交叉编译工具链:
aarch64-linux-gnu-gccversion 7.3.0(来自Linaro官网下载的gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz)。不要用Ubuntu自带的gcc-arm-linux-gnueabihf,它不支持AArch64指令集。 - 内核源码:
https://github.com/rockchip-linux/kernel.git的release-3.10分支。不要用主线内核(5.x/6.x),RK3328的VOP驱动在主线中尚未完全成熟。 - Buildroot:
https://github.com/buildroot/buildroot.git的2020.02.x长期支持分支。它内置了对RK3328的完整支持,且默认启用panel-simple。
验证工具链:
$ aarch64-linux-gnu-gcc --version aarch64-linux-gnu-gcc (Linaro GCC 7.3-2018.05) 7.3.0如果输出是gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1),说明你用错了本地gcc,立刻卸载并安装正确的交叉工具链。
4.2 设备树编写:如何从规格书生成dtsi文件?
假设你的规格书给出了以下关键时序(单位:pixel/clock):
| 参数 | 值 | 物理意义 |
|---|---|---|
H Active | 800 | 一行有效像素数 |
H Front Porch | 40 | HSYNC后到有效像素开始的时间 |
H Back Porch | 60 | 有效像素结束后到HSYNC开始的时间 |
H Sync Width | 48 | HSYNC脉冲宽度 |
V Active | 480 | 一帧有效行数 |
V Front Porch | 13 | VSYNC后到有效行开始的时间 |
V Back Porch | 32 | 有效行结束后到VSYNC开始的时间 |
V Sync Width | 3 | VSYNC脉冲宽度 |
Pixel Clock | 33.3 MHz | 像素时钟频率 |
那么,你的rk3328-clp-lcd.dtsi中timing0节点应严格写为:
timing0: timing@0 { clock-frequency = <33300000>; hactive = <800>; vactive = <480>; hfront-porch = <40>; hback-porch = <60>; hsync-len = <48>; vfront-porch = <13>; vback-porch = <32>; vsync-len = <3>; hsync-active = <0>; /* 实测为低有效 */ vsync-active = <0>; /* 实测为低有效 */ de-active = <1>; /* DE高电平有效 */ pixelclk-active = <0>; /* 像素时钟下降沿采样 */ };现场记录:我在调试一块天马TM050RDH03屏时,规格书写的pixelclk-active = <1>(上升沿采样),但实测发现,只有设成<0>,屏幕才能稳定显示。这是因为TCON芯片内部有半个周期的延迟。这个结论,是我在逻辑分析仪上同时抓取CLK和D0信号,观察数据建立/保持时间后得出的。所以,规格书是参考,实测才是真理。
4.3 内核配置:必须打开的五个开关
进入内核源码目录,运行make menuconfig,确保以下选项被选中(*表示编译进内核,M表示编译为模块):
Device Drivers→Graphics support→Support for frame buffer devices→Enable firmware EDID(CONFIG_FB_EDID=y)Device Drivers→Graphics support→Display device support→Simple panel(CONFIG_DRM_PANEL_SIMPLE=y)Device Drivers→Graphics support→Direct Rendering Manager→Rockchip DRM/KMS Driver(CONFIG_DRM_ROCKCHIP=y)Device Drivers→Graphics support→Direct Rendering Manager→DRM Panel Orientation and Rotation(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y)Device Drivers→Pin controllers→Rockchip pinctrl driver(CONFIG_PINCTRL_ROCKCHIP=y)
特别注意第4项CONFIG_DRM_PANEL_ORIENTATION_QUIRKS。它允许你在设备树中添加orientation = <90>来旋转屏幕,而无需修改应用层代码。这对于竖屏设备(如POS机)是刚需。
编译命令:
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs编译成功后,arch/arm64/boot/dts/rockchip/rk3328-clp-lcd.dtb文件必须存在,且大小在15KB左右。如果为0KB,说明设备树语法错误,用dtc -I dts -O dtb -o /tmp/test.dtb rk3328-clp-lcd.dtsi单独编译测试。
4.4 系统烧写与终极调试:三步定位黑屏根源
烧写镜像后,如果还是黑屏,按以下顺序排查,每一步都有明确的验证方法:
第一步:确认VOP是否已启动在串口终端输入:
$ cat /sys/kernel/debug/vop/vopb/status正常输出应为:
VOPB Status: enabled: 1 format: RGB888 clk: 33300000 Hz ...如果enabled: 0,说明VOP驱动没加载,检查&vopb { status = "okay" }是否生效,以及rockchip,rk3328.dtsi中vopb节点是否被正确包含。
第二步:确认panel-simple是否绑定
$ dmesg | grep -i "panel\|drm"查找关键日志:
[ 1.234567] [drm] Initialized rockchip 1.0.0 20140818 for display-subsystem on minor 0 [ 1.234589] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013). [ 1.234612] [drm] No driver support for vblank timestamp query. [ 1.234634] [drm] simple-panel panel@0: [drm:drm_panel_add] *ERROR* panel already registered最后一行panel already registered是正常现象,表示panel-simple已成功注册。如果看到failed to add panel或no panel found,说明设备树中&panel节点路径错误,或compatible = "simple-panel"拼写错误。
第三步:用fbtest进行终极验证Buildroot默认不带fbtest,需手动添加:
# 在buildroot目录下 $ make menuconfig # 进入 `Target packages` -> `Graphic libraries and applications` -> `fbset` 和 `fbtest` # 保存退出,重新`make`烧写新镜像后,在终端运行:
$ fbtest -T 1 -c 1-T 1表示测试模式1(红绿蓝三色填充),-c 1表示循环1次。如果屏幕依次显示纯红、纯绿、纯蓝画面,说明RGB数据通路100%正常,问题一定出在背光或电源上。此时,用万用表量BL_EN,如果为0V,再检查&backlight节点和&panel中的backlight = <&backlight>是否连通。
实操心得:我给自己定了一条铁律——每次修改设备树后,必须执行
dmesg | tail -50,并搜索vop\|panel\|backlight三个关键词。90%的黑屏问题,答案就藏在这50行日志里。日志里不会告诉你“你参数设错了”,但它会说vopb: invalid timing或backlight: failed to get supply,这就是最精准的诊断书。
5. 常见问题与排查技巧实录:那些让我熬夜到凌晨三点的Bug
在真实项目中,问题从来不会按教科书的顺序出现。下面是我整理的“IPS LCD黑屏问题速查表”,按发生频率从高到低排序,并附上独家排查技巧。
5.1 问题速查表:症状、原因、解决方案、验证方法
| 序号 | 症状 | 最可能原因 | 解决方案 | 验证方法 |
|---|---|---|---|---|
| 1 | 屏幕全黑,背光不亮,串口有log | &backlight节点未启用,或power-supply指向错误 | 检查&backlight { status = "okay" },确认power-supply = <&vcc_bl>中的vcc_bl已在根节点正确定义 | cat /sys/class/backlight/backlight/brightness,如果报No such file,说明backlight驱动未加载 |
| 2 | 屏幕全黑,背光亮,串口log显示vopb: no panel found | &panel节点中compatible值错误,或port@0的remote-endpoint未指向&vopb_out | 将compatible = "simple-panel"改为"rockchip,rk3328-lcd"(如果厂商提供了专用驱动),或检查&vopb_out是否在&vopb节点内正确定义 | `dmesg |
| 3 | 屏幕有微弱灰度,但无图像,或图像严重偏色 | rockchip,rgb-mode设置错误,或rockchip,output_mode与屏的位深不匹配 | 用示波器抓取D0-D23,确认R/G/B数据线物理顺序;查阅规格书确认是18-bit还是24-bit | 修改rgb-mode后,运行fbtest -T 1,观察红绿蓝是否纯净 |
| 4 | 屏幕显示雪花、横纹、大面积色块 | clock-frequency误差过大,或hsync-active/vsync-active极性错误 | 用示波器实测CLK频率,用逻辑分析仪抓HSYNC波形,确认高低电平有效 | dmesg中会出现vopb: invalid timing警告 |
| 5 | 开机LOGO显示正常,但进入Linux桌面后黑屏 | X11或Wayland服务未正确配置DRM后端,或/etc/X11/xorg.conf中Driver "modesetting"未启用 | 在/etc/X11/xorg.conf中添加Section "Device",指定Driver "modesetting",并禁用fbdev | `ps aux |
5.2 独家避坑技巧:那些文档里永远不会写的细节
技巧一:用/sys/kernel/debug/vop/目录做实时诊断这个debugfs目录是RK平台的宝藏。除了前面提到的status,还有:
/sys/kernel/debug/vop/vopb/regs:实时dump所有VOP寄存器值,可确认clock-frequency是否被正确写入。/sys/kernel/debug/vop/vopb/clk:显示当前VOP时钟源和分频系数,可验证PCLK是否真的达到了33.3MHz。/sys/kernel/debug/vop/vopb/irq:显示中断触发次数,如果为0,说明VOP没产生任何帧中断,问题一定在时序或电源。
技巧二:fbset命令的隐藏用法fbset不仅能查,还能改。在调试时,可以临时覆盖设备树中的时序:
$ fbset -xres 800 -yres 480 -vxres 800 -vyres 480 -depth 24 -pixclock 30030 -left 40 -right 60 -upper 13 -lower 32 -hsync 48 -vsync 3这个命令会直接向VOP寄存器写入新的时序参数,无需重启。如果这样能点亮,说明你的设备树参数肯定有误,只需对比fbset -s输出的当前值,就能快速定位是哪个参数错了。
技巧三:逻辑分析仪的“双触发”捕获法单靠示波器看HSYNC,只能知道极性。要精确测量hfront-porch,必须用逻辑分析仪,设置双触发条件:第一次触发在VSYNC下降沿,第二次触发在HSYNC下降沿,然后测量两者之间的时间差。这个差值,就是vfront-porch。同理,hfront-porch是HSYNC下降沿到DE上升沿的时间。这个方法,让我在一次客户现场,30分钟内就修正了被供应商搞错的时序参数。
技巧四:背光PWM的“静默测试”如果怀疑背光驱动有问题,但又不想每次都烧写镜像,可以用debugfs直接控制:
$ echo 0 > /sys/kernel/debug/pwm/pwmchip0/pwm0/duty_cycle $ echo 10000000 > /sys/kernel/debug/pwm/pwmchip0/pwm0/duty_cycleduty_cycle单位是纳秒,period是固定的(由&pwm0节点中的rockchip,pwm-period-ns = <100000000>定义)。这样,你可以绕过整个backlight子系统,直接用硬件PWM验证LED灯条是否完好。
最后再分享一个小技巧:当所有软件手段都失效时,拿出你的万用表,调到二极管档,逐个测量LCD排线座子上的每一个引脚对地的压降。正常的VCC_IO(1.8V)引脚,压降应该在1.7~1.8V之间;GND引脚压降为0;RESET#在未复位时应该是高电平(压降≈1.8V),复位时变为0。如果某个引脚压降是0.3V,那它大概率是虚焊或者PCB断线。这个土办法,在我解决一个因PCB沉金不良导致的间歇性黑屏问题时,立了大功。嵌入式的世界里,有时候最原始的工具,反而最可靠。