Как опрашивать аналоговый вход атмега328

Тема в разделе "Микроконтроллеры AVR", создана пользователем Yerabdi, 19 сен 2017.

  1. Yerabdi

    Yerabdi Нерд

    Здравствтуйте всем как параллельно опрашивать аналоговый вход атмеги328, я использовал PC1 и PC2
    входы. Пробовал опрашивать через счетчик скажем через 100 милисекунд переключает на второй канал входа на 100мкс и обратно на первый канал.все работает но время реакции замедлилось
     
  2. DetSimen

    DetSimen Гик

    Шта?

    Где схема, скетч, внятный вопрос?
     
    Последнее редактирование модератором: 5 окт 2017
    BAR__MEN нравится это.
  3. Airbus

    Airbus Оракул

    Паралельно никак только поочередно.И на Асме и на Си только так.Разница несколько микросекунд принципиальна?
     
  4. ostrov

    ostrov Гуру

    Вдруг пригодится. По слухам самый быстрый код для АЦП:
    Код (C++):
    static inline uint16_t analogReadFast(byte analog_pin) {
      ADMUX = _BV(REFS0) | analog_pin;
      ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADPS2) | _BV(ADPS0); //500 kHz
      while (ADCSRA & _BV(ADSC));
      uint16_t ret;
      asm volatile(
        "lds %A0,  %1\n\t"
        "lds %B0,  %2"
        : "=w" (ret): "n"(&ADCL), "n"(&ADCH));
      return ret;
    }
     
    ИгорьК нравится это.
  5. Yerabdi

    Yerabdi Нерд

    частота микроконтроллера атмеги328Р 16МГц , деление частоты опроса АЦП 4, но уходит на прерывание через 24 тактов. По расчету все правильно но на практике не выходит
     
  6. Airbus

    Airbus Оракул

    А на практике что?
     
  7. Onkel

    Onkel Гуру

    На практике можно мерять 17 килосэмплов в с, но это на все входы . АЦП -то один, он просто работает со входами с0-с5 и ADC6,ADC7 через коммутатор. А щелкать входом во время измерения бесполезно - коммутатор подключает вход на несколько микросекунд к кондеру ацп, заряжает кондер и отключается.
     
  8. akl

    akl Гик

    вопрос: написано, что для избежания некоторых ошибок надо сперва считывать ADCL, будет ли такая строчка правильно считывать эти регистры в целом, и в частности будет ли первым считываться L?
    Код (C++):
    uint16_t adcw= ADCL | (ADCH<<8);
    вот собственно вся функция
    Код (C++):
    static inline uint16_t AdcRead(uint8_t analog_pin){  //ADC
        ADMUX = 0b01000000 | analog_pin; //VCC
        ADCSRA = 0b11000110; // СК/64 (125KHZ)
        while ((ADCSRA & (1 << ADIF)) == 0);
        uint16_t adcw;
        adcw= ADCL|(ADCH<<8);
        ADCSRA |= (1 << ADIF);
        return adcw;
    }
    (запускается вручную единичное измерение, ждет пока появится флаг ADIF)
    в симуляции вроде работает.

    еще тупой очень вопрос - что будет если во время работы АЦП придет какое-то левое прерывание?
     
    Последнее редактирование: 11 окт 2017
  9. AlexU

    AlexU Гуру

    Лучше сделать так:
    Код (C++):
    uint16_t adcw = ADC;
    компилятор сам разберётся какой из регистров читать первым ADCL или ADCH.
    Вопрос звучит не много странно... Вызовется обработчик прерывания, если обработка этого прерывания разрешена.
     
  10. akl

    akl Гик

    я в том смысле, что есть ли какой-то смысл запрещать прерывания где-то в процессе АЦП
     
  11. AlexU

    AlexU Гуру

    Однозначного ответа нет, в одном случае смысла нет, в другом есть...
     
  12. Onkel

    Onkel Гуру

    скорее всего нет. АЦП после запуска работает себе и работает, можно пару раз сходить обработать прерывание и вернуться к ожиданию окончания цикла АЦП. Только надо обработчики прерываний (всегда) делать по принципу "ударил - убежал", как можно более быстрыми, оставляя рутину программе через флаги, ключи, параметры.