☰
用Excel与Logisim设计运动码表:状态转换表与输出函数表驱动数字电路
2026/10/5 1:11:02 网站建设 项目流程

前两天带一个做数字逻辑课设的学弟调运动码表,他一开始就扑进 Logisim 里拖门电路,拖到第二次数码管不亮,整张电路图已经成了一张蜘蛛网。我把他的设计文件关掉,先让他打开 Excel:把状态转换表和输出函数表填清楚,再回去改电路,十分钟就定位到问题。运动码表这个题目看着是“数数”,本质是一个有限状态机加一整套组合逻辑输出,你在 Logisim 里看到的每一个门,都应该能从一张真值表里找到出处。这篇文章就讲我怎么用 Excel 把运动码表的“状态转换”和“输出函数”这两张表做扎实,再反哺到 Logisim 电路里。正在做课设、或者想把组合逻辑设计流程真正走一遍的人,可以直接照着做。

1. 运动码表不是简单的计数器:状态机先于电路

很多同学拿到“运动码表”这个题目,第一反应是找计数器芯片、接数码管、拼时钟,先把显示跑起来。这个思路在只做“从 0 数到 59.99 秒”的时候勉强能用,一旦要求加入启动、暂停、继续、清零这些交互,电路立刻失控。原因很简单:运动码表是有记忆的数字系统,它的行为不只看当前输入,还取决于之前处于什么工作状态,这种系统不能靠纯组合逻辑堆出来,必须用状态机来设计。

1.1 为什么直接拖门电路总会翻车

组合逻辑的特点是“输入一变,输出立刻跟着变”,没有记忆能力。运动码表则需要记住“我现在在计时、在暂停、还是已经清零待机”,否则同一个按键按下时,电路不知道该做什么。

举个例子:启动/暂停共用一个按键,在停止状态按下是“开始计时”,在运行状态按下是“暂停”,在暂停状态按下又是“继续”。同一个输入信号,三个完全不同行为,区别就来自当前状态。这种“当前状态 + 输入 -> 次态”的映射关系,就是有限状态机的核心。

用 Logisim 直接拖门电路做状态机不是不行,而是顺序逻辑天然需要反馈:状态寄存器的输出要接回组合逻辑的输入,组合逻辑的次态输出又要接到寄存器的输入。没有一张表先定清楚每个状态在每个输入下的走向,连线的时候纯靠脑子去记,十几条线一交叉必然出错。更麻烦的是,仿真报错时你根本分不清是状态转移错了、输出译码错了,还是线接错了。

正确顺序是:先在 Excel 里把状态转换表和输出函数表变成一张张完整的真值表,然后用 Logisim 的组合分析工具去生成门电路。真值表错了,电路一定错;真值表对了,电路基本不会跑偏。

1.2 运动码表最小状态集:三个状态、两个按键

课程设计里的运动码表,功能上通常可以收敛为三个状态:

  • STOP(停止待机):计时值清零,等待启动。
  • RUN(运行):计时值持续累加,数码管实时显示。
  • PAUSE(暂停):停在当前计时值,等待继续或清零。

操作键可以合并成两个:

  • START_PAUSE 键:启动/暂停/继续,一个键循环切换。
  • RESET 键:清零,无论当前在哪个状态,按下都回到 STOP。

状态跳转关系是:STOP 下按 START_PAUSE 进入 RUN;RUN 下按 START_PAUSE 进入 PAUSE;PAUSE 下按 START_PAUSE 回到 RUN;任意状态按 RESET 都回到 STOP。用状态机的语言说,这是三个状态、两个输入、若干个输出信号的设计。为什么不再加一个 STOP 专用键?因为课设题目往往限定按键数量,而且“同一个键在不同状态做不同事”恰好能考察状态机设计能力,所以两个键是更典型的题目设定。

1.3 Excel 到底在帮我们做什么

状态转换表和输出函数表,本质都是真值表。Excel 的天然优势是:横向列好输入输出,纵向一行一行列出所有组合,中间可以用公式自动计算次态,还能用条件格式把特殊行标红。无论是 4 个输入的 16 行状态转换表,还是 4 个 BCD 输入到 7 段输出的 10 行译码真值表,用 Excel 都比纸上手写更清晰,也比 Logisim 里直接改真值表更容易批量处理。

后面几步我会把这三张表全部建出来:第一张是状态转换表,第二张是 BCD 计数器的进位输出真值表,第三张是七段数码管的译码真值表。三张表齐了,运动码表的逻辑就等于完成了一大半。

2. 状态转换表:两位触发器、三个有效状态、16 行真值表

状态转换表要回答的是:给定当前状态和输入,次态是什么,输出是什么。在设计运动码表时,我习惯用两位 D 触发器来存放状态,因为三个状态需要两位二进制编码,多出来的一个编码可以拿来兜底。

2.1 状态编码:保留 11 这个陷阱状态

状态编码方案如下:

状态编码 Q1Q0含义
STOP00停止待机,计数清零
RUN01运行计时
PAUSE10暂停保持
未定义11强制回到 STOP

很多初学者只看到三个状态,就自然以为两位编码里 11 用不上,直接在真值表里留空。这是一个隐患。Logisim 仿真时 D 触发器上电的初始值并不总能保证是 00,一旦落到 11,而组合逻辑里 11 对应的次态又是空,电路就可能停在 11 状态“假死”,数码管不跳,怎么按都没反应。把 11 显式地映射回 00,是设计状态机时最省事的兜底策略。

输入我定义为:

  • A = START_PAUSE,1 表示按下。
  • B = RESET,1 表示按下。

由于 RESET 的优先级最高,只要 B=1,无论当前什么状态,次态都回到 STOP。

2.2 在 Excel 里把次态写成布尔公式

打开一个空工作表,列头按这样排:Q1、Q0、A、B、D1、D0、EN、CLR。其中 Q1Q0 是现态,AB 是输入,D1D0 是次态,EN 是计数使能,CLR 是计数器清零。

在 Excel 里我通常会先写公式,让电脑把次态算出来,而不是手填。以第二行数据为例,假设 A2 是 Q1,B2 是 Q0,C2 是 A,D2 是 B,那么:

D1(次态高位)可以这样写:

=IF(D2=1, 0, IF(AND(A2=0, B2=1, C2=1), 1, 0))

含义是:RESET 按下,次态高位是 0;否则只有当现态是 RUN(01)且按下启动/暂停键时,次态才变成 PAUSE(10),高位为 1。

D0(次态低位)的公式稍长一点:

=IF(D2=1, 0, IF(C2=1, IF(OR(AND(A2=0, B2=0), AND(A2=1, B2=0)), 1, 0), IF(AND(A2=0, B2=1), 1, 0)))

这个公式做的事情是:RESET 优先回 00;若没有 RESET,按下启动/暂停键时,STOP 或 PAUSE 都变成 RUN(低位 1),而 RUN 变成 PAUSE(低位 0);若没有按键,则只有 RUN 保持 RUN,低位为 1。

用 Excel 公式算次态,不只是省事,它还能和你之后用 Logisim 组合分析自动生成的表达式交叉验证。两边结果一致,说明状态转换表没抄错。

2.3 完整状态转换表:16 行一次看明白

四位输入(Q1Q0AB)一共 16 种组合,最终表如下:

Q1Q0ABD1D0ENCLR行为说明
00000001STOP 保持
00100110STOP 启动
00010001STOP 清零
00110001RESET 优先
01000110RUN 继续计时
01101000RUN 暂停
01010001RUN 清零
01110001RESET 优先
10001000PAUSE 保持
10100110PAUSE 继续
10010001PAUSE 清零
10110001RESET 优先
11000001未定义回 STOP
11100001未定义回 STOP
11010001未定义回 STOP
11110001未定义回 STOP

看着这张表,输出函数其实已经浮出水面了。EN 只在现态为 RUN 时为 1,写成布尔式就是:

EN = Q1' · Q0

CLR 在现态为 STOP 或未定义状态时为 1,即 Q1 和 Q0 相等的时候为 1:

CLR = Q1 · Q0 + Q1' · Q0' = NOT(Q1 XOR Q0)

这两个输出只跟现态有关,不跟输入直接挂钩,属于 Moore 型输出,好处是稳定,不会因为按键瞬时变化产生毛刺。

2.4 用 Excel 快速生成全部行的技巧

16 行如果手填,容易漏。我的做法是先用 Excel 的自动填充生成 0 到 15 的十进制数,再用 BITAND、BITRSHIFT 之类函数拆出二进制位,或者直接手动拉四个输入列的组合。更土但更稳的办法是:输入列 A、B 两列设数据验证下拉,只有 0 和 1,然后一行行按表填。填完后用条件格式把 B=1 的行标红,一眼就能看出 RESET 优先逻辑是否覆盖完整。

这样一张表,既是设计文档,也是后面 Logisim 组合分析的输入依据,千万别关掉。

3. 输出函数表:从显示需求倒推到每一段点亮条件

状态转换表解决的是“下一步去哪”,输出函数表解决的是“当前这个状态应该把哪些信号拉高”。运动码表的输出分成两层:一层是控制计数器工作的信号,另一层是把计数值变成数码管上可见笔画的译码输出。

3.1 运动码表要显示什么信号

典型的课设运动码表显示四位数字,我按“秒十位、秒个位、百分秒十位、百分秒个位”来排,也就是显示 00.00 到 99.99 秒,或者按 00.00 到 59.99 秒循环。每一位都是 BCD 码的 0-9 计数器,级联成十进制计数器链。计时时钟进百分秒个位,百分秒个位每数满 9 次产生一个进位给百分秒十位,百分秒十位每数满 9 次产生进位给秒个位,秒个位每数满 9 次产生进位给秒十位。

这里的“进位信号”就是一种输出函数,它由当前计数器的 BCD 值和使能信号共同决定。以一位 BCD 计数器为例:输入是 EN(计数使能)和当前计数,输出是次态和进位 C。当 EN=1 且当前值是 9 时,下一拍回到 0,同时 C=1;其他情况 C=0。

3.2 用 Excel 做单个 BCD 计数器的状态表

一位 0-9 计数器在 Excel 里可以这样建:一列写当前值(十进制),一列写 EN,一列写次态十进制,一列写进位 C,再把十进制转成四位二进制位。

次态逻辑用公式表示:

=IF(EN=0, 当前值, IF(当前值=9, 0, 当前值+1))

进位逻辑:

=IF(AND(EN=1, 当前值=9), 1, 0)

十进制转二进制可以用DEC2BIN(当前值, 4),再用MID函数把四位拆到单独的 W、X、Y、Z 列里,作为后面译码表的输入。如果你用的 Excel 没有 DEC2BIN 函数,手动列出 0 到 9 的二进制码也不费事,毕竟只有 10 行。

如果一个设计需要 60 秒上限,只要把秒十位独立做成 0-5 循环的计数器即可,0-5 计数器在 Excel 里不过是把“等于 9 回 0”改成“等于 5 回 0”,其他逻辑完全一样。这就是建表的好处:需求一变,改一个条件,整张表重算,电路再跟着改。

3.3 七段数码管译码表:BCD 输入到段码输出

这是整张 Excel 表里最像“输出函数”的部分。共阴极七段数码管,高电平点亮,输入是四位 BCD 码 WXYZ,输出是 a、b、c、d、e、f、g 七段。

标准 0-9 的段码表如下:

数字WXYZabcdefg
000001111110
100010110000
200101101101
300111111001
401000110011
501011011011
601101011111
701111110000
810001111111
910011111011

输入组合 1010 到 1111 在运动码表里永远不会出现,这些就是无关项。在卡诺图里可以把它们当作 1 或 0 来合并,从而得到更简单的门电路。以 g 段为例,它在 2、3、4、5、6、8、9 时点亮,如果在卡诺图里把无关项合理并入,表达式会比直接列七项短不少。

四个数码管可以共用同一套译码函数,因为在同一时刻每位数码管显示的数字不同,但译码逻辑本身是同一个“0-9 到七段”的映射。课设里最简单的接法是四位各接一片译码电路,不做什么扫描显示,Excel 表也只需要一份七段译码真值表,复制四份电路实例即可。

3.4 从真值表到最简布尔式的判断

拿到真值表之后,手动画卡诺图是一种能力,但真值表行数一多,人工化简容易漏项。Logisim 自带的组合分析工具可以直接从真值表生成化简后的门电路,这一步我在第 4 节详细说。

这里想提醒的是:在 Excel 表格里千万不要只记录“最终化简结果”,原始真值表的每一行都要留着。因为 Logisim 自动生成的电路不一定是最优解,你后期如果想手动优化某一盏数码管段的逻辑,回头对照原始 10 行数据比对照化简式更可靠。

4. 从 Excel 到 Logisim:把真值表变成能跑的电路

Excel 表做得再漂亮,最终还是要落回电路。Logisim 的 Combinational Analysis(组合分析)工具,恰好是连接真值表和门电路之间的桥梁。运动码表的总体思路是:状态机组合逻辑用组合分析生成,状态寄存器和计数器用手工接线,译码部分再次用组合分析生成。

4.1 把状态转换表喂给组合分析

打开 Logisim,新建一个电路,操作路径是 Project -> Analyze Circuit,或者直接按 Ctrl+B 打开组合分析窗口。

在 Inputs 标签页里添加四个输入:Q1、Q0、A、B。在 Outputs 标签页里添加四个输出:D1、D0、EN、CLR。然后切到 Table 标签页,把 Excel 状态转换表里 16 行的内容逐行抄进去。

需要注意,Logisim 的组合分析表格默认要求每个输出格填 0 或 1。如果你用的版本支持把输出格设为 x(无关项),你可以把无法输出的组合标成 x;如果不支持,就暂时填 0,先让电路跑起来,后面再手动优化。对于运动码表来说,状态转换表的 16 行全部是确定值,不会有 x;七段译码表才会有无关项,但也只有 6 行。

填完后点击 Build Circuit,Logisim 会自动把最简门电路放到新电路里。这一步生成的就是状态机的次态组合逻辑和输出逻辑,不需要你手动从布尔代数开始推。

4.2 状态寄存器与计数器接线:时钟必须统一

组合分析生成的电路只有组合逻辑,没有记忆功能。要让状态机“记住”当前状态,需要把 D1D0 接到两位 D 触发器的 D 输入端,D 触发器的 Q 输出再反馈回组合逻辑的 Q1Q0 输入端。切换状态依赖时钟边沿,所以两个 D 触发器要接同一个时钟源。

计数器部分的接线最容易出现误区:有人会把 EN 信号直接接到计数器的 Clock 端,用“有没有脉冲”来控制计不计时。这个方案在 Logisim 仿真可能看起来正常,实际是错误设计。因为 EN 是电平信号,和时钟信号做与门会产生窄脉冲、毛刺,后续转到真实芯片或更高要求的仿真时会被打得很惨。

正确做法是:计数器内部每一位触发器都接统一系统时钟,EN 作为“下一拍是否改变计数值”的控制端。如果是 D 触发器搭计数器,就在 D 输入端用选择逻辑:EN=1 时 D 取“加一后的值”,EN=0 时 D 取当前值,相当于保持。

运动码表的四位计数器可以用同一个系统时钟驱动,状态寄存器的时钟也接这里。这样做可以保证状态切换、计数累加、清零发生在同一时钟边沿,行为完全同步。

4.3 按键边沿检测:不能按一下跳两个状态

状态转换表里输入 A=1 代表“启动/暂停键按下”,但物理按钮按下去之后,电平会保持一段时间,几十毫秒甚至更久,而系统时钟可能在几百 kHz 甚至更高,结果就是一个高电平期间,状态机会被触发很多次:RUN 会跳到 PAUSE,又立刻跳回 RUN,再跳到 PAUSE,数码管表现就是乱闪。

标准的处理是加边沿检测电路,把“按钮按下”这个持续电平转换成“一个时钟周期宽的脉冲”。做法是用两个 D 触发器对按钮信号打两拍,取第二拍和第一拍的逻辑关系:上升沿时,当前值为 1 且上一拍为 0,用一个 AND 门检测,输出一个脉冲。这个脉冲再接状态机的输入 A。

用一句话概括:按键信号不是直接用,而是先同步、再检边、最后才交给状态机。这一点在做课设时非常关键,少了它,状态表再对也没有用。

4.4 整体接线检查单

电路接完后,按这个清单过一遍:

  • 状态寄存器:两位 D 触发器,D 接 D1D0,Q 反馈回组合输入,Clock 接系统时钟。
  • 组合逻辑:输入 Q1Q0AB,输出 D1D0、EN、CLR,由组合分析生成。
  • 计数器链:四位 BCD 计数器级联,百分秒个位 -> 百分秒十位 -> 秒个位 -> 秒十位。
  • 计数器控制:EN 控制加一/保持,CLR 控制清零,全部接状态机输出。
  • 按键:START_PAUSE 和 RESET 都经过边沿检测得到单脉冲信号。
  • 显示:每位 BCD 输出接七段译码器输入,译码器输出接七段数码管对应段。

接线顺序建议从状态机开始,先保证状态能在 STOP、RUN、PAUSE 之间正确切换,再接计数器和显示。一层一层来,不要一步到位把所有线都拉完,否则出错时根本无从下手。

5. 实测最容易翻车的四个点,我在 Excel 表里提前标过

跑通电路只是第一步,运动码表课设的真正难点在调试。以下四个问题,是我带过的设计里出现频率最高的,每个都能从 Excel 表里找到根源。

5.1 长按按钮导致状态反复横跳

症状:按一下启动键,状态在 RUN 和 PAUSE 之间来回切换,像 PPT 自动播放一样停不下来。原因不是状态表写错,而是没有做边沿检测,输入 A 的高电平期间每个时钟周期都会导通一次。排查时可以打开 Logisim 的单步时钟,手动 tick 几下观察状态。如果每 tick 一次状态就翻一次,说明按钮信号没有被转换成单脉冲。

解决方法是前面说的边沿检测。在 Logisim 里可以简单用寄存器芯片或者 D 触发器打一拍,再和原始信号做“当前为 1、上一拍为 0”的组合判断。注意:检查边沿检测电路本身能不能工作,要手动制造一个上升沿,而不是用手一直按住按钮慢慢看。

5.2 清零信号异步且太快,计数器没清干净

如果 CLR 信号是直接从状态机组合逻辑输出接到计数器异步复位端,问题在于:按下 RESET 后状态从 RUN 变到 STOP,组合逻辑输出 CLR 变成 1,计数器清零;但下一次时钟边沿到来时状态仍然保持 STOP,CLR 依然是 1,看起来没问题。问题出在从“按下 RESET”到“下一拍状态真正变成 STOP”之间,有一个时钟周期的延迟,而这个延迟里计数器还在 RUN 状态的 EN=1 控制下继续累加了一拍。

更稳妥的做法是采用同步清零:让 CLR 作为计数器组合逻辑的一部分,在 D 触发器搭的计数器里,把 CLR 和 EN 一起放在次态计算的优先级最前面。CLR=1 时,不管当前计数值是多少,下一拍统一回到 0。这样清零动作和时钟边沿对齐,不会产生半个时钟周期的乱码。

5.3 未定义状态 11 让电路“假死”

症状:电路一上电或者随便按了几下之后,数码管显示乱码,怎么按按键都没反应。多半是状态寄存器进入了 11 编码,而组合逻辑里 11 的次态没有定义。前面我在状态转换表里专门给 11 留了四行,全部映射到 00,就是要防止这种情况。

如果你已经在 Excel 里写了包含 11 行的完整 16 行表,就能提前发现问题。如果在 Logisim 里改真值表时把 11 行空着或者填成了保持 11,就等于制造了一个死锁状态。上电初始状态不确定时,D 触发器完全可能落到 11。

5.4 用 Excel 逐行对照仿真结果

调试状态机最笨也最有效的方法,是一行一行地用 Logisim 手调输入,观察输出,和 Excel 表核对。

具体操作:把 Logisim 时钟停掉,手动把输入 Q1Q0AB 设置成一个值,比如 0、1、1、0(RUN + 按下启动),观察输出 D1D0 是否等于 1、0、0、0,也就是 PAUSE。如果组合分析生成的电路输出和 Excel 表不一致,说明转录真值表时漏行、填错位,或者生成的电路被手动改过。不要怕这个方法慢,运动码表的状态转换表只有 16 行,逐行走一遍也就十几分钟,定位到的都是致命问题。

七段译码部分也可以用同样办法验证:给 BCD 输入设一个十进制数,比如 5,看七段输出是不是 1011011。如果哪一段不对,直接用查找表反推是哪一行抄错,比盯着电路图看半天快得多。

6. 一点实操经验

我自己的习惯是把设计文件命名为“码表设计表.xlsx”,三个 sheet 分别放状态转换表、计数器真值表、七段译码表。状态转换表里用条件格式把 RESET 优先的行标成浅红色,把未定义状态 11 的行标成浅蓝色;七段译码表里用色块区别亮段和灭段。答辩的时候不用费劲画状态图,直接把 Excel 表投影出来,从状态跳转讲到进位输出,再到每段数码管点亮条件,逻辑非常完整。

这个方法也不只适用于运动码表。交通灯控制器、洗衣机状态机、电梯楼层控制器,凡是“状态机 + 组合逻辑输出”的课设,都可以先用 Excel 把真值表坐实,再交给 Logisim 生成电路。你在表上多花的半小时,通常会帮你省下调试时的三小时。

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

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

立即咨询