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

Arduino Uno使用ADC寄存器替代analogRead测量电容结果错误求助

寄存器版本代码问题排查与修复

核心问题点

  • 参考电压配置错误
    原analogRead默认使用AVcc(5V)作为参考电压,你寄存器配置中ADMUX |= B10000000对应REFS1=1、REFS0=0,属于ATmega328P保留配置,实际参考电压远低于5V。阈值972对应5V参考下的约4.74V,在低参考电压下对应的实际充电电压极低,自然充电时间大幅缩短,电容计算结果偏小。
  • ADC转换未完成就读取结果
    你设置ADSC位触发转换后,没有等待转换完成就直接读取ADCL/ADCH寄存器,拿到的是无效的旧值或未完成转换的错误值,进一步导致采样逻辑异常。
  • PD5引脚拉低逻辑错误
    放电阶段的PORTD &= B00000100会清空PORTD除第2位外的所有引脚电平,仅关闭PD5的正确写法是PORTD &= ~(1 << 5),错误的电平操作也会影响充放电逻辑。

修正后的寄存器版本代码

unsigned long starttime = 0;
unsigned long endtime = 0;
double C = 0;
float n = 3.0;  //时间常数
float resistor = n*998000.0;
int value = 0;

void setup() {
  Serial.begin(9600);
  // 设置PD5为输出,不影响其他引脚方向
  DDRD |= B00100000;
  PORTD &= ~B00100000; 
  
  sei();
  ADMUX &= B00000000; //清空所有位
  ADMUX |= B01000000; // REFS1=0、REFS0=1,使用AVcc作为参考电压,和默认analogRead配置一致,选择A0通道
  ADCSRA |= B10000110; // 开启ADC,预分频64,ADC时钟250KHz
}

void loop() {
  // 启动充电
  PORTD |= (1<<5);
  starttime = micros();
  do{
    ADCSRA |= (1 << ADSC); // 触发ADC转换
    while(ADCSRA & (1 << ADSC)); // 等待转换完成
    value = ADCL | (ADCH << 8); // 先读ADCL再读ADCH,读取转换结果
    Serial.println(value);
  }while(value<972);

  endtime = (micros() - starttime);
  C = ((double)endtime/resistor);
  Serial.println(C, 9);

  // 启动放电,仅拉低PD5
  PORTD &= ~(1 << 5);
  do{
    ADCSRA |= (1 << ADSC);
    while(ADCSRA & (1 << ADSC));
    value = ADCL | (ADCH << 8);
  }while(value > 0);
}

验证说明

修正后参考电压和官方analogRead完全一致,每次ADC采样都等待转换完成拿到正确值,充放电引脚操作逻辑正确,采样速率会比官方analogRead快3~5倍,电容测量结果和原代码一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 00:27:05