8051 入门项目里,秒表几乎是最常见的一类练习:功能不复杂,但会同时用到按键输入、状态切换、时间控制和端口输出。这篇内容按“先看目标,再拆代码职责,最后串回主循环”的顺序重写,帮助你判断这套实现到底做了什么、能显示到什么范围,以及它在仿真里为什么能跑起来。
先明确这个秒表要实现什么
这次的目标,是在 8051 系列单片机开发板上做一个简化秒表:用户通过按钮控制开始或暂停计时,LED 负责显示已经过去的时间。
从代码结构来看,这个程序实际完成的是一套很典型的入门方案:
- 用一个计数变量记录当前已经过去的秒数;
- 用一个标志位记录秒表当前是运行还是暂停;
- 通过外部中断 0 响应按键动作;
- 通过 P0 口把计数结果输出到 LED;
- 借助延时函数,让计数按固定节奏更新。
如果你是在仿真软件里练习 8051 基础,这样的设计足够直接:按键只负责切换状态,主循环只负责显示与计数,代码容易看懂,也方便后续继续扩展。
全局变量和延时函数分别负责什么
程序开头先引入了 8051 常用头文件,并定义了两个全局变量:
#include <reg51.h>
unsigned int k;
unsigned int panduan;
这里的 k 用来保存计数结果,也就是已经过去的秒数;panduan 则是状态标志位,用来表示秒表是否处于运行状态。后面的逻辑会围绕这两个变量展开。
接着是延时函数:
void delay(unsigned int n)
{
unsigned int i=0,j=0;
for(i=0;i<n;i++)
{
for(j=0;j<120;j++);
}
}
这个函数使用双重循环消耗 CPU 周期,以此形成软件延时。对这类教学示例来说,这种写法足够直观,能让 LED 刷新和计数变化看起来接近“按秒跳动”。
不过也要注意,这里并不是真正基于硬件定时器的精确定时,而是依赖循环次数来近似延时。所以它更适合做原理验证和仿真演示,而不是对计时精度要求很高的正式应用。
按键为什么要交给外部中断处理
秒表需要随时响应按钮输入,因此示例选择启用 8051 的外部中断 0。初始化函数如下:

void initex()
{
IT0=1;
EX0=1;
EA=1;
}
这几句配置的作用可以直接对应理解:
IT0=1;:把外部中断 0 设置为边沿触发;EX0=1;:允许外部中断 0;EA=1;:打开总中断允许。
有了这一步,按键动作就不需要在主循环里不停轮询,而是可以在触发中断时立即切换状态。
中断服务程序本身也保持了很简洁的写法:
void exisr() interrupt 0
{
panduan=!panduan;
}
它只做一件事:把 panduan 取反。也就是说,第一次按下按钮时,标志位从 0 变成 1,秒表开始计时;再次按下时,标志位从 1 变回 0,秒表暂停。
这种“中断只切状态、主循环再执行显示和计数”的分工非常适合入门项目,因为逻辑边界清楚,也能避免把太多处理塞进中断函数里。
显示函数怎样完成计数和 LED 输出
秒表的核心行为,集中在 display() 函数中:

void display()
{
if(panduan==1)
k++;
if(k<256)
{
P0=~(0x00+k);
delay(1000);
}
else
{
P0=~0x00;
delay(1000);
}
}
这段逻辑可以拆成两部分来看。
1. 什么时候递增计数
只有当 panduan==1 时,程序才执行 k++;。这意味着按键切到运行状态后,计数器才会继续向上增加;如果处于暂停状态,k 会保持当前值不变。
2. LED 如何显示当前秒数
当 k<256 时,程序执行:
P0=~(0x00+k);
这里相当于把 k 的数值送到 P0 口,再经过按位取反后输出。因为 8 位端口最多能直接表达 0 到 255 的变化,所以这套显示方式天然对应 256 个状态。
一旦 k 超过这个范围,程序就进入 else 分支:
P0=~0x00;
也就是说,超出 255 后不再继续显示更大的计数值,而是把端口恢复到固定输出状态。因此,这份代码更准确地说,是一个“0 到 255 范围内可显示”的简化秒表示例。
每次输出之后,程序都会调用一次 delay(1000);,用来拉开显示变化节奏。也正因为这个延时存在,LED 上看到的数字变化不会快得无法观察。
主函数如何把整个秒表跑起来
最后,所有模块都在主函数里被串起来:
void main(void)
{
initex();
while(1)
{
display();
}
}
主函数做的事其实只有两步:
- 先调用
initex();,完成外部中断初始化; - 再进入
while(1)无限循环,不断执行display();。
这样一来,程序运行流程就很清晰了:中断负责接收按键并切换运行状态,主循环负责根据状态决定是否计数,再把结果送到 P0 口显示。
如果你只是想快速搭出一个能在仿真里运行的 8051 秒表示例,这份代码已经具备完整闭环;如果想继续提升,它后面还能自然延伸到硬件定时器计时、数码管显示、清零按键、计数回绕等更常见的功能。
这份 8051 秒表示例适合拿来做什么
从教学角度看,这个例子最大的价值不在“做出了一个多复杂的秒表”,而在于把 8051 的几个基础知识点放进了同一个项目里:变量控制状态、软件延时塑造节奏、外部中断响应按键、P0 口承担显示输出。
因此,它很适合用来完成两件事:
- 理解 8051 程序里“中断 + 主循环”的基本分工;
- 在仿真环境中快速验证按键控制和端口显示是否正常。
同时也要有一个清楚判断:这份实现更偏向入门演示,而不是高精度计时方案。它能帮助你把功能跑通,但如果后续要做更稳定、更准确的秒表,下一步通常就是把软件延时替换为定时器方案,再重新设计显示与计数范围。













