Показаны различия между двумя версиями страницы.
Предыдущая версия справа и слеваПредыдущая версияСледующая версия | Предыдущая версия | ||
products:laboratory_iot_c:exp36 [2024/11/17 13:21] – [Эксперимент 36. Прерывания] labuser30 | products:laboratory_iot_c:exp36 [2024/11/17 17:04] (текущий) – [Программный код эксперимента] labuser30 | ||
---|---|---|---|
Строка 4: | Строка 4: | ||
Их простота заключалась в линейности логики алгоритма. В главном цикле проверялось состояние кнопки и сразу же изменялось | Их простота заключалась в линейности логики алгоритма. В главном цикле проверялось состояние кнопки и сразу же изменялось | ||
состояние светодиода. Задержка, | состояние светодиода. Задержка, | ||
- | с помощью функции | + | с помощью функции |
небольшими схемами и примитивной логикой. Но если хочется | небольшими схемами и примитивной логикой. Но если хочется | ||
чего-то большего, | чего-то большего, | ||
- | использования | + | использования |
Ранее, чтобы проверить состояние вывода микроконтроллера мы использовали команду вроде '' | Ранее, чтобы проверить состояние вывода микроконтроллера мы использовали команду вроде '' | ||
Строка 19: | Строка 19: | ||
==== Эксперимент ==== | ==== Эксперимент ==== | ||
- | Попробуем применить прерывания для работы с энкодером. Нам потребуется сделать две вещи — настроить прерывание и написать функцию- обработчик прерывания. | + | Попробуем применить прерывания для работы с энкодером. Нам потребуется сделать две вещи — настроить прерывание и написать функцию-обработчик прерывания. |
==== Схема эксперимента ==== | ==== Схема эксперимента ==== | ||
Строка 31: | Строка 31: | ||
==== Программный код эксперимента ==== | ==== Программный код эксперимента ==== | ||
- | < | + | < |
- | from machine import I2C, Pin | + | #include < |
- | from esp8266_i2c_lcd import I2cLcd | + | |
- | import time | + | |
- | _init() | + | |
- | DEFAULT_I2C_ADDR | + | #define ENC_A 13 |
+ | #define ENC_B 12 | ||
+ | # | ||
- | encA = Pin(13, Pin.IN) | + | LCDI2C_Generic lcd(DEFAULT_I2C_ADDR, 16, 2); |
- | encB = Pin(12, Pin.IN) | + | |
- | count = 0 | + | bool states[4][2] |
+ | {0,0}, | ||
+ | {1,0}, | ||
+ | {1,1}, | ||
+ | {0,1} | ||
+ | }; | ||
- | states | + | volatile int count = 0; |
- | (1,1), | + | volatile int state = 0; |
- | (0,1), | + | volatile int state_old = 0; |
- | (0,0), | + | |
- | (1,0) | + | |
- | ) | + | |
- | old_state = 0 | + | void printLcd(int number) { |
+ | lcd.clear(); | ||
+ | lcd.print(number); | ||
+ | } | ||
- | def print_lcd(data): | + | int index(bool a, bool b){ |
- | | + | |
- | | + | |
+ | return i; | ||
+ | } | ||
+ | } | ||
+ | return -1; | ||
+ | } | ||
- | def callback(p): | + | void ICACHE_RAM_ATTR |
- | | + | bool value_a = digitalRead(ENC_A); |
- | | + | bool value_b = digitalRead(ENC_B); |
- | global encA | + | |
- | global states | + | |
- | global old_state | + | |
- | value_a | + | state = index(value_a, |
- | | + | |
- | current_state = states.index((value_a, value_b)) | + | if ((state - state_old |
- | + | count++; | |
- | if (current_state | + | if (not(count % 2)){ |
- | count += 1 | + | |
- | if not (count % 2): | + | |
- | print('+'); | + | } |
- | | + | |
- | | + | } |
- | | + | else if ((state |
- | count -= 1 | + | count--; |
- | if not (count % 2): | + | if (not(count % 2)){ |
- | print('-'); | + | |
- | | + | |
- | | + | } |
+ | state_old | ||
+ | } | ||
+ | } | ||
+ | void setup() { | ||
+ | lcd.init(); | ||
+ | lcd.setBacklight(0); | ||
+ | pinMode(ENC_A, | ||
+ | pinMode(ENC_B, | ||
- | i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000) | + | attachInterrupt(digitalPinToInterrupt(ENC_A), callback, CHANGE); |
- | lcd = I2cLcd(i2c, DEFAULT_I2C_ADDR, | + | |
- | lcd.backlight_on() | + | } |
- | + | ||
- | encA.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=callback) | + | void loop() { |
- | encB.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=callback) | + | } |
- | + | ||
- | + | ||
- | while True: | + | |
- | pass | + | |
</ | </ | ||
Сначала настраиваем прерывания: | Сначала настраиваем прерывания: | ||
- | <code python[enable_line_numbers=" | + | <code python[enable_line_numbers=" |
- | encA.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=callback) | + | |
- | encB.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=callback) | + | |
</ | </ | ||
- | Мы настроили, | + | Мы настроили |
Какие могут быть события: | Какие могут быть события: | ||
- | * Pin.IRQ_FALLING | + | * FALLING |
- | * Pin.IRQ_RISING | + | * RISING |
- | * Pin.IRQ_LOW_LEVEL | + | * CHANGE любое изменение |
- | * Pin.IRQ_HIGH_LEVEL | + | * LOW наличие логического 0 |
+ | * HIGH_LEVEL | ||
- | События можно комбинировать. Например, если нужна реакция | + | Обратите внимание на новое |
+ | <code arduino[enable_line_numbers=" | ||
+ | volatile int count = 0; | ||
+ | volatile int state = 0; | ||
+ | volatile int state_old = 0; | ||
+ | </ | ||
- | Рассмотрим функцию- обработчик прерывания: | + | Рассмотрим функцию-обработчик прерывания, она в свою очередь объявлена с атрибутом ICACHE_RAM_ATT. Причина аналогична указанной для переменных выше. |
- | < | + | < |
- | def callback(p): | + | void ICACHE_RAM_ATTR |
- | | + | bool value_a = digitalRead(ENC_A); |
- | | + | bool value_b = digitalRead(ENC_B); |
- | global encA | + | |
- | global states | + | |
- | global old_state | + | |
- | value_a | + | state = index(value_a, |
- | | + | |
- | current_state = states.index((value_a, value_b)) | + | if ((state - state_old |
- | + | count++; | |
- | if (current_state | + | if (not(count % 2)){ |
- | count += 1 | + | |
- | if not (count % 2): | + | |
- | print('+'); | + | } |
- | | + | |
- | | + | } |
- | | + | else if ((state |
- | count -= 1 | + | count--; |
- | if not (count % 2): | + | if (not(count % 2)){ |
- | print('-'); | + | |
- | | + | |
- | | + | } |
+ | state_old | ||
+ | } | ||
+ | } | ||
</ | </ | ||
Она начинается с | Она начинается с | ||
- | < | + | < |
- | | + | bool value_a = digitalRead(ENC_A); |
- | | + | bool value_b = digitalRead(ENC_B); |
- | global encA | + | |
- | global states | + | |
- | global old_state | + | |
</ | </ | ||
- | Ключеваое слово '' | + | Здесь мы впервые объявляем переменные внутри функции. По умолчанию, |
Потом, как и раньше, | Потом, как и раньше, | ||
Строка 154: | Строка 164: | ||
Как мы заметили ранее, при одном щелчке энкодера происходит смена двух состояний энкодера. Чтобы одному щелчку соответствовало изменение счетчика на 1, мы просто проверяем счетчик на четность. | Как мы заметили ранее, при одном щелчке энкодера происходит смена двух состояний энкодера. Чтобы одному щелчку соответствовало изменение счетчика на 1, мы просто проверяем счетчик на четность. | ||
- | < | + | < |
- | | + | if (not(count % 2)){ |
- | print('+'); | + | |
- | | + | |
+ | } | ||
</ | </ | ||
Строка 164: | Строка 175: | ||
Теперь самое главное. Обратим внимание на основной цикл программы. Мы в нем ничего не делаем. Все действия, | Теперь самое главное. Обратим внимание на основной цикл программы. Мы в нем ничего не делаем. Все действия, | ||
- | <WRAP center round important 60%> | + | <WRAP center round info 80%> |
- | В этом эксперименте мы производили настройку аппаратных средств микроконтроллера, а именно настраивали прерывания. Как мы уже узнали, работа прерываний не зависит | + | [[https:// |
+ | |||
+ | [[https:// | ||
</ | </ | ||
+ | |||
+ | |||