почему АЦП всегда читает 1023 независимо от ввода - PullRequest
0 голосов
/ 11 мая 2019

Я пытаюсь прочитать аналоговое напряжение с помощью АЦП в attiny85. Но регистр АЦП всегда читает 1023 независимо от того, что вводится.

Более того, когда вывод АЦП измеряется мультиметром, он показывает почти 3,1 В. Я предположил, что он подтянулся, но на самом деле, когда я подключаю вывод к его аналоговому входу, напряжение на выводе нарушает цепь входного напряжения. Я не знаю, почему это происходит. тот же код работал хорошо до 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;
}

Обновление

следующее изображение описывает мой выход различных каналов АЦП для одного и того же входного напряжения.

выход канала АЦП 2

выход канала АЦП 3

1 Ответ

2 голосов
/ 11 мая 2019

Когда АЦП сконфигурирован с 2.56V в качестве опорного напряжения, то все напряжения на уровне 2,56 и выше будут читать как максимальное значение АЦП, т.е. 1023. То же самое касается 3,1 В.

Возможно, проблема во включенном внутреннем подтягивании:

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

Включенное подтягивание будет источником дополнительного тока и изменением напряжения на входе. Вы никогда не должны использовать внутренние подтягивания с АЦП, так как значение подтягивания отличается от части к части в диапазоне 20k ... 50k, и точное значение трудно предсказать.

Вы должны отключить его:

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

При необходимости используйте внешнее извлечение известного значения.

...