4.07.1. Лабораторная работа №4.7.1.md
Псевдопараллелизм на практике
Тема работы
В предыдущих работах мы использовали аппаратные прерывания, чтобы мгновенно реагировать на события. Это мощный инструмент, но количество пинов с прерываниями ограничено. Что делать, если нам нужно выполнять несколько задач «одновременно» без использования delay()
? Например, плавно мигать одним светодиодом, опрашивать датчик и одновременно ждать нажатия кнопки?
В этой лабораторной работе мы изучим важнейшую технику псевдопараллелизма, используя функцию millis()
. Мы напишем программу, в которой светодиод L2
будет мигать с постоянным интервалом, а кнопка B1
будет в любой момент управлять светодиодом L1
— и всё это без единой блокирующей паузы!
Цель
- Понять, почему функция
delay()
мешает созданию многозадачных программ. - Освоить использование функции
millis()
для создания неблокирующих задержек. - Научиться организовывать код для одновременного выполнения нескольких независимых задач.
Оборудование и материалы
- Отладочная плата
Рудирон
. - USB-кабель для подключения
Рудирона
к компьютеру. - Компьютер с настроенной средой
Arduino IDE
.
Ход работы
-
Проблема
delay()
- «Спящий» микроконтроллерФункция
delay()
очень проста в использовании, но у неё есть огромный недостаток: она полностью «замораживает» микроконтроллер. Пока выполняетсяdelay(1000)
, процессор не делает абсолютно ничего, кроме как ждёт. Он не может считывать кнопки, проверять датчики или отправлять данные. Для сложных проектов это неприемлемо. -
Функция
millis()
millis()
— это встроенный счётчик, который запускается в момент включенияРудирона
и непрерывно считает количество прошедших миллисекунд. Он никогда не останавливается и не блокирует программу.Представьте, что
delay()
— это команда «Спать 10 минут», а работа сmillis()
— это как периодически поглядывать на часы и спрашивать себя: «10 минут уже прошли? Нет? Тогда я пока займусь другими делами».Алгоритм работы с
millis()
всегда одинаков: 1. Запоминаем время последнего события (например, последнего мигания). 2. В циклеloop()
постоянно проверяем, сколько времени прошло с того момента. 3. Если прошло достаточно времени (например, 1000 мс), выполняем нужное действие и сбрасываем таймер, то есть снова запоминаем текущее время. -
Настройка и подключение
Для этого эксперимента нам понадобятся только встроенные компоненты: кнопка
B1
и светодиодыL1
иL2
.- Установите перемычку
PRG | RUN
в положениеPRG
. - Подключите плату к компьютеру и настройте
Arduino IDE
(платаRudiron_Buterbrod_R10_20MHz
и правильный COM-порт).
- Установите перемычку
-
Написание и загрузка кода
Напишем программу, которая будет выполнять две задачи «одновременно»:
- Задача 1. Мигать светодиодом
L2
каждые 500 мс. - Задача 2. По отпусканию кнопки
B1
переключать состояние светодиодаL1
. -
В
Arduino IDE
введите следующий код:// --- Переменные для задачи 1. Мигание L2 --- bool led2State = LOW; unsigned long previousMillis = 0; // Время последнего мигания L2 const long interval = 500; // Интервал мигания L2 (500 мс) // --- Переменные для задачи 2. Кнопка B1 и светодиод L1 --- bool led1State = LOW; bool lastButtonState = LOW; void setup() { pinMode(LED_BUILTIN_1, OUTPUT); pinMode(LED_BUILTIN_2, OUTPUT); pinMode(BUTTON_BUILTIN_1, INPUT_PULLDOWN); } void loop() { // --- Обработка задачи 1. Мигание L2 без delay() --- unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { // Сохраняем время этого мигания previousMillis = currentMillis; // Меняем состояние светодиода L2 led2State = !led2State; digitalWrite(LED_BUILTIN_2, led2State); } // --- Обработка задачи 2. Проверка кнопки B1 --- bool currentButtonState = digitalRead(BUTTON_BUILTIN_1); if (currentButtonState != lastButtonState) { // Если состояние изменилось и сейчас кнопка отпущена (LOW), // то переключаем светодиод L1 if (currentButtonState == LOW) { led1State = !led1State; digitalWrite(LED_BUILTIN_1, led1State); } } lastButtonState = currentButtonState; // Запоминаем состояние кнопки }
- Нажмите кнопку «Upload», чтобы загрузить код на плату.
- Задача 1. Мигать светодиодом
-
Проверка работы
- Сразу после загрузки светодиод
L2
начнёт равномерно мигать. - В любой момент нажмите на кнопку
B1
. Ничего не произойдёт. - Теперь отпустите кнопку. Светодиод
L1
должен мгновенно отреагировать и изменить своё состояние. МиганиеL2
при этом не прервётся ни на мгновение.
- Сразу после загрузки светодиод
Результаты
Вы создали программу, которая эффективно выполняет две задачи одновременно, не блокируя друг друга. Это и есть псевдопараллелизм - микроконтроллер всё ещё выполняет команды последовательно, но делает это так быстро, что для нас это выглядит как параллельная работа.
Анализ результатов
- Задача мигания.
if (currentMillis - previousMillis >= interval)
— эта конструкция проверяет, прошло ли 500 мс, не останавливая выполнениеloop()
. Это позволяет коду для кнопки выполняться тысячи раз в секунду. - Задача кнопки. Алгоритм с
currentButtonState
иlastButtonState
работает точно так же, как и в лабораторной работе 4.1.3. Он отлавливает именно момент отпускания. - Отзывчивость. Поскольку
loop()
не блокируется функциейdelay()
, он готов среагировать на изменение состояния кнопки практически мгновенно.
Выводы
В этой лабораторной работе вы освоили самый важный приём для написания сложных программ для микроконтроллеров — неблокирующую многозадачность с помощью millis()
. Этот подход является стандартом в программировании встроенных систем и позволяет создавать сложные, отзывчивые и надёжные устройства.
Вопросы для самопроверки
- Почему
delay()
мешает созданию многозадачных программ? - Что возвращает функция
millis()
? - Зачем в алгоритме мигания нужна переменная
previousMillis
? - Что произойдёт, если забыть обновить
previousMillis
внутри блокаif
? - Как изменить код, чтобы светодиод
L2
мигал в два раза быстрее, а светодиодL1
по-прежнему реагировал на отпускание кнопки?
Поздравляем с освоением псевдопараллелизма! Теперь вы готовы к созданию по-настоящему сложных проектов. В следующем параграфе мы перейдём к изучению интерфейсов связи и научим Рудирон
общаться с компьютером и другими устройствами.
- Страницы
- 1. Введение
- 1.01. Лабораторная работа №1.1
- 1.02. Лабораторная работа №1.2
- 1.03. Лабораторная работа №1.3
- 1.04. Лабораторная работа №1.4
- 1.05. Лабораторная работа №1.5
- 2. Основы электроники
- 2.01. Электрический ток и параметры цепи
- 2.01.1. Лабораторная работа №2.1.1
- 2.01.2. Лабораторная работа №2.1.2
- 2.02. Сопротивление в цепи
- 2.02.1. Лабораторная работа №2.2.1
- 2.02.2. Лабораторная работа №2.2.2
- 2.03. Полупроводники
- 2.03.1. Лабораторная работа №2.3.1
- 2.03.2. Лабораторная работа №2.3.2
- 3. Основы программирование на C++
- 3.01. Типы данных и переменные
- 3.01.1. Практикум
- 3.02. Операторы в C++
- 3.02.1. Практикум
- 3.03. Структуры ветвления
- 3.03.1. Практикум
- 3.04. Структуры повторения
- 3.04.1. Практикум
- 3.05. Массивы
- 3.05.1. Практикум
- 3.06. Функции
- 3.06.1. Практикум
- 3.07. Решения задач
- 4. Программирование микроконтроллеров
- 4.01. Цифровые сигналы и GPIO
- 4.01.1. Лабораторная работа №4.1.1
- 4.01.2. Лабораторная работа №4.1.2
- 4.01.3. Лабораторная работа №4.1.3
- 4.01.4. Лабораторная работа №4.1.4
- 4.01.5. Лабораторная работа №4.1.5
- 4.01.6. Лабораторная работа №4.1.6
- 4.01.7. Лабораторная работа №4.1.7
- 4.01.8. Лабораторная работа №4.1.8
- 4.02. Аналоговые сигналы и ШИМ
- 4.02.1. Лабораторная работа №4.2.1
- 4.02.2. Лабораторная работа №4.2.2
- 4.02.3. Лабораторная работа №4.2.3
- 4.02.4. Лабораторная работа №4.2.4
- 4.02.5. Лабораторная работа №4.2.5
- 4.03. Аналоговый сигнал и АЦП
- 4.03.1. Лабораторная работа №4.3.1
- 4.03.2. Лабораторная работа №4.3.2
- 4.03.3. Лабораторная работа №4.3.3
- 4.03.4. Лабораторная работа №4.3.4
- 4.03.5. Лабораторная работа №4.3.5
- 4.04. Аналоговый сигнал и ЦАП
- 4.04.1. Лабораторная работа №4.4.1
- 4.04.2. Лабораторная работа №4.4.2
- 4.05. Генерация и измерение импульсов
- 4.05.1. Лабораторная работа №4.5.1
- 4.05.2. Лабораторная работа №4.5.2
- 4.06. Аппаратные прерывания
- 4.06.1. Лабораторная работа №4.6.1
- 4.06.2. Лабораторная работа №4.6.2
- 4.07. Псевдопараллелизм
- 4.07.1. Лабораторная работа №4.7.1
- 4.07.2. Лабораторная работа №4.7.2
- 4.08. Интерфейсы связи - UART
- 4.08.1. Лабораторная работа №4.8.1
- 4.09. Интерфейсы связи - I2C
- 4.09.1. Лабораторная работа №4.9.1
- 4.10. Интерфейсы связи - SPI
- 4.10.1. Лабораторная работа №4.10.1
- home
-
imgs
- 1. Введение
- 1.01. Лабораторная работа №1.1
- 1.02. Лабораторная работа №1.2
- 1.03. Лабораторная работа №1.3
- 1.04. Лабораторная работа №1.4
- 1.05. Лабораторная работа №1.5
- 2. Основы электроники
- 2.01. Электрический ток и параметры цепи
- 2.01.1. Лабораторная работа №2.1.1
- 2.01.2. Лабораторная работа №2.1.2
- 2.02. Сопротивление в цепи
- 2.02.1. Лабораторная работа №2.2.1
- 2.02.2. Лабораторная работа №2.2.2
- 2.03. Полупроводники
- 2.03.1. Лабораторная работа №2.3.1
- 2.03.2. Лабораторная работа №2.3.2
- 3. Основы программирование на C++
- 3.01. Типы данных и переменные
- 3.01.1. Практикум
- 3.02. Операторы в C++
- 3.02.1. Практикум
- 3.03. Структуры ветвления
- 3.03.1. Практикум
- 3.04. Структуры повторения
- 3.04.1. Практикум
- 3.05. Массивы
- 3.05.1. Практикум
- 3.06. Функции
- 3.06.1. Практикум
- 3.07. Решения задач
- 4. Программирование микроконтроллеров
- 4.01. Цифровые сигналы и GPIO
- 4.01.1. Лабораторная работа №4.1.1
- 4.01.2. Лабораторная работа №4.1.2
- 4.01.3. Лабораторная работа №4.1.3
- 4.01.4. Лабораторная работа №4.1.4
- 4.01.5. Лабораторная работа №4.1.5
- 4.01.6. Лабораторная работа №4.1.6
- 4.01.7. Лабораторная работа №4.1.7
- 4.01.8. Лабораторная работа №4.1.8
- 4.02. Аналоговые сигналы и ШИМ
- 4.02.1. Лабораторная работа №4.2.1
- 4.02.2. Лабораторная работа №4.2.2
- 4.02.3. Лабораторная работа №4.2.3
- 4.02.4. Лабораторная работа №4.2.4
- 4.02.5. Лабораторная работа №4.2.5
- 4.03. Аналоговый сигнал и АЦП
- 4.03.1. Лабораторная работа №4.3.1
- 4.03.2. Лабораторная работа №4.3.2
- 4.03.3. Лабораторная работа №4.3.3
- 4.03.4. Лабораторная работа №4.3.4
- 4.03.5. Лабораторная работа №4.3.5
- 4.04. Аналоговый сигнал и ЦАП
- 4.04.1. Лабораторная работа №4.4.1
- 4.04.2. Лабораторная работа №4.4.2
- 4.05. Генерация и измерение импульсов
- 4.05.1. Лабораторная работа №4.5.1
- 4.05.2. Лабораторная работа №4.5.2
- 4.06. Аппаратные прерывания
- 4.06.1. Лабораторная работа №4.6.1
- 4.06.2. Лабораторная работа №4.6.2
- 4.07. Псевдопараллелизм
- 4.07.1. Лабораторная работа №4.7.1
- 4.07.2. Лабораторная работа №4.7.2
- 4.08. Интерфейсы связи - UART
- 4.08.1. Лабораторная работа №4.8.1
- 4.09. Интерфейсы связи - I2C
- 4.09.1. Лабораторная работа №4.9.1
- 4.10. Интерфейсы связи - SPI
- 4.10.1. Лабораторная работа №4.10.1
- home