简介:这份资源面向数字电子技术课程学习者与FPGA初学者,聚焦按键阵列扫描与发光二极管点阵显示控制电路的设计实现,帮助读者理解从人机交互输入到点阵输出的完整逻辑链路。内容以LP-2900开发装置为硬件平台,讲解3行4列共12个按键的扫描识别、RS触发器消抖、3-8线译码器列线控制,以及8行8列点阵的动态扫描显示原理,并给出状态机、计数器、ROM字符译码等模块的划分与设计思路,涉及Quartus II环境下的实现方法。压缩包内为1个doc文档,约253KB,按设计指标、系统概述、单元电路设计与分析等章节组织,条理清晰,便于按模块查阅。目前已有556人学习,适合需要完成课程设计或实验报告、梳理扫描消抖与动态显示思路的读者参考。
1. 12 个按键只给 4 根列线:一组端口数量倒推出的方案
假设你手上只有一块 FPGA 实验开发装置,面板上摆着 3 行 4 列共 12 个按键,旁边是一块 8 行 8 列的发光二极管点阵。要求是:按下哪个键,点阵上就显示它对应的那个标识符,并且一直保持到下一个键按下;如果几个键同时闭合,只认最先作用的那个。如果按直觉来做,每个按键单独占一根输入线,每个发光管单独占一根驱动线,端口数就是 12 + 64 = 76 根。没有哪块中小规模 FPGA 会这样分配引脚。所以这套数字电子方案的全部张力,都压在“用最少的端口换最多的信息”这一件事上:按键靠行、列扫描,把 12 个键压缩进 4 根列线加 3 根行线;显示靠动态扫描,把 64 个点压缩进 8 根行线加 8 根列线。想清楚这一点,后面的计数器、译码器、数据选择器、锁存器和 ROM 就都有了各自的岗位。
2. 需求拆解与器件选型:把五条指标翻译成可测的电平
先把需求说清楚,再谈选型。很多人一上来就画原理图,画到一半发现“保持显示”这四个字没地方落,回头改架构,前面全白做。我的习惯是把每条文字指标翻译成一句可以被示波器或万用表验证的话,翻译不出来的指标,说明还没想明白。
2.1 从“保持显示”和“只认第一键”反推四类必备部件
“按下显示对应标识符,并保持到新键作用”,这句话里藏着两个动作:捕获和保持。捕获的必须是键码,不是显示码——因为显示码要随行扫描不断变化,存显示码等于把动态扫描钉死。所以第一类部件是锁存器,宽度等于键码位数,四位就够。
“多个按键同时闭合,只响应最先作用的按键”,听起来像要做一个优先级编码器,其实不用。扫描是串行的,计数器一个状态一个状态地走,走到哪个闭合点就停在哪,天然就是“先到先得”。关键在于“停”这个动作要落到计数器的使能端上,而不是落到数据通路上。所以第二类部件是一个能被外部信号封锁的计数器。
第三类部件是字模存储。12 个字符,每个字符 8 行,每行 8 位,共 96 个字节。这个容量决定了地址线的位数:7 位地址刚好 128 个单元,比 96 多一点,多出来的正好用来处理计数器里那几个“空状态”。
第四类容易被忽略:消抖。机械触点在闭合瞬间会产生五到二十毫秒的连续跳变,如果扫描时钟是 1kHz,这一串跳变会被当成几十次按键。所以消抖必须在信号进入扫描逻辑之前完成,用基本 RS 触发器做电平整形,前面配一级 RC 让跳变变缓。
2.2 器件清单:七片 7490、两片 74161 与一块 128×8 ROM 的分工
整个系统按功能切成八块,每块对应一到几个标准器件。这种“标准器件搭积木”的做法在课程设计里比全塞进 FPGA 内部更直观,因为每个信号在板上都能用探头点到,出了问题能一层层往回追。
| 功能块 | 器件 | 用量 | 在系统里的角色 | 关键约束 |
|---|---|---|---|---|
| 分频器 | 7490 二-五-十进制计数器 | 7 片 | 把 10MHz 晶振分成 8 档 | 取 50% 占空比接法 |
| 状态机 A | 74161 四位二进制计数器 | 1 片 | 产生 16 个键扫描状态 | ENP、ENT 同时受封锁 |
| 状态机 B | 74161 四位二进制计数器 | 1 片 | 产生 8 个行扫描状态 | 只取 QCQBQA 三位 |
| 列译码 | 74138 三-八线译码器 | 1 片 | 把 Q3Q2 译成 4 根列线 | 输出低有效 |
| 行选择 | 74153 双四选一选择器 | 1 片(双片封装用一半) | 把 Q1Q0 译成行线选择 | 1C3 必须接高电平 |
| 键码锁存 | 74377 八位锁存器 | 1 片 | 保存命中的键码 | LD 下降沿有效 |
| 字模存储 | 128×8 ROM | 1 块 | 存 12 个字符的点阵 | 7 位地址,8 位数据 |
| 行译码 | 74138 | 1 片 | 把行计数译成 ROW1~ROW8 | 输出低有效,接点阵行 |
| 反相选择 | 组合逻辑门 | 若干 | 前景背景互换 | 与原信号成同或关系 |
| 颜色选择 | 74138 | 8 片 | 每列在红、绿之间二选一 | 使能端接 ROM 数据位 |
这里有个数字值得单独说:为什么 74153 只用了三个输入却要占一个四选一。因为 3 行阵列只用到 X0、X1、X2 三根行线,第四个输入 1C3 不能悬空,也不能接地,必须接高电平。接高的效果是:当计数器走到 Q1Q0 = 11 时,选择器输出恒为高,永远不会被判为“命中”。这四个状态就是整个设计里刻意留出来的空档,后面处理 ROM 地址时要靠它们。
2.3 时钟预算:按键扫描周期、行扫描频率与消抖窗口的三角关系
时钟算错,整个方案在纸面上就站不住。10MHz 晶振进 7 片 7490 级联,每片十分频,总共 10^7 分频,输出端可以取到 10MHz、1MHz、100kHz、10kHz、1kHz、100Hz、10Hz、1Hz 共 8 档。行扫描和键扫描各取一档。
行扫描要满足人眼的视觉暂留。8 行扫一遍是一帧,帧频低于 50Hz 就会看出闪烁。取 1kHz 作为行扫描时钟,单行驻留 1ms,一帧 8ms,帧频 125Hz,余量充足。
键扫描要满足“不漏键”。一轮扫描要走过 16 个计数器状态,如果键扫描时钟取 100Hz,单状态 10ms,一轮就是 160ms。人的按键闭合时间通常在 0.2s 到 1.2s 之间,160ms 勉强能覆盖,但遇到快速点按就可能整个漏掉。我一般会把键扫描时钟提到 1kHz,单状态 1ms,一轮 16ms,比最短的按键动作还短一个数量级,怎么按都不会丢。
代价是消抖压力变大。1ms 的扫描周期根本来不及靠数字计数滤掉 5~20ms 的抖动,所以消抖必须放在模拟侧做完。这也是为什么 RS 触发器整形那一级不能省:它的作用不是“让信号变干净”,而是把一段连续跳变收敛成一次确定的翻转,之后数字电路看到的就只有一个干净的边沿。
3. 总体架构设计:两条扫描链如何共用一块 ROM
两条链,一条管输入,一条管输出,中间靠一块 ROM 缝起来。想清楚它们各自的闭环怎么转、又在哪里交汇,总体图就不用死记了。
3.1 按键扫描链的闭环:计数器、译码器、选择器、锁存器
状态机 A 是一片 74161,工作在自由计数模式,CLRN 和 LDN 都接高电平使其失效,ABCD 四个置数端悬空不用。它的四位输出分成两组:高两位 Q3、Q2 送 74138 的 A1、A0,译出四根低有效的列线 Y0~Y3;低两位 Q1、Q0 送 74153 的 B、A,从 X0、X1、X2 和一根接高的 1C3 中选一个送到输出 Y。
闭环是这样合上的:74153 的输出 Y 同时接两处,一处是 74161 的 ENP 和 ENT,一处是反相后接 74377 的 LD。当扫描到的那个交叉点上的按键闭合,对应行线被拉低,选择器输出 Y 变低,74161 的使能失效,计数器停在当前状态不再前进;同一时刻 74377 的 LD 收到一个下降沿,把当前四位的键码锁进寄存器。整个“捕获 + 保持”在一个时钟周期内完成,不需要额外的握手信号。
这里有个位序细节必须提前定死:Q3Q2 管列、Q1Q0 管行。这跟某些教材上 Q3Q2 管行、Q1Q0 管列的画法正好相反。两种接法都能工作,但键码的排列顺序完全不同,ROM 里的数据必须跟着改。我在第 5 章会把这条列为第一个坑,因为它造成的现象非常像“ROM 数据写错了”,很容易查错方向。
3.2 显示扫描链的闭环:三位行计数与列码同步输出
状态机 B 也是一片 74161,只取 QC、QB、QA 三位组成 8 个状态,送第二片 74138 的 S2、S1、S0,译出 8 根行驱动信号 ROW1~ROW8。这三位同时还接到 ROM 的低三位地址 A2~A0 上,保证“扫到哪一行,就取出哪一行的列码”,两者天然同步。
列码从 ROM 的 D7~D0 出来,经过反相选择逻辑,再送点阵的 C1~C8。开发装置上这八根线后面接了反相器,所以 FPGA 侧看到的是高电平有效:ROWi 和 Cj 同时为 1,第 i 行第 j 列的发光管才亮。这一点直接影响字模数据的极性——字模里写 1 表示这个点亮,写 0 表示灭,跟“低电平有效”的直觉正好相反。换一块不带反相器的板子,整套字模要按位取反。
两条链的交汇点就在 ROM 的地址线上:高四位 A6~A3 来自 74377 锁存的键码,低三位 A2~A0 来自状态机 B 的行计数。地址一旦拼好,读出来的就是“第几个字符的第几行”。这也是为什么锁存器保存的必须是键码而不是别的什么——它直接就是地址的高半段。
3.3 键码到 ROM 地址的位序映射表
按 Q3Q2 选列、Q1Q0 选行的接法,16 个计数器状态对应的物理按键和 ROM 地址块如下。注意最后四行,Q1Q0 = 11 时 74153 选中的是接高的 1C3,输出恒高,永远不会命中,所以这四个状态在物理上没有对应按键,但它们仍然占据 ROM 的地址空间。
| 计数器输出 Q3Q2Q1Q0 | 选中列线 | 选中行线 | 对应按键 | ROM 地址块 |
|---|---|---|---|---|
| 0000 | Y0 低 | X0 | 第 1 列第 1 行 | 0x00~0x07 |
| 0001 | Y0 低 | X1 | 第 1 列第 2 行 | 0x08~0x0F |
| 0010 | Y0 低 | X2 | 第 1 列第 3 行 | 0x10~0x17 |
| 0011 | Y0 低 | 1C3 接高 | 无 | 0x18~0x1F(留空) |
| 0100 | Y1 低 | X0 | 第 2 列第 1 行 | 0x20~0x27 |
| 0101 | Y1 低 | X1 | 第 2 列第 2 行 | 0x28~0x2F |
| 0110 | Y1 低 | X2 | 第 2 列第 3 行 | 0x30~0x37 |
| 0111 | Y1 低 | 1C3 接高 | 无 | 0x38~0x3F(留空) |
| 1000 | Y2 低 | X0 | 第 3 列第 1 行 | 0x40~0x47 |
| 1001 | Y2 低 | X1 | 第 3 列第 2 行 | 0x48~0x4F |
| 1010 | Y2 低 | X2 | 第 3 列第 3 行 | 0x50~0x57 |
| 1011 | Y2 低 | 1C3 接高 | 无 | 0x58~0x5F(留空) |
| 1100 | Y3 低 | X0 | 第 4 列第 1 行 | 0x60~0x67 |
| 1101 | Y3 低 | X1 | 第 4 列第 2 行 | 0x68~0x6F |
| 1110 | Y3 低 | X2 | 第 4 列第 3 行 | 0x70~0x77 |
| 1111 | Y3 低 | 1C3 接高 | 无 | 0x78~0x7F(留空) |
12 个有效块正好 96 个单元,加上 4 个留空块共 128 个单元,一块 128×8 的 ROM 刚好装满,一个地址都不浪费。这张表建议在画原理图之前就画出来贴在旁边,后面写 ROM 数据、查错、答辩,全靠它。
4. 单元电路落地:分频、消抖、字模与颜色控制的具体实现
架构定了,剩下的就是把每个盒子填满。这一章挑四个最容易出偏差的单元展开,每个都给出可复现的参数或代码。
4.1 分频器:七片 7490 级联与 50% 占空比的接法选择
7490 内部是“二进制 + 五进制”两段结构,CLKA 进、QA 出是二分频;CLKB 进、QCQBQA 出是五分频。要凑成十分频,两种接法:
| 接法 | 输入输出走法 | 取哪个脚做输出 | 输出占空比 |
|---|---|---|---|
| 接法一 | 时钟进 CLKA,QA 接 CLKB | QD | 20% |
| 接法二 | 时钟进 CLKB,QD 接 CLKA | QA | 50% |
两种都能十分频,差别在输出波形。接法一输出的是窄脉冲,高电平只占五分之一周期;把它拿去驱动行扫描,行导通时间被压缩到 20%,点阵亮度明显偏暗,而且级联到下一级时对时钟脉宽的要求更苛刻。接法二输出方波,占空比 50%,行导通时间翻倍有余,亮度均匀,级联也更省心。我选接法二,七片全部按这个方式串起来,每片的 CLRA、CLRB、SET9A、SET9B 四个异步端统一接地,防止上电时被误置位。
七片级联后输出 8 档频率,用排针或跳线选一档送给状态机 A,另一档送给状态机 B。选频这一步不要用拨码开关直接切时钟线,开关抖动会在切换瞬间产生毛刺,把计数器打到一个随机状态。通常的做法是加一级与门做门控,切换时先把时钟关掉。
4.2 消抖与键保持:RS 触发器整形加计数器使能封锁
消抖这一级,硬件上是这样的:按键一端接地,另一端通过 100kΩ 电阻上拉到 +5V,同时对地并一只 0.1μF 电容,时间常数 τ = RC = 10ms,正好覆盖机械触点 5~20ms 的抖动区间。电容上的电压再送进两个交叉耦合的与非门构成的 RS 触发器,把缓变的模拟边沿整形成陡峭的数字边沿。
为什么不靠数字计数消抖?因为键扫描时钟是 1kHz,一个状态只有 1ms,要滤掉 20ms 的抖动得连续采样 20 次,而扫描根本不会在同一个状态上停留那么久。模拟侧先解决,数字侧才干净。
键保持的实现落在计数器使能上。下面是这一段的等价描述,实际电路里由 74161 的 ENP、ENT 和 74377 的 LD 完成:
// 键扫描核心:命中即停,同时锁存键码 module key_scan( input wire clk, // 键扫描时钟,取 1 kHz input wire rst_n, // 低有效复位,清计数器与锁存器 input wire [2:0] row_x, // RK1~RK3,未按键时为高电平 output reg [3:0] key_code, // 锁存的键码 Q3..Q0 output wire [3:0] col_y // 送 74138 的列译码输出,低有效 ); reg [3:0] cnt; wire row_sel, hit; assign col_y = ~(4'b0001 << cnt[3:2]); // Q3Q2 译码成四根列线 assign row_sel = (cnt[1:0] == 2'd0) ? row_x[0] : (cnt[1:0] == 2'd1) ? row_x[1] : (cnt[1:0] == 2'd2) ? row_x[2] : 1'b1; // 1C3 接高,永不命中 assign hit = ~row_sel; // 行线被拉低即命中 always @(posedge clk or negedge rst_n) begin if (!rst_n) cnt <= 4'd0; else if (hit) cnt <= cnt + 4'd1; // 未命中才继续扫描 else cnt <= cnt; // ENP/ENT 失效,保持当前状态 end always @(posedge clk or negedge rst_n) begin if (!rst_n) key_code <= 4'd0; else if (!hit) key_code <= cnt; // 对应 74377 的 LD 下降沿锁存 end endmodulecnt就是状态机 A 的本体,row_sel模拟 74153 的四选一行为,hit对应选择器输出取反。命中时计数停止,键码写入key_code。这里锁存比命中晚一拍,对应实际电路中 74377 的 LD 要经过一级反相器这个延迟,仿真和实物都要按这个时序对。
4.3 字模组织与 ROM 数据文件生成
一个字符占 8 个字节,字节内的 D7~D0 从高到低对应点阵从左到右八列,8 个字节从低地址到高地址对应从上到下八行。写数据文件时这两个方向都不能搞反,否则字符会变成镜像或者上下颠倒。
以字符“1”为例,八行的二进制是:
00011000 00111000 00011000 00011000 00011000 00011000 01111110 00000000对应的十六进制就是 18、38、18、18、18、18、7E、00。字符“*”的八行是 00、24、18、7E、18、24、00、00。其余十个字符照这个格式补齐,注意留出四个无效块整块填 0,避免扫描到无效键码时屏幕出现残留亮点。
手写 128 个单元容易出错,用脚本生成更可靠:
# 把 8x8 字模按 [键码 x 8 + 行号] 的地址写成 Quartus 的 .mif FONT = { 0x0: [0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00], # 键码 0000 的字符 0x4: [0x00, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x00, 0x00], # 键码 0100 的字符 # 其余 10 个键码按同样格式补齐 } with open("keyfont.mif", "w", encoding="utf-8") as f: f.write("DEPTH = 128;\nWIDTH = 8;\nADDRESS_RADIX = HEX;\n" "DATA_RADIX = HEX;\nCONTENT BEGIN\n") for addr in range(128): code, line = addr >> 3, addr & 0x07 # 高四位键码,低三位行号 data = FONT.get(code, [0] * 8)[line] # 无效键码块整块写 0 f.write(f" {addr:02X} : {data:02X};\n") f.write("END;\n")addr >> 3取出高四位当键码,addr & 0x07取出低三位当行号,正好和地址线的拼接方式一一对应。FONT.get(code, [0]*8)这一句是关键:查不到对应字符时返回一整行的 0,把四个无效块自动留空,不用手动去数地址。
4.4 反相选择器与颜色选择器:同或门和八片 74138 的用法
反相选择就是一个二选一的极性翻转。列出真值表:原信号 0、控制 0,输出 1;原信号 1、控制 0,输出 0;原信号 0、控制 1,输出 0;原信号 1、控制 1,输出 1。四行看下来,输出和原信号是反相还是同相,完全由控制位决定,逻辑关系就是同或。
// inv_sw = 0 时输出取反(前景背景互换),inv_sw = 1 时同相 assign dot_col = ~(font ^ inv_sw); // 同或:两位相同出 1,不同出 0font是 ROM 读出的 8 位字模,inv_sw是面板上的电平开关。同或的结果直接送点阵列线,按下开关的瞬间整屏黑白互换,这个功能在验收时很直观,一眼就能看出有没有生效。
颜色选择用八片 74138,一片负责一列。每片的 A 引脚接同一个电平开关,G1 使能接 ROM 输出里的对应数据位,输出端 Y0、Y1 分别驱动这一列的红灯和绿灯。逻辑上是这样:某一列在字模里是 1,说明这一列在当前行要点亮,这一位的 1 送到 G1 使能端,74138 被激活,此时 A 的电平决定点亮红灯还是绿灯;这一位是 0,74138 整体不使能,两路输出都不动作,这一列保持熄灭。八片并联,就实现了“只让该亮的点换颜色,不该亮的点不受影响”。
5. 联调避坑:四类最容易翻车的现象与排查路径
原理图能跑通不代表实物能跑通。下面四条是这类设计里出现频率最高的,每条都按“看到什么、为什么、怎么改”写。
5.1 现象:字符整体错位,或者显示成另一个键的图案
按下第一个键,点阵上出来的是第五个字符;按下第五个键,出来的又是别的。字模数据逐行核对过,没有问题。
原因基本只有一个:键码的位序和 ROM 的地址映射对不上。Q3Q2 管列还是管行,只要和教材上的画法反了,16 个状态到 12 个按键的对应关系就整个重排一次,ROM 里的数据块必须跟着重排。更隐蔽的一种情况是,只把 Q3Q2 和 Q1Q0 对调了,却没有相应地把四个无效状态重新定位,导致 0x18、0x38、0x58、0x78 这几个块本该留空的地方填了字符,扫描到无效键码时反而亮出东西来。
解决的办法是回到第 3.3 节那张表,先确认 Q3Q2 接的是列译码还是行选择,再按新映射重排整个数据文件。我的习惯是在原理图旁边打印一张地址映射表,每填完一个字符块就在表上打勾,填完十二个再回头抽查三块,比对二进制。
5.2 现象:多个键同时按下时,响应的是后按的那个
设计要求是只认最先作用的按键,实测却是最后松手的那个胜出,或者干脆乱跳。
原因在封锁的时机上。74161 有两个使能端 ENP 和 ENT,一个管计数一个管进位,只接一个的时候,另一个悬空或者接高,计数器在某些状态下仍会前进一拍。还有一种情况是封锁信号取自选择器输出但没有做同步,命中瞬间计数器已经多走了一个状态,锁存进去的就是下一个键码。
解决方法是 ENP 和 ENT 同时接选择器输出,并且让 74377 的锁存沿严格落后封锁沿半拍——实际电路里就是让 LD 走一级反相器,仿真里体现为锁存条件比停计条件晚一个时钟。改完之后同时按住两个键,显示的应该始终是扫描序列里靠前的那个。
5.3 现象:点阵亮度不均,边缘发灰,或者整屏轻微闪烁
字符能显示,但看着不舒服。有的行亮有的行暗,快速扫一眼隐约看到拖影。
先查行扫描频率。如果状态机 B 的时钟取自 100Hz 档,一帧就是 80ms,帧频 12.5Hz,肉眼一定能看出闪。把时钟换到 1kHz 档,一帧 8ms,问题一般就消失了。
如果换了时钟还闪,那就是列码和行码不同步。ROM 的低三位地址和行译码器的输入必须来自同一组信号,中间不能插缓冲器或者反相器,否则地址建立时间不同,某一行会读到上一行的数据,表现就是上下错半行。我遇到过的一次是行译码器前面串了一级非门做驱动增强,结果那一级的延迟让地址比数据晚到,屏幕上每一行都往上串了一行,看起来像整个字符被压扁了。去掉那级门就好了。
5.4 现象:按住键不放,再按其他键全部无响应
单键功能都对,但一旦按住某个键,系统就卡在那里,必须断电重启才恢复。
这是设计上没考虑“释放”这个动作。计数器被封锁之后就一直停着,锁存器也一直保持着那个键码,没有任何机制让它重新开始扫描。教材上的原理图常常省略这一块,因为重点在扫描逻辑本身,但做成实物就必须面对。
最简单的补救是保留一个手动复位按钮,接到 74161 的 CLRN 和 74377 的清零端,按住键看完显示后按一下复位,系统重新开始扫描。更完善的做法是加一路释放检测:把选择器输出经过一个单稳态,按键松开时产生一个窄脉冲去清封锁标志,计数器自动恢复。课程设计里用第一种就够,答辩时能说清楚第二种思路是加分项。
6. 验收与答辩:用一份测试记录把方案讲圆
方案做完只是及格线,能不能验收通过、答辩讲清楚,取决于你有没有一份像样的测试记录。我一般会先列测试用例,再逐条跑,跑完把实测现象写进去,最后拿这张表当答辩提纲。
测试用例至少覆盖七类:12 个单键逐个按下、连续快速按两个不同键、两个键同时按住、按住一个键超过五秒、快速点按(小于 0.1 秒)、切换反相开关、切换颜色开关。每类记三列:操作、预期现象、实测现象。
| 用例 | 操作 | 预期现象 | 判定依据 |
|---|---|---|---|
| T01 | 依次按下 12 个键 | 每次显示对应标识符并保持 | 12 个字符与键位一一对应,无错位 |
| T02 | 先按 A 再按 B | 显示 A 的字符,松手后仍保持 | 后按键不覆盖已有显示 |
| T03 | A、B 同时按住 | 显示扫描序列靠前的那个 | 与键码大小顺序一致 |
| T04 | 按住某键 5 秒 | 显示保持不变,不闪烁不跳变 | 计数器停在原状态 |
| T05 | 快速点按某键 | 能捕获到并显示 | 无漏键 |
| T06 | 拨动反相开关 | 整屏黑白互换 | 前景背景同时翻转 |
| T07 | 拨动颜色开关 | 亮点由绿变红,松开恢复 | 只有亮点换色,暗点不受影响 |
答辩的问题基本围绕“为什么这么选”。下面几个是高频的,提前准备答案能省很多临场组织语言的时间。
| 可能的提问 | 回答要点 |
|---|---|
| ROM 为什么是 128 个单元而不是 96 个 | 4 位计数器有 16 个状态,其中 Q1Q0 = 11 的四个状态被 1C3 接高屏蔽,物理上不对应按键,但地址空间照样占 32 个单元,必须留空填 0 |
| 键扫描周期怎么算的 | 单状态驻留时间乘以状态数,1kHz 下是 1ms × 16 = 16ms,远小于人最短的按键时间 |
| 多键同时按下为什么只认第一个 | 命中即通过 ENP、ENT 封锁计数器,后面的扫描点根本不会被访问,先到先得是扫描顺序的自然结果 |
| 消抖做在哪一级 | 模拟侧 RC 加 RS 触发器整形,数字侧不再做计数消抖,因为 1ms 的扫描周期滤不掉 20ms 的抖动 |
| 换成 4×4 阵列要改哪里 | 行选择改用 74153 的四个输入,键码扩 |
本文还有配套的精品资源,点击获取