Аналоговый вход.

seri0shka
seri0shka аватар
Offline
Зарегистрирован: 19.11.2018

Пытаюсь побороть ATTiny26L. С цифровыми выходами более-менее разобрался, а с аналоговым входом не получается. Задача- измерить напряжение на входе АС9 (у ATTiny26L аналоговых входов 10 штук, в отличие от Атмеги8).

Вот урезанная версия кода для измерения напряжение на входе АС9 (выдрано на просторах интернета, номер входа подкорректировал под свой случай):

int main()
{
  ADCSRA |= (1 << ADEN) // Включаем АЦП
            | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // устанавливаем предделитель преобразователя на 128

  ADMUX |= (0 << REFS1) | (1 << REFS0) // выставляем опорное напряжение Vcc
           | (1 << MUX0) | (0 << MUX1) | (0 << MUX2) | (1 << MUX3); // снимать сигнал будем с входа AC9

  while (1)
  {
    do {
      ADCSRA |= (1 << ADSC);  // Начинаем преобразование
    }
    while ((ADCSRA & (1 << ADIF)) == 0); // пока не будет выставлен флаг об окончании преобразования
    int data = (ADCL | ADCH << 8); // Считываем полученное значение
  }
}

Без аналогового входа всё работает, вот пример кода для отображения на индикаторе числа от 000 до 999 (аналоговая часть закомментирована, если разкомментировать, выводится число 423 независимо от напряжения на входе, причём с потухшим сегментом от порта  РА3) :

#include <util/delay.h>
unsigned char Dig[10];
byte Disp1, Disp2, Disp3;
int Disp;
int qwer;


int main()
{
  DDRB = 56;// B00111000 - назначаю выходами порты PB3, PB4, PB5
  DDRA = 255;// назначаю выходами все порты A
  PORTB = 0;
  PORTA = 255;

  /*
    ADCSRA |= (1 << ADEN) // Включаем АЦП
              | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // устанавливаем предделитель преобразователя на 128

    ADMUX |= (0 << REFS1) | (1 << REFS0) // выставляем опорное напряжение Vcc
             | (1 << MUX0) | (0 << MUX1) | (0 << MUX2) | (1 << MUX3); // снимать сигнал будем с входа AC9
  */
  _delay_ms(2000);//
  Dig_init();


  while (1)
  { //
    qwer ++;
    if (qwer > 20) {
      Disp ++;
      qwer = 0;
    }

    /*   do {
         ADCSRA |= (1 << ADSC);  // Начинаем преобразование
       }
       while ((ADCSRA & (1 << ADIF)) == 0); // пока не будет выставлен флаг об окончании преобразования
       int data = (ADCL | ADCH << 8); // Считываем полученное значение
    */
    Display (Disp);
  }
}

// Функция выделяет цифры из трехзначного числа Number
void Display (int Number)
{
  int Num1, Num2, Num3;
  Num1 = Num2 = 0;
  while (Number >= 100)
  {
    Number -= 100;
    Num1++;
  }
  while (Number >= 10)
  {
    Number -= 10;
    Num2++;
  }
  Num3 = Number;
// динамическая индикация трёх разрядов на семисегментном индикаторе.
  PORTB |= _BV(5);
  PORTB |= _BV(4);
  PORTB &= ~_BV(3);// младший разряд
  PORTA = Dig[Num3];
  _delay_ms(1);

  PORTB |= _BV(5);
  PORTB &= ~_BV(4);// средний разряд
  PORTB |= _BV(3);
  PORTA = Dig[Num2];
  _delay_ms(1);

  PORTB &= ~_BV(5);// старший разряд
  PORTB |= _BV(4);
  PORTB |= _BV(3);
  PORTA = Dig[Num1];
  _delay_ms(1);
}

void Dig_init()
{
  Dig[0] = (250);   // схема с общим катодом, комбинации для символов 0...9
  Dig[1] = (34);
  Dig[2] = (185);
  Dig[3] = (171);
  Dig[4] = (99);
  Dig[5] = (203);
  Dig[6] = (219);
  Dig[7] = (162);
  Dig[8] = (251);
  Dig[9] = (235);
}

  Что я делаю не так?

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Для начала было пы неплохо внятно изложить проблему. 

- Полный код с проблемой

- Что ожидается при запуске 

- Что получается при запуске

seri0shka
seri0shka аватар
Offline
Зарегистрирован: 19.11.2018

Полный код с проблемой:

#include <util/delay.h>
unsigned char Dig[10];
byte Disp1, Disp2, Disp3;
int Disp;
int qwer;


int main()
{
  DDRB = 56;// B00111000 - назначаю выходами порты PB3, PB4, PB5
  DDRA = 255;// назначаю выходами все порты A
  PORTB = 0;
  PORTA = 255;

  
    ADCSRA |= (1 << ADEN) // Включаем АЦП
              | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // устанавливаем предделитель преобразователя на 128

    ADMUX |= (0 << REFS1) | (1 << REFS0) // выставляем опорное напряжение Vcc
             | (1 << MUX0) | (0 << MUX1) | (0 << MUX2) | (1 << MUX3); // снимать сигнал будем с входа AC9
  
  _delay_ms(2000);//
  Dig_init();


  while (1)
  { //
    qwer ++;
    if (qwer > 20) {
      Disp ++;
      qwer = 0;
    }

      do {
         ADCSRA |= (1 << ADSC);  // Начинаем преобразование
       }
       while ((ADCSRA & (1 << ADIF)) == 0); // пока не будет выставлен флаг об окончании преобразования
       Disp = (ADCL | ADCH << 8); // Считываем полученное значение
    
    Display (Disp/2);
  }
}

// Функция выделяет цифры из трехзначного числа Number
void Display (int Number)
{
  int Num1, Num2, Num3;
  Num1 = Num2 = 0;
  while (Number >= 100)
  {
    Number -= 100;
    Num1++;
  }
  while (Number >= 10)
  {
    Number -= 10;
    Num2++;
  }
  Num3 = Number;
// динамическая индикация трёх разрядов на семисегментном индикаторе.
  PORTB |= _BV(5);
  PORTB |= _BV(4);
  PORTB &= ~_BV(3);// младший разряд
  PORTA = Dig[Num3];
  _delay_ms(1);

  PORTB |= _BV(5);
  PORTB &= ~_BV(4);// средний разряд
  PORTB |= _BV(3);
  PORTA = Dig[Num2];
  _delay_ms(1);

  PORTB &= ~_BV(5);// старший разряд
  PORTB |= _BV(4);
  PORTB |= _BV(3);
  PORTA = Dig[Num1];
  _delay_ms(1);
}

void Dig_init()
{
  Dig[0] = (250);   // схема с общим катодом, комбинации для символов 0...9
  Dig[1] = (34);
  Dig[2] = (185);
  Dig[3] = (171);
  Dig[4] = (99);
  Dig[5] = (203);
  Dig[6] = (219);
  Dig[7] = (162);
  Dig[8] = (251);
  Dig[9] = (235);
}

Что ожидается при запуске: На семисегментном индикаторе должно отображаться число от 0 до 511 в зависимости от напряжение на входе АС9.

Что получается при запуске: На семисегментном индикаторе отображается число 511 независимо от напряжение на входе АС9. Сегмент от порта  РА3 (он же AREF) не отображается.

Если закомментировать строки 16...20 и 34...38, работают все сегменты и отображается число от 000 до 999 последовательно (то есть всё работает как должно).

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

В 19 строке для опорного выбираетс АREF, а не Vcc как в комментарии написано. Для Vcc оба бита должны быть 0

seri0shka
seri0shka аватар
Offline
Зарегистрирован: 19.11.2018

Блин, как просто всё оказалось!!! А я пять дней голову ломаю. Спасибо огромное! У меня мелькала догадка, когда понял, что потухший сегмент связан с AREF. Но я не развил её в нужном направлении...

И тогда ещё вопрос: можно ли заменить

ADMUX |= (0 << REFS1) | (0 << REFS0) // выставляем опорное напряжение Vcc
             | (1 << MUX0) | (0 << MUX1) | (0 << MUX2) | (1 << MUX3); // снимать сигнал будем с входа AC9

на что-то вроде

ADMUX = B001001;

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Пожалуйста.

Можно. Но потом разбираться или менять что-то будет намного менее удобдно.