在51单片机上秒表计时器在0~59秒范围内循环计时,每次增加1秒。 当复位键有效时,该计时器清零后停止计时。在复位键无效的前提下,当使能键有效时该计时器开始计时,当使能键无效时该计时器暂停计时。并使用两位数码管动态显示计时值。
时间: 2023-05-25 16:03:35 浏览: 83
本题需要用到51单片机的定时器和外部中断功能,可以采用下面的方法实现:
1. 定义计时器的中断服务函数,每次中断时将秒数加1,并判断是否超过59。如果超过59,则将秒数清零,重新开始计时。
2. 定义复位键的外部中断服务函数,当复位键按下时,将秒数清零,并停止计时。
3. 定义使能键的外部中断服务函数,当使能键按下时,开始计时;当使能键松开时,暂停计时。
4. 在主函数中初始化计时器和外部中断,然后进入循环。在循环中,将秒数转化为两位数码管的显示,并不断更新,以达到动态显示的效果。
下面是具体代码实现(注释中已经详细解释了每个部分的具体实现方法):
```c
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit EN = P1^0; // 使能键
sbit CLR = P1^1; // 复位键
uchar code table[] = {
// 数码管显示表格
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90
};
uchar seconds = 0; // 秒数
bit timer_enable = 0; // 计时器使能标志
bit timer_running = 0; // 计时器运行标志
// 定时器中断服务函数
void timer_isr() interrupt 1
{
TH0 = 0x3C; // 重新设置计时器初值
TL0 = 0xB0;
seconds++; // 秒数加1
if (seconds >= 60) // 超过59秒,清零并重新开始计时
seconds = 0;
}
// 复位键中断服务函数
void clr_isr() interrupt 0
{
if (CLR == 0) // 复位键按下
{
seconds = 0; // 秒数清零
timer_enable = 0; // 停止计时
timer_running = 0;
}
}
// 使能键中断服务函数
void en_isr() interrupt 2
{
if (EN == 0) // 使能键按下
{
timer_enable = 1; // 开始计时
timer_running = 1;
}
else // 使能键松开
{
timer_enable = 0; // 暂停计时
timer_running = 0;
}
}
// 延时函数,调整数码管显示的亮度
void delay(uint n)
{
uint i, j;
for (i = 0; i < n; i++)
for (j = 0; j < 100; j++);
}
void main()
{
uchar i, j, k;
TMOD = 0x01; // 定时器0工作在模式1
TH0 = 0x3C; // 计时器初值,0.01s中断一次
TL0 = 0xB0;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许计时器中断
EA = 1; // 开启总中断
IT0 = IT1 = 1; // 外部中断采用下降沿触发
while (1)
{
if (timer_enable) // 如果计时器使能
{
if (!timer_running) // 如果计时器没有在运行
{
// 启动计时器并设置运行标志
TR0 = 1;
timer_running = 1;
}
}
else // 如果计时器没有使能
{
if (timer_running) // 如果计时器在运行
{
// 停止计时器并清除运行标志
TR0 = 0;
timer_running = 0;
}
}
// 将秒数转化为两位数码管的显示
i = seconds / 10; // 十位数
j = seconds % 10; // 个位数
k = 8; // 数码管位选择
// 动态显示每一位
P0 = table[i];
P2 = k;
delay(1);
P0 = 0xFF; // 灭数码管
k = 4;
P2 = k;
delay(1);
P0 = table[j];
P2 = k;
delay(1);
P0 = 0xFF; // 灭数码管
}
}
```