AT89S51单片机P0口接有1个7段 LED 数码 管,初始显示0。外部输入引脚(P3.4)接有1个按钮开关。每当按钮开关按下1次时,并使数码管显示增1,当按下第10次时,数码管从9再变为0
时间: 2024-02-27 11:58:17 浏览: 120
这是一个常见的单片机练习题,需要使用定时器中断和外部中断来实现。
首先,需要初始化 P0 口为输出模式,同时将数码管显示 0。然后,需要初始化 P3.4 为输入模式,并使能外部中断。当 P3.4 引脚检测到电平变化时,会触发外部中断,执行中断服务程序。
在中断服务程序中,首先需要使用定时器中断来实现计时功能。每当定时器中断发生时,计数器加 1,并判断是否达到 10。如果达到 10,则将计数器清零,并将数码管显示 0;否则,将计数器的值显示在数码管上。
当 P3.4 引脚检测到电平变化时,会触发外部中断。在外部中断服务程序中,需要判断按钮状态。如果按钮按下,则将计数器加 1,并判断是否达到 10,执行相应的操作。
具体的代码实现可以参考以下示例:
```c
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit button = P3^4; // 按钮开关接在 P3.4 引脚上
sbit seg_a = P0^0; // 数码管 a 段接在 P0.0 引脚上
sbit seg_b = P0^1; // 数码管 b 段接在 P0.1 引脚上
sbit seg_c = P0^2; // 数码管 c 段接在 P0.2 引脚上
sbit seg_d = P0^3; // 数码管 d 段接在 P0.3 引脚上
sbit seg_e = P0^4; // 数码管 e 段接在 P0.4 引脚上
sbit seg_f = P0^5; // 数码管 f 段接在 P0.5 引脚上
sbit seg_g = P0^6; // 数码管 g 段接在 P0.6 引脚上
sbit seg_dp = P0^7; // 数码管 dp 点接在 P0.7 引脚上
uchar code seg_num[] = { // 数码管显示 0-9
0x3f, 0x06, 0x5b, 0x4f, 0x66,
0x6d, 0x7d, 0x07, 0x7f, 0x6f
};
uint counter = 0; // 计数器,记录按下按钮的次数
// 定时器中断,每 1ms 触发一次
void timer_isr() interrupt 1 {
static uint ms_count = 0;
TH0 = 0xfc; // 重新赋值定时器初值,产生 1ms 的定时时间
TL0 = 0x66;
ms_count++;
if (ms_count >= 10) { // 每 10ms 计数器加 1
ms_count = 0;
counter++;
if (counter >= 10) { // 如果计数器达到 10,则清零并显示 0
counter = 0;
P0 = seg_num[counter];
return;
}
}
P0 = seg_num[counter]; // 显示计数器的值
}
// 外部中断,当 P3.4 引脚检测到电平变化时触发
void ext_isr() interrupt 0 {
if (button == 0) { // 按钮按下时计数器加 1
counter++;
if (counter >= 10) { // 如果计数器达到 10,则清零并显示 0
counter = 0;
P0 = seg_num[counter];
return;
}
}
}
void main() {
TMOD = 0x01; // 定时器工作在模式 1,计数器初值为 0,定时时间为 1ms
TH0 = 0xfc;
TL0 = 0x66;
ET0 = 1; // 使能定时器中断
EA = 1; // 使能总中断
IT0 = 1; // 外部中断触发方式为下降沿
EX0 = 1; // 使能外部中断
P0 = seg_num[counter]; // 初始显示 0
while (1);
}
```
阅读全文