【问题标题】:why adc always reads 1023 irrespective of input为什么无论输入如何,adc 总是读取 1023
【发布时间】:2019-09-28 20:12:55
【问题描述】:

我正在尝试使用 attiny85 中的 ADC 读取模拟电压。但是无论给出什么输入,ADC 寄存器总是读取 1023。

此外,当用万用表测量 ADC 引脚时,它显示接近 3.1V。我以为它被拉高了,但事实是,当我将引脚连接到其模拟输入时,引脚上的电压会干扰输入电压电路。我不知道为什么会这样。相同的代码在 6 个月前运行良好,但现在不行了。原因不明。谁能解释我实际上做错了什么?我使用 USBasp 作为我的程序员,使用 attiny85 作为我的目标微控制器,使用 arduino 作为我的编译器。我也尝试使用 WinAVR 进行编译,但模拟输入引脚的电压仍然接近 3.1V。 在此先感谢:)

#define F_CPU 16000000UL
#define myTx PB1 //PB1
#define myRx PB0 //PB0
#define ADC_CH_2 PB4
#define ADC_CH_3 PB3

#include <SoftwareSerial.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
float ADCval;
int i = 0, p;

SoftwareSerial myPort(myRx, myTx); //rx,tx

ISR(ADC_vect) {

  p = ADCW;
  ADCval = (float)p * 5.00f / 1024.0f;


  //logging the data
  myPort.print(i++);
  myPort.print(" ADC: ");
  myPort.print(p);

  myPort.print(" voltage: ");
  myPort.println(ADCval);

}

int main(void) {
myPort.begin(9600);
MCUCR &= ~(1 << PUD); //disabling Pull Up Disable i.e, enabling pullups

//I/O configuration
DDRB &= ~(1 << ADC_CH_2) & ~(1 << ADC_CH_3); //configuring as input
PORTB |= (1 << ADC_CH_2) | (1 << ADC_CH_3); //  writing 1 to an input pin activates pullup-resistor
DIDR0 |= (1 << ADC_CH_2) | (1 << ADC_CH_3); // disable digital buffer
myPort.print("DDRB: ");
myPort.println(DDRB);

myPort.print("PORTB: ");
myPort.println(PORTB);

//ADC configuration

ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADIE); //enable conversion complete interrupt
ADCSRA |= (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2); // prescaler 128 - 16000000/128=125khz;
myPort.print("ADCSRA: ");
myPort.println(ADCSRA);

ADMUX &= ~(1 << ADLAR); // right most shift in ADCH and ADCL i.e, ADCH has two MSB bits and ADCL has 8 LSB bits



ADMUX |= (1 << REFS1) | (1 << REFS2); ADMUX &= ~(1 << REFS0); //Vref as 2.56V
ADMUX |= (1 << MUX1) | (1 << MUX0) ; ADMUX &= ~(1 << MUX2) & ~(1 << MUX3); //adc3

sei(); // enable all interrupts
myPort.print("ADMUX: ");
myPort.println(ADMUX);

while (1)
{
_delay_ms(1000);
ADCSRA |= 1 << ADSC;
myPort.print("DDRB: ");
myPort.println(DDRB);
myPort.print("ADMUX: ");
myPort.println(ADMUX);
myPort.print("ADCSRA: ");
myPort.println(ADCSRA);
myPort.print("PORTB: ");
myPort.println(PORTB);

}




return 0;
}

更新

下图描述了我在相同输入电压下不同 ADC 通道的输出。

output of ADC channel 2

output of ADC channel 3

【问题讨论】:

  • 我正在调查该代码,但我想问一下,可以吗? ADMUX &= ~(1
  • ISR 中的浮点运算和串行数据记录充其量是不明智的。
  • @dunajski 实际上变量 temp 是 ADMUX。在这里输入代码时我忘了更改它。
  • 有一条法律,当你问一些事情时,有人只回答一个问题:-)。我问的其他问题怎么样,然后我认为你应该编辑你的帖子,让他在没有这些错误的情况下回答更“有吸引力”。
  • 我很抱歉@dunajski,我将对其进行编辑并重新发布。谢谢你纠正我。

标签: arduino embedded avr attiny winavr


【解决方案1】:

当 ADC 配置为 2.56V 作为参考电压时,所有 2.56 及以上的电压将被读取为 ADC 的最大值,即 1023。 3.1 V 也是如此。

问题可能在于启用的内部上拉:

PORTB |= (1 << ADC_CH_2) | (1 << ADC_CH_3); //  writing 1 to an input pin activates pullup-resistor

启用上拉将提供额外的电流并改变输入电压。切勿将内部上拉电阻与 ADC 一起使用,因为上拉电阻的值在 20k...50k 范围内因器件而异,而且很难预测准确值。

你应该禁用它:

PORTB &= ~(1 << ADC_CH_2) & ~(1 << ADC_CH_3); //  disable pull-ups

如果需要,使用已知值的外部上拉。

【讨论】:

  • 引体向上已禁用。但仍然遇到同样的问题。
  • 但这并没有改变我的答案:3.1V > 2.56V,您将获得 ADC 值 1023。请检查您的原理图或在REFS1:0 位中使用另一个参考电压(例如 Aref 或 AVCC) ADMUX注册
  • 非常感谢@AterLux,您建议禁用上拉的解决方案适用于其他 adc 引脚。但即使禁用上拉,adc3 仍会读取 1023。可能是什么原因??
  • 我使用电阻分压器应用了 421mV 的测试输入,并使用万用表对其进行了验证。 ADC 在 adc2、adc1 中读取正确的值。但 adc3 读取 1023。
  • 我得到了解决方案。当我用另一个 attiny85 替换部件 (mcu) 时,一切都按预期工作。谢谢大家的讨论
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-23
  • 2020-09-09
相关资源
最近更新 更多