АЦП в avr328p

Тема в разделе "Микроконтроллеры AVR", создана пользователем Danil_2002, 27 май 2019.

  1. Danil_2002

    Danil_2002 Гик

    Добрый день!

    Помогите разобраться с получением результатов преобразования АЦП.

    Написал вот такую программу в качестве примера:
    Код (C++):

    void ADC_init()
    {
      ADMUX = (1 << REFS0); // V питания
      ADMUX |= (1 << ADIE);
      ADCSRA = (1 << ADEN) // Включаем ADC
      |(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0);
    }
    unsigned int ADC_convert()
    {
      ADCSRA |= (1 << ADSC);
      while(!(ADCSRA >> 4)&1); // Ждем результатов
      unsigned int result_ADC = (ADCL|ADCH << 8);
      return result_ADC;
    }
    int main()
    {
      ADC_init();
      Serial.begin(9600);
      while(1)
      {
        unsigned int result_ADC = ADC_convert();
        Serial.println(result_ADC);
      }
    }
    Эта программа должна получить показания АЦП с A0. К A0 подключен переменный резистор.
    Проблема в том, что монитор порта постоянно показывает 74 или 73, в чем проблема?
     
  2. Airbus

    Airbus Радиохулиган Модератор

    Как и куда подключен резистор?Если никак и никуда и ничего не подключено то 73-74 у.е это помехи на А0 которые ловит АЦП.
    Зачем столько кода?Я понимаю что это по-фен шую но есть же волшебная команда AnalogRead?
     
  3. Danil_2002

    Danil_2002 Гик

    Потенциометр подключен к А0. Я написал программу на Arduino для проверки, там результаты правильные.
     
  4. Airbus

    Airbus Радиохулиган Модератор

    Должно так-оодин вывод плюс второй GND а движок на А0.Так?
     
    Последнее редактирование: 27 май 2019
  5. Danil_2002

    Danil_2002 Гик

  6. Airbus

    Airbus Радиохулиган Модератор

    Последнее редактирование: 27 май 2019
  7. Danil_2002

    Danil_2002 Гик

    Могу, дайте пару минут
     
  8. AlexU

    AlexU Гуру

    Что этим хотели сказать?
     
  9. b707

    b707 Гуру

    не знаю, повлияет или нет - но я бы в процедуре adc_convert в while добавил скобки в условие (не уверен. что оно правильно вычисляется), а в чтении результата явно привел бы ADCH к типу uint_16
     
  10. ADCSRA |= (1<<ADSC);
    while(ADCSRA & (1<<ADSC));
    return ADC;
     
    ИгорьК нравится это.
  11. Danil_2002

    Danil_2002 Гик

    я раньше так же пробовал, тоже самое
     
  12. parovoZZ

    parovoZZ Гуру

    Не надо ничего выдумывать. Пиши так
    Код (C++):
    unsigned int result_ADC = ADC;
    Результат лучше в прерывании снимать, а не тупо ждать.
     
  13. Danil_2002

    Danil_2002 Гик

    Да, если убрать эту строчку, то все работает
     
  14. parovoZZ

    parovoZZ Гуру

    Вот мои функции работы с АЦП (для 24 тиньки) в режиме 8 бит
    Код (C++):
    inline void ADC_On(void)
    {
        ADCSRA =    (1<<ADEN) |                // Разрешаем работу ADC
            (1<<ADIE) |                // Разрешаем прерывание
            (1<<ADATE) |                // Старт преобразования вручную
            (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);        // Прескалер = 8
    }

    inline void ADC_Start_Conversion (void)
    {
         ADCSRA =    (1<<ADEN) |                // Разрешаем работу ADC
            (1<<ADIE) |                // Разрешаем прерывание
            (1<<ADATE) |                // Старт преобразования вручную
            (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) |        // Прескалер = 8
            (1<<ADSC);                // Старт конвертации
    }

    inline void ADC_Off(void)
    {
        ADCSRA =    (1<<ADEN) |                // Разрешаем работу ADC
            (0<<ADIE) |                // Запрещаем прерывание
            (1<<ADATE) |                // Старт преобразования вручную
            (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) |        // Прескалер = 8
            (0<<ADSC);
    }

    inline void ADC_Init (void)
    {
        DIDR0 =    (1<<ADC1D) | (1<<ADC2D) | (1<<ADC3D);
       
    //    ADMUX =    AREF;          
        ADCSRB =    (1<<BIN) | (1<<ADLAR) | (0<<ADTS1) | (0<<ADTS0);    // Двухполярный режим работы
    }

    inline uint8_t ADC_Get_Data (void)
    {
         return ADCH;
    }
     
  15. Danil_2002

    Danil_2002 Гик

    Всем большое спасибо за ответы
     
  16. parovoZZ

    parovoZZ Гуру

    И вдогонку
    Код (C++):
    #define AREF_internal        (1<<REFS1) | (0<<REFS0)            // AREF 1.1v
    #define AREF_external        (0<<REFS1) | (1<<REFS0)            // AREF external (PA0)
               
    #define ADC_Change_in(Analog_input)    ADMUX = AREF_external | (Analog_input) //
     
  17. AlexU

    AlexU Гуру

    Вот эта проверка:
    не правильная.
    Проще сделать так:
    Код (C++):
    while(ADCSRA & (1 << ADSC)); // Ждем результатов
     
  18. AlexU

    AlexU Гуру

    И данные читать лучше так:
    Код (C++):
    unsigned int result_ADC = ADC; // вместо (ADCL|ADCH << 8);
    компилятор сам разберётся в какой последовательности читать регистры ADCH и ADCL и как их "упаковывать" в одно число.
     
  19. Danil_2002

    Danil_2002 Гик

    А если с помощью прерывания сделать то что я просил, это как лучше сделать?
     
  20. parovoZZ

    parovoZZ Гуру

    Код (C++):
    volatile uint16_t result_ADC; //в секции глобальных переменных

    ISR(ADC_vect)
    {
    result_ADC = ADC;
    }
    Но лучше через состояние IDLE организовать.