You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Arduino乒乓游戏Timer中断不工作 秒数始终显示0问题求助

问题根因排查

1. 中断计数逻辑错误

你当前使用的是Timer1的溢出中断,结合主流Arduino Uno的硬件特性:

  • 主控ATmega328P主频为16MHz,你设置了256预分频,Timer1的计数频率为 16000000 / 256 = 62500 Hz
  • 16位定时器的最大计数值为65535,每计满65536个时钟周期才会触发1次溢出中断,两次溢出中断的间隔约为1.048秒
  • 你在ISR中是每触发1次溢出中断才给counter加1,要等counter累加到62500才会让seconds加1,换算下来需要近18小时才会出现seconds不为0的情况,所以你看到的输出始终是0。

2. 缺少串口初始化

你在loop中直接调用Serial.print(),但setup()里没有添加Serial.begin(波特率)的初始化代码,串口输出本身也会异常,也是输出异常的原因之一。


修复方案

建议改用CTC比较匹配中断实现,计时精度更高,更符合你的60秒计时需求,参考代码如下:

volatile uint16_t seconds = 0;
// 计时启停控制变量,游戏回合开始时设为true,结束/超时时设为false
volatile bool timer_running = false;
// 超时标记,中断里触发超时后可以在主循环判断处理
volatile bool time_out = false;

void setup() 
{
  Serial.begin(115200); // 初始化串口,波特率要和串口监视器配置一致
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  // 16MHz主频+256预分频下,1秒对应62500个计数,从0开始计数所以要减1
  OCR1A = 62499;
  TCCR1B |= (1 << WGM12); // 开启CTC模式
  TCCR1B |= (1 << CS12);  // 配置256预分频
  TIMSK1 |= (1 << OCIE1A); // 开启比较匹配A中断
  interrupts();
}

// 比较匹配中断服务函数,每秒触发1次
ISR(TIMER1_COMPA_vect)
{
  if(!timer_running) return;
  seconds++;
  if(seconds >= 60) {
    timer_running = false;
    time_out = true;
  }
}

void loop() 
{
  // 读取中断修改的变量时建议关中断,避免8位机读16位变量时被中断打断出现数值错误
  noInterrupts();
  uint16_t current_sec = seconds;
  bool current_timeout = time_out;
  interrupts();

  Serial.println(current_sec);
  if(current_timeout) {
    // 这里添加60秒超时的处理逻辑
  }
  
  game = update();
  lcd.clear(); 
  render();
}

注意事项

  • 游戏单回合开始时,需要关中断后重置seconds = 0、time_out = false、timer_running = true启动计时
  • 游戏单回合提前结束时,需要将timer_running设为false停止计时,避免影响下一轮计数

内容的提问来源于stack exchange,提问作者Doesnt Matter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 05:45:09