Arduino — различия между версиями
Avp (обсуждение | вклад) (→Подключение оборудования: Поправил ссылку) |
Avp (обсуждение | вклад) (→Прерывания: Дополнил) |
||
| Строка 1: | Строка 1: | ||
= Прерывания = | = Прерывания = | ||
| − | Допустим, мы сделали "бегущий огонь" и теперь хотим прикрутить кнопку для управления режимом светодиодов | + | Допустим, мы сделали "бегущий огонь" и теперь хотим прикрутить кнопку для управления режимом светодиодов: |
| − | Плюс, добавляя кнопку в наш проект, мы добавляем в наш проект неопределённость -- нажатие на кнопку может возникнуть в любой момент, и | + | <pre> |
| + | const int LED_MIN = 22; | ||
| + | const int LED_MAX = 30; | ||
| + | const int DELAY = 100; | ||
| + | |||
| + | void setup() { | ||
| + | for (int pin = LED_MIN; pin <= LED_MAX; ++pin) | ||
| + | pinMode(pin, OUTPUT); | ||
| + | } | ||
| + | |||
| + | void blink(int pin) { | ||
| + | digitalWrite(pin, HIGH); | ||
| + | delay(DELAY); | ||
| + | digitalWrite(pin, LOW); | ||
| + | delay(DELAY); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | for (int pin = LED_MIN; pin <= LED_MAX; ++pin) | ||
| + | blink(pin); | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | Самым прямолинейным решением, на первый взгляд, является считывание значение кнопки в начале <code>loop</code>. К примеру: | ||
| + | |||
| + | <pre> | ||
| + | const int BUTTON = 31; | ||
| + | |||
| + | // ... пропущена часть кода из предыдущей программы ... | ||
| + | |||
| + | boolean isEnabled = false; | ||
| + | |||
| + | void loop() { | ||
| + | if (digitalRead(BUTTON)) { | ||
| + | isEnabled = ! isEnabled; | ||
| + | } | ||
| + | |||
| + | if (isEnabled) { | ||
| + | isEnabled = true; | ||
| + | for (int pin = LED_MIN; pin <= LED_MAX; pin++) | ||
| + | blink(pin); | ||
| + | } | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | Собираем схему, добавляем считывание значения с цифрового порта и логику переключения режимов. Всё бы хорошо, но наше кратковременное нажатие на кнопку обычно приводит к многократному считыванию значения: за время, пока нажата кнопка, <code>loop</code> успевает отработать несколько раз; как следствие, логика не работает, как должна. | ||
| + | |||
| + | Плюс, добавляя кнопку в наш проект, мы добавляем в наш проект неопределённость -- нажатие на кнопку может возникнуть в любой момент; в таких случаях говорят, что событие возникает асинхронно (по отношению к нашей программе.) Если нажатие на кнопку возникло в тот момент, когда Arduino "не смотрела" на значение на порту и занималась другим делами, то событие пройдёт незамеченным. Если же всё делать по-нормальному, то мы должны обрабатывать это событие в тот момент, как оно возникла. | ||
Для правильного решения данной задачи необходимо использовать прерывания. | Для правильного решения данной задачи необходимо использовать прерывания. | ||
== Реакция на внешние события == | == Реакция на внешние события == | ||
| − | Для обработки внешнего | + | Для обработки внешнего асинхронного события нам потребуются как минимум две вещи: |
* Написать обработчик события | * Написать обработчик события | ||
* Связать обработчик с внешним событием | * Связать обработчик с внешним событием | ||
Версия 18:56, 11 апреля 2016
Содержание
Прерывания
Допустим, мы сделали "бегущий огонь" и теперь хотим прикрутить кнопку для управления режимом светодиодов:
const int LED_MIN = 22;
const int LED_MAX = 30;
const int DELAY = 100;
void setup() {
for (int pin = LED_MIN; pin <= LED_MAX; ++pin)
pinMode(pin, OUTPUT);
}
void blink(int pin) {
digitalWrite(pin, HIGH);
delay(DELAY);
digitalWrite(pin, LOW);
delay(DELAY);
}
void loop() {
for (int pin = LED_MIN; pin <= LED_MAX; ++pin)
blink(pin);
}
Самым прямолинейным решением, на первый взгляд, является считывание значение кнопки в начале loop. К примеру:
const int BUTTON = 31;
// ... пропущена часть кода из предыдущей программы ...
boolean isEnabled = false;
void loop() {
if (digitalRead(BUTTON)) {
isEnabled = ! isEnabled;
}
if (isEnabled) {
isEnabled = true;
for (int pin = LED_MIN; pin <= LED_MAX; pin++)
blink(pin);
}
}
Собираем схему, добавляем считывание значения с цифрового порта и логику переключения режимов. Всё бы хорошо, но наше кратковременное нажатие на кнопку обычно приводит к многократному считыванию значения: за время, пока нажата кнопка, loop успевает отработать несколько раз; как следствие, логика не работает, как должна.
Плюс, добавляя кнопку в наш проект, мы добавляем в наш проект неопределённость -- нажатие на кнопку может возникнуть в любой момент; в таких случаях говорят, что событие возникает асинхронно (по отношению к нашей программе.) Если нажатие на кнопку возникло в тот момент, когда Arduino "не смотрела" на значение на порту и занималась другим делами, то событие пройдёт незамеченным. Если же всё делать по-нормальному, то мы должны обрабатывать это событие в тот момент, как оно возникла.
Для правильного решения данной задачи необходимо использовать прерывания.
Реакция на внешние события
Для обработки внешнего асинхронного события нам потребуются как минимум две вещи:
- Написать обработчик события
- Связать обработчик с внешним событием
TODO
Прерывания по таймеру
TODO
См. также
- We interrupt this program to bring you an Arduino interrupt tutorial (англ.)
- Microcontroller tutorial series: AVR and Arduino timer interrupts (англ.)