Arduino Mega TIMER1 интервал в одну секунду

Правильно ли установлен этот таймер для Arduino Mega? Он должен отсчитывать ровно одну секунду. И почему, когда я печатаю в последовательном мониторе (seconds_passed++), он увеличивается на 2, а не на 1?

Полный код на Pastebin: ССЫЛКА

noInterrupts();
//set and initialize the TIMER1

TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // set entire TCCR1B register to 0
TCCR1B |= (1 << CS12);
TIMSK1 |= (1 << TOIE1);
TCNT1 = 3036;

attachInterrupt(digitalPinToInterrupt(ignition_pin), ignitionSignal, CHANGE);
interrupts();

ISR(TIMER1_OVF_vect) {
  //TIMER1 overflow interrupt -- occurs every 1sec --
  instantSpeed();
  LPG_Consumption();
  LPG_injector_open_duration = 0;
  unleadedConsumption();
  unleadinj_Open_Duration = 0;
  seconds_passed++;
  vss_pulses = 0;
  TCNT1 = 3036;
}

, 👍1

Обсуждение

Я не эксперт в этом, но Mega работает на 16 МГц. ваш прескалер 256, поэтому TCMT1 должен быть 16000000/256 в течение 1 секунды?, @Juraj

Вы задали новый вопрос на ту же тему, вместо того, чтобы улучшить свой предыдущий вопрос. По крайней мере, удалите свой предыдущий вопрос сейчас, @chrisl


1 ответ


1

Ваша конфигурация таймера пока в порядке. Тем не менее я рекомендую использовать вектор прерывания TIMER1_COMPA_vect вместо TIMER1_OVF_vect, который имеет преимущество лучшей читаемости (в моем представлении), и TCNT1 не нужно сбрасывать в ISR (вместо этого OCR1A просто инициализируется с 62500 один раз в setup()). Поэтому TIMER0 должен работать в режиме CTC (очистить таймер при сравнении совпадений), а WGM12 должен быть установлен в TCR1B.

Причина, по которой seconds_passed увеличивается в два раза, заключается в том, что вы выполняете последовательную печать(seconds_passed++) в instantSpeed (). Печать на последовательном интерфейсе чертовски медленная, и использовать ее в ISR-это никуда не годится!

,

Спасибо, вы имеете в виду что-то вроде этого: TCR1A = 0; // отменить настройку таймера Arduino TCR1B = 0; // то же самое TCNT1 = 0; // таймер сброса OCR1A = 62500 - 1; // период = 62500 тактов TCR1B = _BV(WGM12) // Режим CTC, ВВЕРХУ = OCR1A | _BV(CS12); // часы в F_CPU/256 TIMSK1 = _BV(OCIE1A); // прерывание на выходе сравнение A, @Adam

Я не могу гарантировать, потому что у меня сейчас нет atmega2560, так что, возможно, придется кое-что исправить. Что должен делать TOP=OCR1A? Я не думаю, что в этом есть необходимость. Также я думаю, что " OCR1A=62500 "теоретически правильно ("галочки" в 0 нет), но, вероятно, вы не заметите никакой разницы..., @Sim Son

Это всего лишь комментарий., @Adam

Все в порядке! Я предлагаю вам попробовать это автономно, мигнув светодиодом, просто чтобы посмотреть. Если это не сработает, не стесняйтесь спрашивать!, @Sim Son

@Adam: Избегайте написания кода в комментариях: он не очень читаем. Вместо этого опубликуйте ссылку. @SimSon: 1. Адам скопировал вставку из [этого ответа](https://arduinoprosto.ru/q/54547). 2. Таймер отсчитывает от 0 до OCR1A _включительно. Если вам нужен период 62500, то для OCR1A следует установить значение 62500-1=62499., @Edgar Bonet

@EdgarBonet так что практически сброс TCNT-это один тик?, @Sim Son