说明
每次按下计数键时触发INT0中断,中断程序累加计数, 计数值显示在3只数码管上,按下清零键时数码管清零
Proteus仿真
使用到的元器件:
单片机:AT89C51
电容:CAP
极性电容:CAP-ELEC
电阻:RES、RESPACK-7
晶振:CRYSTAL
按键:BUTTON
数码管:7SEG-COM-CAT-GRN
C51代码
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
//段码0-9、所有段关闭
uchar code DSY_CODE[] =
{
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x00
};
uchar Display_Buffer[3] = {0, 0, 0};
uint Count = 0;
sbit Clear_Key = P3^6;
// 延时函数,用于按键去抖和显示稳定
void DelayMs(uint ms)
{
uchar i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}
// 显示计数器值到数码管
void Show_Count_ON_DSY()
{
// 数值分解为百位、十位和个位
Display_Buffer[2] = Count / 100;
Display_Buffer[1] = (Count % 100) / 10;
Display_Buffer[0] = Count % 10;
//赋值为0x0a是隐藏0,不显示百位和十位的0
if (Display_Buffer[2] == 0)
{
Display_Buffer[2] = 0x0a; // 不显示百位上的 0
if (Display_Buffer[1] == 0)
{
Display_Buffer[1] = 0x0a; // 不显示十位上的 0
}
}
// 设置 P0, P1, P2 连接到三个数码管
P0 = DSY_CODE[Display_Buffer[0]]; // 个位
P1 = DSY_CODE[Display_Buffer[1]]; // 十位
P2 = DSY_CODE[Display_Buffer[2]]; // 百位
}
void main()
{
P0 = 0xff;
P1 = 0xff;
P2 = 0xff;
//IE是51单片机的中断使能寄存器,用于控制是否允许各个中断触发
//在IE寄存器中,每一位对应一个中断的使能控制位
//如果你的程序只用 INT0,且不关心其他中断可以使用此方法设置中断,但是不推荐,推荐逐位写法
//IE = 0x81;等价于EA = 1;EX0 = 1;
IE = 0x81; // 使能外部中断 1000 0001
IT0 = 1; // 设置外部中断0为下降沿触发
while(1)
{
if (Clear_Key == 0) //清零按钮按下
{
Count = 0;
DelayMs(20); //延时消抖
}
Show_Count_ON_DSY();
DelayMs(10); //显示稳定延时
}
}
// 外部中断服务函数,外部中断0触发时执行,计数加 1
//外部中断服务函数的命名不受限制,但是必须遵守特定格式
//void 函数名() interrupt 中断号
//EX_INT0只是一个函数名,可以换成任何名称;但是interrupt 0必须保留,它表示这个函数是外部中断0的中断服务程序
void EX_INT0() interrupt 0
{
Count++;
DelayMs(50); // 延时消抖
}
IE(中断使能寄存器)介绍
IE 是 8051 单片机的中断使能寄存器(Interrupt Enable Register),用于控制是否允许各个中断触发。
在 IE 寄存器 中,每一位对应一个中断的使能控制位:
提示: 如果你的程序需要多个中断,建议使用逐位赋值,而不是直接赋值 IE = 0xXX;,这样可以避免误关其他中断。