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

Arduino Mega替代Uno运行电容式传感器代码的定时器中断适配问题

代码适配Arduino Mega的修改方案

核心问题原因

你代码的问题核心是直接操作了Arduino核心占用的Timer0相关变量和寄存器,ATmega2560(Mega的主控)和ATmega328P(Uno的主控)的Timer0相关变量暴露规则、寄存器操作逻辑有差异,具体修改点如下:

修改点1:替换废弃的timer0_overflow_count调用

旧版Uno核心对外暴露了timer0_overflow_count变量,但Mega所用的AVR核心已经将该变量改为内部私有静态变量,你写的extern声明无法获取正确值,直接废弃手动计时逻辑,改用Arduino官方提供的micros()函数实现计时,兼容性更强。

修改点2:移除对系统Timer0的直接修改

直接重置TCNT0和计时器溢出计数会打乱Mega系统自带的millis()、delay()等函数的正常运行,改用官方计时函数后完全规避该问题。

修改点3:保留原端口操作逻辑

原代码中对PORTH、PINH的操作对应Mega的数字引脚8,只要你硬件接线正确无需额外修改。

修改后完整可运行代码

#define resolution 8
#define mains 60 // 60: 北美、日本; 50: 其他大部分地区
#define refresh 2 * 1000000 / mains

void setup() {
  Serial.begin(9600);

  // unused引脚拉低减少干扰
  for(int i = 2; i < 14; i++) {
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }

  for(int i =22; i < 53; i++){
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }

  pinMode(8, INPUT);
}

void loop() {  
  Serial.println(time(8, B00100000), DEC);
} 

long time(int pin, byte mask) {
  unsigned long count = 0, total = 0;
  unsigned long start = micros();
  while(micros() - start < refresh) {
    pinMode(pin, OUTPUT);
    PORTH = 0;
    pinMode(pin, INPUT);
    while((PINH & mask) == 0)
      count++;
    total++;
  }
  return (count << resolution) / total;
}

如果你坚持要使用寄存器操作计时器,可以改用Mega上未被系统默认占用的Timer1/Timer3/Timer4/Timer5,修改时注意16位定时器的寄存器操作规则即可。

内容的提问来源于stack exchange,提问作者Renan Almeida

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 06:57:03