中断定时器60秒倒计时

#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);        // 循环显示当前秒数
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值