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

Arduino Mega Pro定时器与ADC异常:LM35读数始终为零求助

问题排查与解决方案

1. 检查Timer1配置对ADC的干扰

Arduino Mega的16位Timer1与ADC共享部分系统资源,若bit16_timer_1_init()函数修改了ADC相关寄存器,会直接导致ADC无法工作:

  • 误开启ADC触发源并选择Timer1作为触发(ADCSRA的ADATE位+ADCSRB的ADTS位配置)
  • 修改ADC时钟分频,使其超出50kHz-200kHz的正常工作范围(由ADCSRA的ADPS位控制)

解决:
在定时器初始化函数末尾,强制恢复ADC默认配置:

// 恢复ADC自由运行模式,时钟分频128(16MHz/128=125kHz,符合ADC要求)
ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
ADCSRB = 0; // 关闭外部触发,使用默认自由运行

2. 清理ISR中的冗余操作

Timer1的中断服务函数(ISR)若执行耗时操作或误修改ADC寄存器,会打断analogRead的转换流程。

解决:

  • ISR仅做最小化操作:仅设置print_data_flag为true,禁止在ISR中调用analogRead或串口打印
  • 检查ISR代码,确保未修改ADCSRA、ADCSRB等ADC相关寄存器

3. 重置Timer1寄存器避免残留问题

你提到注释init()后定时器仍运行,是因为Timer1的初始化由bit16_timer_1_init()完成,之前的配置残留或未清除的中断标志会导致ISR持续触发。

解决:
在定时器初始化函数开头,先重置所有Timer1寄存器:

void bit16_timer_1_init() {
  // 完全重置Timer1状态
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  TIMSK1 = 0; // 先关闭中断
  TIFR1 = _BV(OCF1A) | _BV(OCF1B) | _BV(ICF1); // 清除所有挂起的中断标志

  // 后续你的定时器配置代码(示例为CTC模式,1秒触发一次)
  TCCR1B |= _BV(WGM12);
  OCR1A = 15624; // 16MHz/1024分频,每秒触发一次
  TCCR1B |= _BV(CS12) | _BV(CS10); // 分频1024
  TIMSK1 |= _BV(OCIE1A); // 开启比较匹配A中断
}

4. 确认ADC引脚无功能冲突

Arduino Mega部分引脚支持复用(如PWM),若Timer1的PWM引脚与你的ADC引脚重叠,会导致引脚功能冲突。

解决:

  • 显式设置ADC引脚为输入模式:pinMode(A0, INPUT);(analogRead虽会自动设置,但显式操作更稳妥)
  • 避免将ADC引脚用作Timer1的PWM输出(Timer1对应引脚为11、12、13)

5. 测试最小化验证代码

编写极简代码排除其他逻辑干扰,确认核心功能是否正常:

#include <avr/io.h>
#include <avr/interrupt.h>

volatile bool print_flag = false;

void bit16_timer_1_init() {
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  TIMSK1 = 0;
  TIFR1 = _BV(OCF1A);

  TCCR1B |= _BV(WGM12);
  OCR1A = 15624;
  TCCR1B |= _BV(CS12) | _BV(CS10);
  TIMSK1 |= _BV(OCIE1A);
}

ISR(TIMER1_COMPA_vect) {
  print_flag = true;
}

void setup() {
  Serial.begin(9600);
  bit16_timer_1_init();
  sei(); // 开启全局中断
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
}

void loop() {
  if (print_flag) {
    int temp1 = analogRead(A0);
    int temp2 = analogRead(A1);
    Serial.print("Temp1: ");
    Serial.print(temp1);
    Serial.print(", Temp2: ");
    Serial.println(temp2);
    print_flag = false;
  }
}

若这段代码能正常读取数值,说明原始代码中存在变量冲突、第三方库干扰等其他问题。


内容的提问来源于stack exchange,提问作者Ahmed Rifaat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 15:47:18