Кнопка, прерывания и Таймер/Счетчик1
- Войдите на сайт для отправки комментариев
Вс, 19/05/2019 - 21:29
Здравствуйте!
Плата 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 ()
{
}
... по спадающему изменению фронта сигнала...
по спадающему фронту сигнала
В "программировании" тема про внутренние прерывания ещё не утонула, там обсуждалась проблема (со стр. 4 более внятно), у которой схожие симптомы были.
Спасибо, сейчас посмотрю.
Н-да, а ссыллку, пожалуйста.
http://arduino.ru/forum/programmirovanie/vnutrennie-preryvaniya?page=3#c...
Спасибо, помогло!
Neogar, вы ещё учтите, что ARDUINO IDE по-умолчанию запускает таймер1 из внутренней функции init(), которая запускается до сетапа. Соответссно разумнее будет его остановить в первой-же строчке сетапа, во избежание проблем , и следующей строкой на всякий случай отчистить флаги таймера (TIFR1=0xff).
Neogar, вы ещё учтите, что ARDUINO IDE по-умолчанию запускает таймер1 из внутренней функции init(), которая запускается до сетапа. Соответссно разумнее будет его остановить в первой-же строчке сетапа, во избежание проблем , и следующей строкой на всякий случай отчистить флаги таймера (TIFR1=0xff).
Спасибо, dimax! Регистр TIFR1 я уже очистил, остановку таймера учту.
В этой статье нашел хорошее описание настройки таймера.
Neogar, вы ещё учтите, что ARDUINO IDE по-умолчанию запускает таймер1
Разве? Таймер 0. Или ты имеешь в виду "конфигурирует для ШИМа"?
Как я понял функция "init()" в файле "wiring.c" запускает ТС0 и конфигурирует ТС1 и ТС2 для ШИМа, но не запускает их. Под остановкой ТС1 перед настройкой можно подразумевать его реинициализацию и запуск.
Получается, что если в скетче использовать стандартные функции
void setup() { } void loop() { }, то таймеры настраиваются. Но если использовать
int main(void) { while (1) { // код } return 0; }, то таймеры будут НЕ настроены и НЕ запущены (по дефолту после сброса микроконтроллера).
Если в main() не включите init(), то останетесь без millis(), delay() и прочих фишек Ардуино.)