#include <REGX52.H>
// 数码管位选控制引脚定义
sbit SEG1=P2^2;
sbit SEG2=P2^3;
sbit SEG3=P2^4;
// 按键和蜂鸣器引脚定义
sbit K1=P3^2;
sbit Buzzer=P1^5;
// 全局变量定义
unsigned int sec=60; // 倒计时秒数
unsigned int count=0; // 定时器计数
bit is_counting=0; // 倒计时状态标志
/**
* @brief 毫秒级延时函数
* @param xms 需要延时的毫秒数
* @note 通过嵌套循环实现软件延时,延时时间约为xms毫秒
*/
void Delay_ms(unsigned int xms)
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
// 共阴数码管段码表(0-9)
// 0 1 2 3 4 5 6 7 8 9
unsigned char Number1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/**
* @brief 数码管显示函数
* @param Location 数码管位置(1-8)
* @param Num 显示的数字(0-9)
* @note 通过位选和段选控制数码管显示,包含消隐处理
*/
void Nixie(unsigned char Location,Num)
{
switch(Location)
{
case 1: P2_4=1;P2_3=1;P2_2=1;break;
case 2: P2_4=1;P2_3=1;P2_2=0;break;
case 3: P2_4=1;P2_3=0;P2_2=1;break;
case 4: P2_4=1;P2_3=0;P2_2=0;break;
case 5: P2_4=0;P2_3=1;P2_2=1;break;
case 6: P2_4=0;P2_3=1;P2_2=0;break;
case 7: P2_4=0;P2_3=0;P2_2=1;break;
case 8: P2_4=0;P2_3=0;P2_2=0;break;
}
P0=Number1[Num];
Delay_ms(5); // 显示延时,增强数码管亮度
P0=0x00; // 消隐,消除重影
}
/**
* @brief 显示倒计时秒数
* @param num 需要显示的秒数(0-99)
* @note 将秒数拆分为十位和个位分别显示
*/
void display(unsigned int num)
{
Nixie(1,num/10); // 显示十位
Delay_ms(5);
Nixie(2,num%10); // 显示个位
Delay_ms(5);
}
/**
* @brief 蜂鸣器发声函数
* @note 通过高低电平交替产生约500Hz的方波,驱动蜂鸣器发出声音
*/
void Buzzer_on()
{
unsigned int i;
for(i=0;i<500;i++)
{
Buzzer=1;
Delay_ms(1);
Buzzer=0;
Delay_ms(1);
}
}
/**
* @brief 定时器1初始化函数(10ms)
* @note 配置定时器1为模式1(16位),定时10ms
*/
void timer1_init()
{
TMOD |= 0x10; // 定时器1模式1(16位)
TH1 = 0xD8; // 定时初值,10ms@12MHz
TL1 = 0xF0; // 12MHz晶振下的初值(65536-10000)
ET1 = 1; // 使能定时器中断
TR1 = 1; // 启动定时器
}
/**
* @brief 外部中断0初始化函数
* @note 配置外部中断0为下降沿触发
*/
void ext0_init()
{
IT0 = 1; // 下降沿触发
EX0 = 1; // 使能外部中断0
EA = 1; // 开总中断
}
/**
* @brief 定时器1中断服务函数
* @note 每10ms触发一次,累计100次为1秒,更新倒计时秒数
*/
void timer1_isr() interrupt 3
{
TH1 = 0xD8; // 重新加载初值
TL1 = 0xF0;
if(is_counting && sec>0)
{
count++;
if(count>=100) // 100 * 10ms = 1s
{
count=0;
sec--;
if(sec==0) // 倒计时为0时蜂鸣器响
{
Buzzer_on();
}
}
}
}
/**
* @brief 外部中断0服务函数
* @note 按键按下时触发,重置倒计时为60秒并开始计时
*/
void ext0_isr()interrupt 0
{
Delay_ms(20); // 消抖延时
if(K1==0) // 确认按键按下
{
sec = 60; // 重置为60秒倒计时
count = 0; // 清除定时器计数
is_counting = 1; // 开始倒计时
}
}
/**
* @brief 主函数
* @note 系统入口函数,初始化定时器和中断,然后循环显示倒计时
*/
void main()
{
timer1_init(); // 初始化定时器1
ext0_init(); // 初始化外部中断0
is_counting = 1; // 默认启动时就开始倒计时
while(1)
{
display(sec); // 循环显示当前秒数
}
}