☰
FPGA点阵屏驱动实战:从扫描时序到灰度调光的完整方案
2026/10/14 16:18:24 网站建设 项目流程

简介:面向FPGA初学者与数字逻辑课程实验者,提供一套基于EP1C3T144C8芯片的点阵显示完整工程资料,适合在课程设计或课后实验中对照练习。整个工程围绕点阵屏驱动控制器展开,包含用Verilog编写的多个核心模块,如行控制、分频模块、扫描控制、八位计数器与四选一多路选择器;同时附带BDF原理图、Quartus工程配置文件、编译报告及时序仿真记录,便于看清从代码到下载到实验板的完整流程。压缩包共收录一百一十三个文件,其中以Verilog源文件、原理图文件、工程设置文件为主,并包含多种备份、日志与报告文件,有助于逐步比较和排查设计问题;整个包大小仅两百零九千字节,下载与解压都很方便。目前已有一千二百余人学习,内容定位清楚,特别适合想通过实际项目理解点阵刷新原理、扫描时序以及模块化设计思想的读者。通过复现此工程,能够真正掌握数据存储、动态扫描、驱动器译码等关键环节,为后续更复杂的数字系统设计打下扎实基础。

1. 点阵显示这口锅,为什么值得用FPGA来背

在嵌入式开发者的日常里,点阵屏大多是单片机驱动的活,一块8x8或16x16的LED点阵,配上两三个移位寄存器,单片机刷一刷就完事了。但换到FPGA上,很多人反而手足无措:明明IO口够多、时钟快到飞起,却连点亮一块16x16屏都要折腾半天,甚至怀疑是不是FPGA压根不适合干这种事。点阵屏的真正核心是刷新时序和扫描节奏,而不是简单的“给电就亮”,FPGA在并行控制和精确时序上天然占优,难点只在于怎么把自己的思维从“串行一条线”切到“并行一片面”。

这个标题里的“点阵显示”不是让你点亮几个灯交差,而是要在FPGA内部搭出一条可持续运行的显示通路:行扫描计数器、列数据缓存、刷新仲裁逻辑,甚至灰度调制。它能解决的问题也很具体:多路点阵屏的同步驱动、高刷新率下的残影抑制、以及把CPU从繁重的逐行刷新中解放出来。适合谁?已经在FPGA上写过流水灯、却又被点阵卡住的新手,还有准备把点阵屏铺到设备面板、想摸清驱动功耗和刷新率边界的工程师。

2. 搭建点阵显示的硬件底子:点阵模块与驱动选型

点阵显示不是光靠逻辑代码就能跑通的,硬件的带载能力、电平匹配、供电方式直接决定你后期要不要返工。这一章把硬件方案定下来,后续的代码才有明确的落点。

2.1 点阵屏的种类与驱动芯片的差异

市面上常见的点阵屏主要有三种:共阳8x8单色模块、共阴8x8单色模块、以及自带驱动芯片(如MAX7219类)的模块。前两种是裸LED矩阵,所有正负极都引到排针上,需要外部不断扫描刷新才能稳定显示,而且亮度与扫描频率强相关。第三种模块内部集成了串行接口和恒流驱动,单片机或FPGA只需要发数据帧就行,省心不少,但代价是刷新率和灰度控制受限于芯片内部的时序,自由度打了折扣。

从FPGA的角度看,我倾向于选裸LED矩阵或仅带移位寄存器的模块,理由很直接:FPGA的优势就是自己控制时序,如果用了MAX7219类芯片,反而把关键节奏交给对方,排错时还得去读芯片手册。裸矩阵的缺点是占用IO多,但入门级FPGA通常有几十个可用IO,驱动一块16x16完全够用。若要做更大规模,比如4块16x16拼在一起,那就要引入74HC595或MBI5024这种串转并芯片,用串行链换IO数量。

驱动芯片选型时主要看三组参数:输出电流能力、通道数量、以及时钟频率上限。74HC595每路只能灌入几十毫安,驱动单个LED有余量,但驱动整行并联的16个LED就得靠三极管或达林顿管扩流。MBI5024这类恒流驱动芯片自带电流设定引脚,用一颗电阻就能限定整片输出电流,更适合长时间点亮或灰度扫描的场景。FPGA连接驱动芯片时,除了数据、时钟、锁存三根线,还要留意芯片的OE(输出使能)引脚是否支持PWM快速开关,这直接关系到后续亮度调节能不能做。

2.2 最小硬件连接方案:IO分配与限流电阻计算

以一块16x16共阳点阵屏为例,常见做法是:16根行线接PNP三极管做行扫描,16根列线接NPN三极管或直接进驱动芯片的恒流输出,行列交叉处的LED通过行线和列线的电平差来点亮。FPGA的IO先接到三极管基极或驱动芯片输入,再由三极管放大电流去驱动LED,FPGA本身不直接承受大电流。这样分配最大的好处是,IO口只负责小电流控制,即便接线出错,烧的也是三极管而不是FPGA。

限流电阻的计算决定了点阵亮度是否均匀。共阳接法下,每一列的16个LED共享一个列限流电阻,但这个电阻是按“单行同时点亮时最坏情况”来选的。假设LED正向压降2V,电源5V,整行16路同时亮,每路设计电流10mA,那列总电流就是160mA,电阻压降3V,计算得R约18.75欧姆,取更小的阻值可以让电流更大,但也要看三极管能否承受。实际操作中常见翻车是把电阻选得过大,电流限制在几毫安,导致整屏昏暗,然后疯狂怀疑代码的扫描频率不对。

推荐先用万用表实测:把某一行的所有列都通过一个可调电阻接到电源,调整电阻让单颗LED电流达到设计值,记下电阻值,再等比例换算到整行匹配的场景。这一步能避开“亮度不够却不知道该调代码还是调硬件”的玄学排查。下面是16x16屏的IO分配参考表,适合入门级FPGA板:

信号方向数量作用
row_scan_sel输出16行选通信号,低电平有效,经三极管驱动行线
col_data输出16列数据信号,高电平点亮该列LED
btn_rst_n输入1异步复位按键,用于初始状态复位
clk_50m输入1系统时钟,作为扫描计数基准

注意col_data和row_scan_sel如果引脚数不够,可以把col_data降为8位并配合74HC595串行扩展,代价是每行扫描时要先花16个时钟周期填充移位寄存器,刷新周期的余量要重新核算。硬件连接完成后,通电前先用万用表测一遍行列之间有无短路,特别是相邻排针距离近的模块,容易因为焊锡桥接造成整行常亮。

3. 核心逻辑实现:扫描驱动与分时复用

硬件连线固定后,代码才是真正考验人的部分。点阵显示的原理并不复杂:每一时刻只有一行被选通,列数据按该行内容输出,然后迅速切到下一行,如此循环,只要循环频率够快,人眼看到的就是一幅完整的静态画面。问题来了:这个“够快”到底是多少?帧率做到60Hz以上才能稳定无闪烁,16行逐行扫描意味着每行只有约1ms的停留时间,扫描频率要达到16乘以60约960Hz以上,脉冲宽度刚好落在LED的亮灭响应范围内。

如果你现在就写一个简单的计数器循环去轮流选通行线,大概率会遇到残影和亮度不均。背后的原因在于“切换行时列数据还没准备好”的瞬间偏差:选通新一行时,上一行的列数据仍然保留在IO输出上,这一帧的起始处就会混入上一行的图案。解决办法是严谨地按“先改列数据,再切换行选通”的顺序操作,甚至主动设计一个极短的消隐窗口。

3.1 行扫描时序:用计数器生成刷新节奏

在FPGA里,推荐用一个分频计数器来产生行扫描时钟。假设系统时钟为50MHz,想要每行保持0.9ms,那么计数器需要计数约45000个周期。每次计数溢出时,行地址加一,同时拉高消隐信号,等到行选通切换稳定后再释放列数据。这比直接对时钟计数、一满就切行要可靠得多,因为行切换瞬间的毛刺都藏在消隐窗口里。

行扫描时钟的频率并不是越高越好。频率太低,16行扫完一帧的时间变长,画面开始闪烁;频率太高,每行的点亮时间过短,平均亮度呈线性下降,同时三极管的开关损耗加大,甚至发热明显。经验值是把单行停留时间控制在0.5ms到1.5ms区间,对应的单帧扫描周期在8ms到24ms之间,刷新率约40到120Hz。若你的屏尺寸更大,行数更多,单行停留时间只能往短了压,但最低不能低于0.2ms,否则LED的亮度会肉眼可见地掉下去。

这里还要注意一个细节:行选通信号的极性要与硬件一致。共阳点阵PNP三极管接法通常是低电平选通行线,代码里行地址输出取反后再送IO;共阴接法反过来。选错极性的表现很典型:屏幕全亮或者全灭,而不是“行显示顺序错误”。先用测试代码让某一行恒常选通,验证硬件极性,再继续写扫描逻辑,这能省下一晚上的排查时间。

3.2 一帧数据的组织方式:行缓存与SRAM读地址生成

要显示的内容不能直接塞进FPGA逻辑里的每一个寄存器,16x16的矩阵还好,如果扩充到64x64,寄存器数量会爆炸。常见做法是在FPGA内部例化一块轻量级的RAM或ROM,把一帧画面按“行号+列数据”的形式存进去。扫描模块在运行时,按当前行号从RAM里取出对应的16位列数据,并行输出到列IO。RAM可以使用FPGA内部的块内存,也可以用分布式RAM,关键是读端口要支持“当前周期给地址,下一周期出数据”,这决定了扫描时钟能跑多快。

行缓存的组织格式有两种流派:一种是“行地址 + 16位列数据”按顺序排列,简单直接;另一种是按像素位平面组织,把灰度数据的每一位分开存,为时间片灰度做准备。我建议先按第一种组织,代码读起来直观,后续扩展再改。数据更新方(比如串口接收的上位机或者状态机)往RAM中写入新画面时,千万不要直接写正在被扫描时钟读取的地址,否则画面会出现撕裂。解决方式是使用双端口RAM,一个端口只读,另一个端口只写,两个端口各自独立,互不干扰。

读地址生成逻辑是另一处容易出错的地方。当行扫描计数器加一后,读地址需要同步更新,但RAM的读延迟会导致当前周期读到的是上一行的数据。处理方法有两种:要么提前一拍把行地址送到RAM,等下一拍数据稳定后再切行选通;要么在行扫描计数器变化之后插入一个等待周期,牺牲一点性能换取确定的数据时序。两种方案在实际中都能用,我更倾向于“提前一拍送地址”,这样行切换时可以做到零等待,扫描有效占空比更高。

3.3 点阵行列驱动的Verilog代码骨架

下面给出一个16x16共阳点阵屏的最简扫描驱动模块,代码里省略了RAM数据初始化,重点展示行扫描节奏和列数据输出的配合:

// 16x16点阵扫描驱动,行选低有效,列数据高有效 module dot_matrix_driver #( parameter ROW_NUM = 16, parameter COL_WIDTH = 16, parameter CLK_HZ = 50_000_000 )( input clk, input rst_n, output reg [COL_WIDTH-1:0] col_data, output reg [ROW_NUM-1:0] row_sel ); // 单行停留时间设定为 0.9ms localparam ROW_TICKS = CLK_HZ / 1000 * 9 / 10; reg [15:0] row_cnt; // 当前行地址 reg [23:0] tick_cnt; // 行停留计数器 reg [COL_WIDTH-1:0] frame_ram [0:ROW_NUM-1]; // 行缓存 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin row_cnt <= 0; tick_cnt <= 0; col_data <= 0; row_sel <= 16'hFFFF; // 初始无行选通 end else begin tick_cnt <= tick_cnt + 1'b1; if (tick_cnt >= ROW_TICKS - 1) begin tick_cnt <= 0; // 切换到下一行 row_cnt <= row_cnt + 1'b1; // 先把列数据更新为下一行内容 col_data <= frame_ram[row_cnt + 1'b1]; // 经过一个时钟周期后再切换行选,避开列数据变化毛刺 row_sel <= ~(16'h0001 << row_cnt); end end end endmodule

这段代码的一个细节是frame_ram的读操作:frame_ram[row_cnt + 1'b1]直接在时序逻辑里使用,综合工具会推断出带读地址寄存器的RAM输出,因此col_data在行选切换前一个周期就已经更新。row_sel计算成独热码再取反,送入PNP三极管基极,低电平对应选通行。ROW_TICKS参数可以按实际点阵尺寸调整,如果换成了8x8屏,行数减半,单行停留时间可以适当加倍,亮度会更好。注意这里没有处理RAM初值,工业化使用时需要在上电后通过一个初始化状态机向frame_ram写入显示内容。

以上逻辑只完成了静态画面显示。如果直接烧录,大概率能看到一个不闪烁的画面,但可能会发现首行或末行有亮斑,这和第3.1节提到的消隐处理相关。代码里用延时一个时钟周期再切换行选,就是为了避免在col_data变化的同时拉低row_sel,导致瞬时出现多余的导通路径。若你的屏对毛刺更敏感,可以在行切换时先把row_sel全部拉高,等一个周期再选通新行,代价是每行损失约0.5%的亮度,肉眼基本察觉不到。

4. 让显示更好看:亮度调节、灰度显示与平滑滚动

静态点亮只是第一步,实际项目里没有谁愿意看一块亮度恒定、内容死板的点阵。调整亮度、显示灰度图像、实现文字滚动,是点阵屏从“能亮”走向“可用”的三道关卡。每个功能都会改变扫描时序的结构,动手前先把原理捋清楚。

4.1 PWM调亮度:复用计数器不做乘法

亮度调节最简单的方案是改变扫描周期的占空比:在一帧时间内,让所有行点亮的时间按同一比例缩短。实现方式是在行扫描计数器中加入一个“亮度阈值”比较,当计数器值小于阈值时输出列数据,否则列数据全部清零。这个阈值就是亮度等级,数值越大亮度越高。

和单片机里用定时器输出PWM不同,FPGA里做PWM应该直接复用现有的tick_cnt计数器。每当tick_cnt从0计数到ROW_TICKS-1时,行扫描已经完成了一个完整周期,如果我们在tick_cnt处于前一半时允许列输出、后一半时强制列清零,那亮度就是50%。亮度等级做成寄存器,上位机随时可以修改,扫描模块不需要额外增加乘法器资源,只多一个比较器,逻辑资源开销几乎为零。

需要注意的是,列数据清零时不能把行选通也一起关掉。一旦行选通跟着PWM一起开关,会引入更低频的闪烁成分。正确的做法是保持行扫描顺序不变,只屏蔽列数据输出,这让LED熄灭时间均匀分散在整个扫描周期中,人眼感知到的亮度变化是连续的。另外,PWM频率必须远高于人眼临界闪烁频率,tick_cnt的计数周期已经由行停留时间决定,不要太天真地把亮度调节做成独立低频方波,否则低亮度时整个屏幕会肉眼可见地闪。

4.2 时间片灰度:给每个bit分配显示时长

如果想显示图像而不是纯文字,常见的方案是时间片灰度,也叫位平面灰度。它的原理是把一个像素的灰度值拆成多个bit,每个bit在整体显示周期中占用不同长度的时间片,比如4bit灰度第0位占1个时间片、第1位占2个、第2位占4个、第3位占8个,一个完整周期总共15个时间片。当这4个时间片循环播放时,人眼通过视觉残留把亮度的不同占空比叠加起来,从而产生16级灰度的感知。

实现这个方案要把帧缓存从“行优先”改成“位平面优先”。比如存储结构从frame_ram[行地址]变为plane_ram[bit序号][行地址],扫描时先在第0个时间片内扫完所有16行,期间每行只输出灰度值的bit0;然后进入第1个时间片,扫完所有行并输出bit1。完整循环一次后,所有bit的时间片都播放过一遍,画面就刷新了一次。位平面扫描把“一帧”这个概念拉长了15倍,所以每个时间片内的行扫描要尽可能快,否则刷新率会跌破安全线。

一个容易被忽略的坑是时间片的长度分配不能靠线性计数,而要按二进制权重扩展。如果把每个bit的时间片都设为相同长度,显示的灰度就不是线性而是错误的。实现时用灰度值各位去控制tick_cnt计数上限:bit0走一轮完整行扫描,bit1走两轮,bit2走四轮,以此类推。这样每个bit的显示时间比天然就是1比2比4比8,不需要复杂的乘法器。如果你的点阵屏对灰度精度要求更高,比如8bit灰度,那时间片总数会膨胀到255个,扫描压力非常大,这时候就得降低扫描行数或者提升系统时钟频率,否则画面闪烁和残影会一起出现。

4.3 文字滚动:移位寄存器与刷新周期的配合

文字滚动比静态显示难在“滚”的动作不能破坏扫描节奏。一种常见做法是维护一个滚动缓冲区,每次帧刷新完成后把整帧数据向左移动一列,然后重新写入RAM。这个动作如果放在扫描过程中间做,会导致正在读取的那些行读到半新半旧的数据,画面出现明显的撕裂带。

合理的方式是把滚动更新和扫描刷新分时复用:扫描模块专门读RAM,滚动模块在扫描任务间隙(比如每一帧的全部行扫完之后)集中更新整块RAM。16x16的屏更新整帧只需要写16个地址,时间极短,哪怕在帧末端预留几个微秒的区间就足够。滚动步长按列进行,每帧移动一列或两列,具体速度取决于帧率,60Hz帧率下移动2列每秒能滚过120列,换算成文字宽度就是每秒约7.5个汉字。

滚动方向的差异也要关注:左滚和右滚在实现上是同一套逻辑,只是更新RAM时列地址的增减方向不同。而上下滚动会涉及行地址的偏移,本质一样,但要注意行扫描计数器的起点必须跟着滚动偏移量改变,否则首行会出现插入内容的下半截。我见过有开发者为了做上下滚动,把行扫描地址和滚动偏移量相加,结果RAM读地址超出边界,显示了别的存储单元里的残余数据,屏幕出现随机噪点。给读地址做mod运算或者状态机限制范围,就能排除这个隐患。

5. 实机点亮避坑指南:5个常见问题的现象、原因与解法

不管代码仿真跑得多漂亮,一上实机问题就像雨后春笋一样冒出来。这里整理了5个我实机调试点阵屏时反复遇到的典型问题,每一条都按“现象 → 原因 → 解决”拆解,希望能帮你少走点弯路。

5.1 显示残影且整屏亮度不均

现象:画面能显示,但边缘有淡淡的拖影,特别是扫描行切换时,上一行图案的亮斑会残留在下一行附近,整屏亮度感觉左边比右边暗。

原因:行切换时列数据没有先归零,导致上一行残留的列驱动电平在新行选通瞬间形成了不该亮的回路。另一个原因是行扫描频率不足,LED的余辉时间约0.1ms,如果每行停留时间超过0.5ms,人眼就足以捕捉到光点的移动轨迹,造成亮度看起来不均匀。

解决:先确认列数据更新和行选通之间存在至少一个时钟周期的间隔,确保列数据稳定后再切行。再把单行停留时间压到0.3ms以下,比如16行屏单帧扫描约4.8ms,刷新率约200Hz,此时余辉效应几乎不可感知。注意别为了追求刷新率把行停留时间压得过短,FPGA的IO翻转速率和RAM读延迟会成为新的瓶颈,物理极限大约在0.1ms。

5.2 首行或末行出现亮斑或白线

现象:整个画面正常,但唯独第一行或最后一行的某个LED常亮,甚至扫描过程中某行有一小段额外发亮,形成一个稳定的亮点。

原因:行扫描计数器计数到最大值后回绕,这个回绕瞬间行选通和列数据同时出现了竞争,导致不是目标组合的某一行被短暂导通。例如行计数从15跳回0时,row_sel译码逻辑可能在同一个时钟周期内出现了两个行同时为低电平的状态,从而点亮了特定LED。

解决:在行计数器回绕周期额外插入一个消隐指令,把所有行选通拉高、列数据清零,再让计数器开始新一轮扫描。这个“空状态”持续一个到两个时钟周期即可,屏幕不会感知到亮度损失,但能彻底消除回绕毛刺。另一个办法是把行地址做成格雷码循环而不是二进制回绕,但逻辑复杂度会增加,不建议新手这么干。

5.3 扫描速度提上去后出现横条纹

现象:把tick_cnt的计数上限调低,画面刷新率确实上去了,但屏幕上开始出现一道一道的横向暗纹,且频率随亮度变化移动。

原因:这与LED的峰值电流和电源纹波直接相关。扫描速度越快,行选通切换时电流冲击越大,电源线上的瞬时压降就越显著。当多行同时切换的瞬间,板上电容来不及补充电流,供给LED的电压被拉低,就会在扫描循环的某些固定相位上产生亮度凹陷,视觉表现为横条纹。

解决:硬件层面在点阵屏电源输入端并联一个大容量电解电容和一个小容量瓷片电容,比如470uF加100nF组合,降低电源阻抗。软件层面检查行选通信号的翻转沿是否同时触发太多次,如果行选通独热码的生成逻辑存在竞争冒险,会产生同一个周期多处翻转的毛刺。可以试着把行选通输出寄存器化,让所有行信号在同一时钟沿更新,减少同时翻转的数量。

5.4 灰度模式下闪烁明显

现象:时间片灰度模式运行,亮度调低或者灰度值较小区域,整体画面出现明显的闪烁感,而静态模式没有这个问题。

原因:灰度模式的时间片总数变多,单位时间内分配给每个bit的扫描次数变少。比如4bit灰度总时间片15个,低灰度值的像素所对应的bit时间短,占空比很小,LED实际点亮时间极短,平均亮度低,余辉无法覆盖整个刷新周期,闪烁自然严重。本质上还是刷新率不足的问题。

解决:优先提高系统时钟频率,或者减少灰度位数。如果系统时钟50MHz受限,可以把点阵的行扫描做成分时双区扫描,把16行分成两组各8行,并行扫描两个区域,等效于把刷新率翻倍。另外一种做法是牺牲一定灰度精度换取刷新率,比如把4bit灰度降到3bit灰度,时间片总数从15降到7,扫描压力减小近一半,人眼对8级灰度的感知差异在多数文字和图案显示中并不明显。

5.5 下载后偶尔正常偶尔花屏

现象:同一份代码,下载到FPGA里有时画面正常,有时完全花屏,需要手动复位一下才能恢复,复位后有时又变花屏。

原因:多半是RAM初值没有可靠初始化。display模块中定义的行缓存frame_ram属于寄存器数组,FPGA上电后寄存器状态不确定,如果初始化状态机没有执行或者被复位信号过早解除,扫描模块就会读到随机数据。花屏的随机性正好对应RAM内容的不确定性。

解决:在代码里给frame_ram加一个显式的复位条件,利用状态机在rst_n释放后先执行一次全RAM清零,再切换到正常扫描模式。清零动作需要花几个时钟周期,但值得为确定性付出这一点延迟。另外检查复位信号的释放边沿是不是干净,如果复位信号存在抖动,扫描计数器在释放瞬间会走到随机值,也会导致花屏。用两个触发器做异步复位同步释放是最好的习惯。

6. 验证显示效果的一个实用技巧:用逻辑分析仪抓取刷新时序

代码仿真只能证明逻辑正确,实机上真正的时序是否如你所愿,最好用逻辑分析仪来验证。点阵屏的扫描信号频率通常在千赫兹到几十千赫兹量级,逻辑分析仪的采样率要求不高,重点在于同时抓取多路信号并观察它们之间的相对关系。我习惯把行选通的低电平有效信号、列数据的最高位、以及内部用于指示扫描周期的标志信号各引一个测试引脚出来,然后同时抓取,看行切换时列数据是否已经稳定。

抓取结果里最需要确认的有三个点:第一,每行的选通时长是否一致,若出现某一行的低电平脉宽明显长于其他行,说明计数器存在溢出边界问题;第二,行选通信号的下降沿和列数据的变化沿是否完全对齐,理想状态应该是列数据变化先完成,行选通下降沿滞后至少一个时钟周期,否则就会出现残影;第三,是否存在两个行选通信号同时为低电平的情况,尤其是行计数回绕瞬间。逻辑分析仪上如果看到两张波形有重叠的凹陷,那就是竞争冒险,返回代码里去检查那个空状态是否真的插入了。

如果你没有逻辑分析仪,退而求其次的办法是利用FPGA内部逻辑观察:把行扫描计数器的值通过片上逻辑分析仪IP核抓出来,再用UART或JTAG回读。这一步能定位计数是否按照预期跳跃,但看不到真实IO上的毛刺,所以只能算半个方案。真正到位的调试习惯是,每次修改扫描参数后,都抓一次波形存档,对比修改前后的差异,而不是凭肉眼盯着屏幕看亮度变化。有人说点阵显示是玄学,是因为他没有把屏幕的表现与时序波形建立对应关系,一旦把两者对应上,所有的“奇怪现象”都能在波形上找到明确的解释。

这套方法占用的资源很少,却能让模糊的“看着还行”变成可量化的“刷新率稳定、残影消失、毛刺可控”。我在做某块16行点阵屏的时候,因为当初图省事省掉了行切换的间隔时钟,屏幕上的竖线残影困扰了一整晚,后来就是靠逻辑分析仪抓波形才发现列数据和行选通下降沿相差仅0.5个时钟周期,而这一丁点时间差刚好超过LED的导通阈值。从那以后,每写完一个显示模块,我都先抓波形再焊屏。验证不是可有可无的收尾,它决定了你后面几天的睡眠质量。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询