Кнопка, прерывания и Таймер/Счетчик1

Neogar
Offline
Зарегистрирован: 05.12.2017
Здравствуйте!
Плата Arduino Nano. Кнопка подключена к GND и PORTD2(INT0).
Задача скетча простая: при нажатии на кнопку срабатывает прерывание (INT0_vect) по спадающему изменению фронта сигнала на входе(PORTD2) порта. В обработчике прерывания настраивается Таймер/Счетчик1 и запускается.
Но Таймер/Счетчик1 начинает отсчет сразу, без нажатия кнопки.
Объясните, пожалуйста, где я ошибся в скетче.
 
#define BUTTON_PIN          PORTD2
#define MILLISECONDS_8      0x08
#define MILLISECONDS_64     0x3E8
#define MILLISECONDS_704    0x2AF8
#define MILLISECONDS_1000   0x3D09


ISR (INT0_vect)
{
  TCCR1A = 0x00;
  TCNT1  = 0x00;
  OCR1A  = MILLISECONDS_1000;
  TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10); // Предделитель 1024
  TIMSK1 = (1 << OCIE1A);                            // Прерывание по совпадению с A ТС1
}


ISR (TIMER1_COMPA_vect)
{
  static uint8_t count;

  EIMSK &= ~(1 << INT0);        // Запрещаем внешние прерывания INT0(PORTD2)
  count++;
  if (count > 0) {
    Serial.println("Timer ON"); // Для отладки
  }
}


void  setup ()
{
  Serial.begin(9600);           // Для отладки
  cli();
  PORTD |=  (1 << BUTTON_PIN);  // INPUT_PULLUP
  EICRA  =  (1 << ISC01);       // По спадающему фронту на входе INT0(PORTD2)
  EIMSK |=  (1 << INT0);        // Разрешаем внешние прерывания INT0(PORTD2)
  sei();
}


void  loop ()
{

}

 

 

Neogar
Offline
Зарегистрирован: 05.12.2017

... по спадающему изменению фронта сигнала...

 по спадающему фронту сигнала

sadman41
Offline
Зарегистрирован: 19.10.2016

В "программировании" тема про внутренние прерывания ещё не утонула, там обсуждалась проблема (со стр. 4 более внятно), у которой схожие симптомы были.

Neogar
Offline
Зарегистрирован: 05.12.2017

Спасибо, сейчас посмотрю.

Neogar
Offline
Зарегистрирован: 05.12.2017

Н-да, а ссыллку, пожалуйста.

sadman41
Offline
Зарегистрирован: 19.10.2016
Neogar
Offline
Зарегистрирован: 05.12.2017

Спасибо, помогло!

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Neogar, вы ещё учтите, что ARDUINO IDE по-умолчанию запускает таймер1 из внутренней функции init(), которая запускается до сетапа. Соответссно разумнее будет его остановить в первой-же строчке сетапа, во избежание проблем , и следующей строкой на всякий случай  отчистить флаги таймера (TIFR1=0xff).

Neogar
Offline
Зарегистрирован: 05.12.2017

dimax пишет:

Neogar, вы ещё учтите, что ARDUINO IDE по-умолчанию запускает таймер1 из внутренней функции init(), которая запускается до сетапа. Соответссно разумнее будет его остановить в первой-же строчке сетапа, во избежание проблем , и следующей строкой на всякий случай  отчистить флаги таймера (TIFR1=0xff).

Спасибо, dimax! Регистр TIFR1 я уже очистил, остановку таймера учту.

Neogar
Offline
Зарегистрирован: 05.12.2017

В этой статье нашел хорошее описание настройки таймера.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

dimax пишет:

Neogar, вы ещё учтите, что ARDUINO IDE по-умолчанию запускает таймер1 

Разве? Таймер 0. Или ты имеешь в виду "конфигурирует для ШИМа"?

Neogar
Offline
Зарегистрирован: 05.12.2017

Как я понял функция "init()" в файле "wiring.c" запускает ТС0 и конфигурирует ТС1 и ТС2 для ШИМа, но не запускает их. Под остановкой ТС1 перед настройкой можно подразумевать его реинициализацию и запуск.

Neogar
Offline
Зарегистрирован: 05.12.2017

Получается, что если в скетче использовать стандартные функции

void setup() {

}

void loop() {

}

, то таймеры настраиваются. Но если использовать

int main(void)
{

  while (1)
  {
    // код
  }
  return 0;
}

, то таймеры будут НЕ настроены и НЕ запущены (по дефолту после сброса микроконтроллера).

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Neogar пишет:
то таймеры будут НЕ настроены и НЕ запущены (по дефолту после сброса микроконтроллера).
Ну, а кто ж их за Вас настроит? Системную настройку Вы втеснили, а сами не настроили.

Green
Offline
Зарегистрирован: 01.10.2015

Если в main() не включите init(), то останетесь без millis(), delay() и прочих фишек Ардуино.)