Arduino Mega 2560 подсчет задержек между событиями на разных контактах

Мне интересно, как точно посчитать задержки времени между событиями нарастания, происходящими на 4 разных линиях/контактах, используя Input Capture Arduino Mega 2560. Как синхронизировать таймер/счетчики? Буду признателен за вашу помощь и предложения.

, 👍0


1 ответ


2

Это невозможно. По крайней мере, без модификации оборудования.

Микроконтроллер ATmega2560, лежащий в основе Arduino Mega, четыре входных блока захвата, подключенных к входным контактам захвата ICP[1345]. К сожалению, на плате Arduino разведены только два из этих контактов. В таблице ниже перечислены четыре контакта ICP с указанием их номеров на Пакет TQFP и на плате Arduino:

   pin     package  Arduino
───────────────────────────
ICP1/PD4     47        --
ICP3/PE7      9        --
ICP4/PL0     35        49
ICP5/PL1     36        48

Если вам не удастся припаять провода к отсутствующим контактам, вы не сможете использовать четыре входных блока захвата.

Что касается синхронизации, у вас есть два варианта:

  • Если вы используете предварительный делитель (т.е. коэффициент предварительного делителя больше, чем один), вы должны использовать его функцию «сброса предварительного делителя» с битом TSM (Режим синхронизации таймера/счетчика) включен. Это позволит вам запустите четыре таймера одновременно, когда вы очистите бит TSM. Смотрите Подробности в техническом описании микроконтроллера.

  • Если вы не используете предварительный делитель, вы можете просто запустить четыре таймеры в быстрой последовательности, с отключенными прерываниями. Они не будут начинаются почти одновременно, но вы можете компенсировать это, когда устанавливая их начальные значения.

В качестве примера второго варианта следующая функция запускает четыре таймера без предварительного делителя и синхронизированного подсчета:

void init_timers() {
    // Очищаем конфигурации таймера.
    TCCR1A = 0; TCCR1B = 0;
    TCCR3A = 0; TCCR3B = 0;
    TCCR4A = 0; TCCR4B = 0;
    TCCR5A = 0; TCCR5B = 0;

    // Устанавливаем начальные значения.
    TCNT1 = 0;
    TCNT3 = 2;
    TCNT4 = 4;
    TCNT5 = 6;

    // Запускаем таймеры.
    noInterrupts();
    TCCR1B = _BV(CS10);
    TCCR3B = _BV(CS30);
    TCCR4B = _BV(CS40);
    TCCR5B = _BV(CS50);
    interrupts();
}

Раздел, который запускает таймеры, компилируется в эту сборку:

cli              ; noInterrupts();
ldi r24, 0x01    ; r24 = _BV(CS10)
sts TCCR1B, r24  ; TCCR1B = r24
sts TCCR3B, r24  ; TCCR3B = r24
sts TCCR4B, r24  ; TCCR4B = r24
sts TCCR5B, r24  ; TCCR5B = r24
sei              ; interrupts();

Поскольку инструкция sts завершается за два такта, эта задержка будет компенсировать смещение начальных значений таймера.

Теперь, если вас не волнует точность на уровне микросекунд, вы можете забыть о таймерах и использовании внешних прерываний (или прерываний по изменению состояния контактов) и запишите время с помощью micros().

,