简介:这份资源面向FPGA初学者与显示驱动开发者,聚焦用Altera FPGA驱动RGB接口液晶屏并输出彩条测试画面的完整工程。内容围绕像素时钟、行场同步信号生成、并行RGB数据传输、帧缓冲配置及Quartus II综合调试等关键环节展开,可帮助读者理解从时序控制到图像显示的完整链路,适合作为TFT显示入门的实操参考。压缩包共126个文件,约3.43MB,以cdb、hdb、ddb等Quartus编译中间数据库文件为主,辅以Verilog源码、qsf工程配置、sof下载文件及readme说明,保留了工程综合与布局布线的过程痕迹,便于对照分析。已有1722人学习下载。读者可从中获得可直接打开的完整工程、彩条显示实现思路与编译排错线索,用于快速验证RGB时序参数并迁移到自有显示屏方案。
1. 从 tft_rgb_colorbar.rar 说起:一块屏点亮之前,先让彩条跑起来
手里拿到一个名为 tft_rgb_colorbar.rar 的压缩包,很多人第一反应是解压、找工程、双击打开、点下载,然后盯着屏幕等一个彩条出现。真到现场你会发现,事情没这么顺:屏不亮、颜色反了、彩条只出一半、花屏闪屏,甚至烧录器连不上。这个包本质上是一份 TFT 屏 RGB 接口的点屏验证工程,核心目标只有一个——用最少的依赖,把红绿蓝白黑几组标准彩条稳定地刷到屏上,证明时序、引脚、时钟、数据位序这几件事全对。它适合刚接手屏驱的嵌入式工程师、做显示模组的测试人员,以及需要快速判断「是屏的问题还是板子的问题」的硬件调试者。彩条不是玩具,它是点屏阶段最便宜的黑匣子:颜色对了,时序基本就对了;彩条歪了,后面所有 UI 都是白搭。
2. RGB 接口点屏的时序底座:彩条为什么能验证一整条链路
彩条看着简单,其实是把 RGB 并行接口的每一个关键信号都逼到了边界上。红、绿、蓝、白、黑五组颜色,恰好覆盖了数据总线全 0、全 1、单通道满量程这几种极端组合,任何一根数据线虚焊、位序接反、时钟相位错位,都会在彩条上留下肉眼可见的痕迹。所以理解 tft_rgb_colorbar 这类工程,第一步不是改代码,而是把 RGB 接口的时序模型在脑子里立住。
2.1 RGB 并行接口到底在传什么
TFT 屏的 RGB 接口,本质是一组并行数据线加三个同步信号:像素时钟 PCLK、行同步 HSYNC、场同步 VSYNC,有的屏还带数据使能 DE。每个 PCLK 周期,主机把当前像素的 R、G、B 分量同时打到数据总线上,屏端在时钟边沿采样。一行像素传完,HSYNC 拉一个脉冲告诉屏「换行了」;一帧传完,VSYNC 拉脉冲告诉屏「换帧了」。
关键在于,HSYNC 和 VSYNC 并不是紧贴着有效像素的。真实时序里,一行由「行前沿 HFP + 有效像素 HACT + 行后沿 HBP」组成,一帧由「场前沿 VFP + 有效行 VACT + 场后沿 VBP」组成,同步脉冲本身还有宽度 HSW、VSW。这几个参数凑不齐,屏要么不亮,要么图像整体偏移,要么右边出现一条竖黑边。彩条工程的价值就在于:它把 HACT、VACT 固定成屏的分辨率,把其余消隐参数暴露成宏,让你一处一处调。
我一般会先把屏手册里的时序表抄成一张参数表,再对照工程里的宏逐个核对。常见 5 寸 800×480 屏的一组典型值是:PCLK 约 33MHz,HSW 48、HBP 88、HFP 40,VSW 3、VBP 32、VFP 13。不同屏差别很大,别照抄,抄的是方法不是数字。
2.2 彩条图案的生成逻辑与数据位序
彩条本身不需要帧缓存。最省资源的做法是在行扫描过程中用计数器现算颜色:把一行有效像素均分成若干段,每段赋一个固定 RGB 值。这样不占显存,逻辑资源也小,非常适合点屏验证阶段。
真正容易翻车的是数据位序。RGB565 下,一个像素 16 位,R 占高 5 位、G 占中间 6 位、B 占低 5 位;但屏端排线未必按这个顺序接,有的模组是 BGR 排列,有的把高低位对调。彩条里红绿蓝三段如果显示成蓝绿红,基本就是 R/B 通道反了;如果红色显示成青色,那是某几位取反或位序整体错位。下面这段是彩条生成的核心逻辑,用 Python 模拟一遍,方便你在上板前先验证颜色映射对不对:
# 模拟 RGB565 彩条生成,验证位序与分段逻辑 WIDTH = 800 SEGMENTS = 8 # 一行分 8 段彩条 def rgb565(r, g, b): # 标准 RGB565 打包:R 高5位,G 中6位,B 低5位 return ((r & 0x1F) << 11) | ((g & 0x3F) << 5) | (b & 0x1F) # 8 段标准彩条颜色(8位分量) COLORS = [ (255, 255, 255), # 白 (255, 255, 0), # 黄 (0, 255, 255), # 青 (0, 255, 0), # 绿 (255, 0, 255), # 品红 (255, 0, 0), # 红 (0, 0, 255), # 蓝 (0, 0, 0), # 黑 ] def build_line(x): seg = x * SEGMENTS // WIDTH # 当前像素落在第几段 r, g, b = COLORS[seg] # 8位转5/6/5位:右移截断,工程里常用四舍五入,这里用截断便于对照 return rgb565(r >> 3, g >> 2, b >> 3) # 打印前 8 个像素和段边界处的值,检查分段是否均匀 for x in [0, 99, 100, 399, 400, 799]: print(x, hex(build_line(x)))这段代码的作用不是替代硬件,而是在电脑上先把「分段边界对不对、颜色打包对不对」验证掉。参数说明:SEGMENTS决定一行几段,点屏阶段常用 8 段,段数越多越容易看出行方向是否被压缩;rgb565里的移位量 3、2、3 对应 8 位到 5/6/5 位的截断,如果你在硬件里用的是四舍五入,边界像素值会差 1,肉眼一般看不出,但做自动化比对时要注意。跑完这段,把输出和屏上实际颜色逐段对照,能快速定位是软件打包错还是硬件接线错。
2.3 时钟与消隐参数:先让屏「认」到信号
很多新手把彩条代码烧进去,屏一片白或者一片黑,就怀疑代码。实际上八成是 PCLK 频率或消隐参数不对。屏对 PCLK 有范围要求,太低刷新闪,太高直接不锁存;消隐参数不满足最小值,屏内部的行场计数器会错乱。
排查顺序我固定为:先降 PCLK 到手册下限附近,确认屏能出稳定图像;再逐项调 HBP/HFP/VBP/VFP,观察图像是否整体右移或下移;最后才动 HSW/VSW。因为前后沿影响的是图像位置,同步宽度影响的是同步是否被识别,前者现象直观,后者一错就全黑,先易后难。工程里这些参数通常以宏的形式集中在某个头文件,改完重新编译烧录即可,不需要动逻辑。
提示:调消隐参数时一次只改一个,改完记录现象。同时改三个参数,出了问题你根本不知道是谁的锅。
3. 把 tft_rgb_colorbar 跑起来:从解压到彩条上屏的最小路径
拿到压缩包到屏上出彩条,中间隔着工程导入、引脚核对、时钟配置、烧录验证四道关。这一章按实际操作顺序走一遍,每一步都给出可对照的检查点,新手照着做能跑通,熟手可以拿它当核对清单。
3.1 解压后的工程结构与先看什么
解压后先别急着打开 IDE。先看目录里有没有 README 或说明文件,再看有没有引脚定义表、屏型号说明、时钟配置。一个规范的点屏工程,通常包含:启动文件与链接脚本、屏驱初始化代码、彩条图案生成、主循环、以及一个板级配置文件。板级配置里会写清楚 RGB 数据线接哪几个 GPIO、HSYNC/VSYNC/PCLK/DE 各接哪个脚、背光控制脚是哪个。
先核对屏型号和分辨率。工程默认分辨率如果和你的屏不一致,彩条会只占屏幕一部分或者溢出。常见做法是找LCD_WIDTH、LCD_HEIGHT这类宏,改成你屏的实际值,同时把消隐参数按新分辨率重算。重算不是简单按比例缩放,而是查屏手册的时序表,因为消隐最小值往往和分辨率不是线性关系。
再看数据总线宽度。RGB565 是 16 位,RGB888 是 24 位,工程如果按 16 位配的,你接的是 24 位屏,颜色会缺位。这一步看错,后面全白费。
3.2 引脚与数据位序的核对方法
引脚核对不能靠肉眼数排线。我的做法是拿万用表蜂鸣档,从屏排线的 R0 开始,一根一根对到主控 GPIO,边对边在纸上画表。RGB565 下数据线是 R0-R4、G0-G5、B0-B4,共 16 根,加上 PCLK、HSYNC、VSYNC、DE 四根控制线,一共 20 根。对完表,再和工程里的宏逐个比对。
位序问题有个快速验证法:先只点亮纯红、纯绿、纯蓝三屏,每屏单独烧一次。纯红屏如果显示成纯蓝,R/B 反了;纯红显示成暗红或偏色,高位丢了;纯红里混着绿点,相邻数据线短路或位序错位。三屏验完,位序基本就锁死了。这比直接上彩条更容易定位,因为彩条颜色多,出错时你分不清是哪一段的问题。
工程里数据位序通常体现在一个打包函数或宏里,比如把 8 位 R 左移 11 位、G 左移 5 位、B 不移。如果你的屏是 BGR 排列,就要把 R 和 B 的移位对调。改完记得同步改彩条生成里的打包逻辑,否则软件算的和硬件发的对不上。
3.3 时钟树配置与 PCLK 分频计算
PCLK 一般由系统时钟分频得到。假设主频 168MHz,屏要求 PCLK 在 30MHz 左右,那分频系数取 5 到 6 之间。分频不是随便取整就行,要反算实际 PCLK,再对照屏手册的范围。比如 168/5=33.6MHz,168/6=28MHz,如果手册写 30-35MHz,就选 5。
配置时钟树时注意两点:一是 PCLK 不能超过屏和主控双方的上限,取小值;二是 PCLK 和 HSYNC/VSYNC 的极性要匹配屏的要求,有的屏上升沿采样,有的下降沿,极性反了图像会整体错位半行。极性通常在屏驱初始化寄存器里配,或者在主控的 LTDC/显示控制器里配,两处要一致。
下面是一段典型的 PCLK 反算检查脚本,用来在改分频前先算清楚实际频率和刷新率:
# 反算 PCLK 与实际刷新率,改分频前先跑一遍 sys_clk = 168e6 # 主控显示时钟源 div = 5 # 分频系数 pclk = sys_clk / div hsw, hbp, hfp = 48, 88, 40 vsw, vbp, vfp = 3, 32, 13 hact, vact = 800, 480 htotal = hact + hbp + hfp + hsw vtotal = vact + vbp + vfp + vsw refresh = pclk / (htotal * vtotal) print(f"PCLK = {pclk/1e6:.2f} MHz") print(f"HTotal = {htotal}, VTotal = {vtotal}") print(f"刷新率 = {refresh:.2f} Hz") # 判断:PCLK 是否在屏手册范围,刷新率是否落在 55-65Hz参数说明:div是你要试的分频系数,改它看 PCLK 和刷新率怎么变;htotal、vtotal是含消隐的总周期,刷新率低于 50Hz 会肉眼可见闪烁,高于 70Hz 有些屏会丢帧。这段脚本的意义在于,很多工程默认参数是给某块特定屏调的,换屏后刷新率可能掉到 40Hz,你不算就不知道问题出在时钟上。
3.4 烧录后彩条不对的逐级排查顺序
烧录成功但彩条不对,按这个顺序查,别跳步:第一步看背光,屏全黑先确认背光使能和亮度 PWM;第二步看是否有稳定图像,全白或全黑多半是时序没锁存;第三步看彩条分段是否均匀,不均匀是 HACT 或分段逻辑错;第四步看颜色是否正确,颜色错查位序和打包;第五步看边缘是否有黑边或偏移,偏移查 HBP/HFP/VBP/VFP。
每一步都有对应的观察点,不要一上来就改代码。我见过太多人彩条颜色不对就去调时钟,结果越调越乱。颜色和时序是两条独立的链路,先分清现象属于哪条链路,再动手。
4. 点屏现场最容易翻车的五个坑
彩条工程本身不复杂,复杂的是现场。同一份代码,换一块屏、换一块板、换一根排线,现象就完全不同。下面五条是我在点屏阶段反复遇到的,每条都按现象、原因、解决写清楚,照着对照能省不少时间。
4.1 彩条只出一半或右边竖黑边
现象:屏左半部分有彩条,右半部分是黑,或者右侧固定一条竖黑边。原因通常是 HACT 设小了,或者 HBP/HFP 之和超过了屏能接受的范围,导致有效像素被挤到一边。也有一种情况是 PCLK 太快,屏采样跟不上,右侧像素丢失。
解决:先把 HACT 改成屏的实际水平分辨率,再核对 HBP+HFP+HSW 是否和手册一致。如果参数都对仍有黑边,把 PCLK 降一档再看。降频后黑边消失,说明是采样裕量不够,不是参数错。
4.2 颜色整体反相或红蓝互换
现象:红色显示成青色,或者红蓝对调。原因分两种:红蓝互换是 R/B 通道位序接反,属于接线或打包顺序问题;整体反相是数据总线取反,常见于屏端默认极性配置和主控不一致。
解决:红蓝互换先改打包函数里 R 和 B 的移位,不动硬件;整体反相查屏驱初始化里的数据极性寄存器,或者主控输出极性配置。改完用纯红、纯绿、纯蓝三屏单独验证,别直接上彩条。
4.3 图像闪烁或撕裂
现象:彩条稳定但整体闪烁,或者上下半屏错位。原因多半是刷新率和 PCLK 不匹配,或者 VSYNC 极性反了导致帧同步错乱。也有显存带宽不够的情况,但彩条不占显存,基本可以排除。
解决:先用 3.3 的脚本算刷新率,低于 50Hz 就提高 PCLK 或减小消隐;刷新率正常还闪,查 VSYNC 极性,把极性反过来试一次。撕裂一般是双缓冲没配好,彩条工程单缓冲,出现撕裂说明帧同步信号没被正确识别。
4.4 烧录成功但屏完全不亮
现象:烧录器提示成功,屏无任何反应。原因可能是背光没开、屏驱初始化没执行、复位脚没拉高,或者排线接触不良。这类问题最容易被误判成代码错。
解决:先量背光使能脚电压,再量复位脚,最后量 PCLK 是否有波形。有示波器最好,没有就用万用表直流档看 PCLK 平均电压是否在中间值附近。三步都正常还不亮,换一根排线试,排线虚接在点屏阶段非常常见。
4.5 换屏后参数照抄导致花屏
现象:同一份工程换一块同分辨率但不同批次的屏,出现花屏或颜色异常。原因是不同批次屏的时序裕量、数据极性、甚至 RGB 排列可能不同,照抄旧参数就翻车。
解决:每换一块屏,重新查该屏手册的时序表和接口定义,至少核对 PCLK 范围、消隐最小值、数据位序三项。同分辨率不等于同时序,这是血泪经验。工程里最好把屏相关参数集中到一个配置文件,换屏只改这一个文件,别散落在各处。
5. 从彩条到真实画面:把验证工程变成可复用的点屏基线
彩条跑通只是起点,真正有价值的是把这套验证流程固化成基线,后面接真实 UI、接摄像头、接视频流时,能快速判断问题出在屏链路还是上层逻辑。这一章讲三个进阶做法,都是我在多个点屏项目里沉淀下来的习惯。
5.1 用参数表驱动屏配置,而不是散落宏
把分辨率、PCLK、HSW/HBP/HFP、VSW/VBP/VFP、数据位序、极性这些全部收进一张参数表,工程里只留一个结构体或一组宏引用它。换屏时只改表,不改逻辑。下面是一个配置结构体的示例:
// 屏参数集中配置,换屏只改这里 typedef struct { uint16_t width; uint16_t height; uint32_t pclk_hz; uint16_t hsw, hbp, hfp; uint16_t vsw, vbp, vfp; uint8_t rgb_order; // 0=RGB, 1=BGR uint8_t polarity; // bit0: PCLK, bit1: HSYNC, bit2: VSYNC } lcd_timing_t; static const lcd_timing_t g_lcd = { .width = 800, .height = 480, .pclk_hz = 33600000, .hsw = 48, .hbp = 88, .hfp = 40, .vsw = 3, .vbp = 32, .vfp = 13, .rgb_order = 0, .polarity = 0x0, };这样做的直接好处是,出问题时你能一眼看到全部时序参数,而不是在十几个文件里翻宏定义。参数说明:rgb_order控制打包顺序,polarity按位控制三个同步信号的极性,改一个位就能试一种组合,比改寄存器直观。
5.2 彩条加边框和坐标标记,快速定位偏移
纯彩条只能看出颜色和分段,看不出整体偏移量。我的做法是在彩条四周加一圈 1 像素白边框,再在左上角画一个固定大小的方块。边框贴边说明消隐参数刚好,边框被裁说明 HACT/VACT 或前后沿超了;左上角方块位置偏了,直接读出偏移像素数,反推该调 HBP 还是 VBP。这个技巧在调消隐阶段比反复烧录快得多。
5.3 把点屏验证做成上电自检
产品化阶段,我会保留一个上电自检模式:开机先刷 2 秒彩条,再刷纯红绿蓝各 1 秒,最后进正常画面。产线测试时看这几秒就能判断屏链路是否正常,不用拆机接调试器。自检代码和正常显示共用同一套时序配置,避免两套参数不一致。这个习惯帮我拦下过不少排线虚接和批次屏参数漂移的问题。
最后说个我自己的教训:早期点屏我总想一步到位,直接上真实画面调,结果颜色不对、位置不对、闪烁混在一起,查了两天才发现只是 HBP 少了 8 个像素。从那以后我坚持先彩条、再纯色、最后真实画面,每一步都留可对照的现象。点屏这件事,慢就是快。希望帮到你。
本文还有配套的精品资源,点击获取