Страница 1 из 9
Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 09:15:30
electroget
Доброго времени суток уважаемые коты.
Сам я в программировании специалистом совсем не являюсь, поэтому хочу спросить мнение у специалистов. Накропал для Ардуины вот такой код:
Спойлер
Код: Выделить всё
#include <lgt328p.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); // Подключаем дисплей
volatile bool intFlag = false;
unsigned long delayFront; // Переменная для времени задержки включения выхода
void setup() {
interrupts();
lcd.init();
lcd.backlight();// Включаем подсветку дисплея
lcd.clear(); // очистить дисплей
lcd.setCursor(0,0);
lcd.print("Setting A");
lcd.setCursor(0,1);
lcd.print("Delay mS");
lcd.setCursor(0,2);
lcd.print("Voltage V");
lcd.setCursor(0,3);
lcd.print("Carrent A");
delayFront == 0;
Serial.begin(9600);
pinMode(2,INPUT);
pinMode(3,OUTPUT);
pinMode(7,INPUT);
pinMode(8,INPUT);
pinMode(9,INPUT);
pinMode(10,INPUT);
digitalWrite(3,LOW);
attachInterrupt(0, event, RISING);
}
void event() {intFlag = true;}
void loop() {
if(digitalRead(7)==HIGH)delayFront=1; if(digitalRead(8)==HIGH)delayFront=2; if(digitalRead(9)==HIGH)delayFront=5; if(digitalRead(10)==HIGH)delayFront=10;
Serial.println(delayFront);
lcd.setCursor (12, 1);
lcd.print(delayFront);
lcd.print(" ");
if (intFlag) {
intFlag = false; // сбрасываем флаг
ЗДЕСЬ ДОЛЖНА БЫТЬ ФУНКЦИЯ ЗАДЕРЖКИ НА [b]delayFront[/b] МИЛЛИСЕКУНД
digitalWrite(3,HIGH); // включение выхода
Serial.println("Interrupt!");
}
}
Этот код должен делать вот что. После прихода фронта импульса на цифровой вход
2, возникшее прерывание с
задержкой на
delayFront миллисекунд должно включить цифровой выход
3. В статьях по программированию Ардуины пишут, что при выполнении прерываний функции времени работают с некими ограничениями. Какую функцию программирования мне следует использовать для того чтоб получать необходимую задержку включения выхода?
P.S. Задержка включения выхода нужна на десятки и даже сотни миллисекунд. Поэтому
delayMicroseconds(time) получается что не подходит.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 10:51:08
veso74
delay() не работает в interrupt, а micros() и millis() не меняет свое значение в interrupt, но все три функции работает вне interrupt.
Насколько критично время импульса? Также обработайте ситуацию: в течение времени после прерывания произошло новое прерывание (в зависимости от алгоритма вашего устройства: 1. оно должно или 2. не должно продлить время или проигнорировать новое прерывание). В первом варианте снова пропустите временной период, а во втором случае можете просто остановить прерывания cli(); и продолжить позже sei();.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 11:01:08
electroget
[uquote="veso74",url="/forum/viewtopic.php?p=4670269#p4670269"]delay() не работает в interrupt, а micros() и millis() не меняет свое значение в interrupt, но все три функции работает вне interrupt.[/uquote]
То есть, если я уже после обработки прерывания вставлю код с функцией millis() и после этого дам команду digitalWrite(3, HIGH); то межу прерыванием и включением выхода 3 получится необходимый мне интервал времени задержки?
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 11:04:54
veso74
Да.
При наличии флага в прерывании реакця будет задержана на несколько такт, пока не войдет в loop. Вот почему спросил о критичности времени. Есть вариации на включения в прерывание и выключения в цикле по истечении времени. Выбирайте согласно своему алгоритму.
---
Реакция мог бы быть с задержки - вижу, что пшете сообщения в Serial в цикле без каких-либо условий.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 11:10:30
electroget
veso74,
Точность вообще не критична. Это делается для установки времени задержки срабатывания электронного предохранителя. Интервалы будут задаваться внешним переключателем: 1,2,5,10,50,100,200 миллисекунд.
Скажите, а выполнение прерывания нужно обязательно специальной командой останавливать? В каком месте кода её нужно вставлять?
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 11:13:45
veso74
Для предохранителя: измените проверки if .. if ... if на if ... else if ... else if ... или на switch-case. И lcd.print и Serial.println() - ето медленные функции. Напишите их хотя бы с условием, что не пишет каждой раз в loop.
Одно сообщение не даст объяснения

. Необходимо чтение и понимание и множество тестов и проверок, пока не установите на место в первый раз.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 11:18:54
electroget
[uquote="veso74",url="/forum/viewtopic.php?p=4670279#p4670279"]lcd.print и Serial.println() - ето медленные функции. Напишите их хотя бы с условием, что не пишет каждой раз в loop.[/uquote]
Это я всё конечно уберу когда программа заработает как надо. Вы мне пожалуйста ещё скажите про прекращение работы прерывания. Выполнение прерывания нужно обязательно специальной командой останавливать? В каком месте кода её нужно вставлять?
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 11:26:56
veso74
Это решите сами. Зависит от выбранного алгоритма.
noInterrupts(); или cli(); -> запрещаем прерывания
interrupts(); или sei(); -> разрешаем прерывания
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 11:33:49
electroget
veso74,
Понял, спасибо. Буду пробовать сделать.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 12:38:08
codenamehawk
veso74 писал(а):delay() не работает в interrupt,
И с каких это пор она не работает в прерывании?
Работает и в прерывании.
Для коротких отрезков времени можете ее использовать,
"the delay() function and many sketches use short delays for such tasks as switch debouncing, the use of delay()
in a sketch has significant drawbacks. No other reading of sensors, mathematical calculations, or pin manipulation can go on during the delay function, so in effect, it brings most other activity to a halt."
https://docs.arduino.cc/language-refere ... ime/delay/
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 12:53:00
veso74
[uquote="codenamehawk",url="/forum/viewtopic.php?p=4670318#p4670318"]И с каких это пор она не работает в прерывании?
...[/uquote]
wiring.c, строка 83.

delay() в interrupt прекратит interrupt. Необходимы и другие корректировки.
Проще использовать собственную задержку вне interrupt.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 12:55:26
smacorp
Не надо делеить в обработчиках прерываний. Независимо от способа. Это учит плохому. Это будет говнокод.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 12:58:46
veso74
Совершенно верно. Некоторые компиляторы/IDE даже не допускают этого. Они уже "умные"

.

Не должно быть и медленные операции, такие как печать на ЖК-дисплее, на другой тип, в Serial порте, а также медленные вычисления, напр. с float, циклами и т. д.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 13:05:34
OKF
[uquote="codenamehawk",url="/forum/viewtopic.php?p=4670318#p4670318"]in a sketch has significant drawbacks. No other reading of sensors, mathematical calculations, or pin manipulation can go on during the delay function, so in effect, it brings most other activity to a halt."[/uquote]
Ну почему же). Внутри delay() есть yield() - функция позднего связывания. Определив её у себя, можно выполнять операции во время работы delay().
Добавлено after 4 minutes 3 seconds:
[uquote="veso74",url="/forum/viewtopic.php?p=4670325#p4670325"]delay() в interrupt прекратит interrupt.[/uquote]
Да ладно! Вы невнимательны.)
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 13:06:58
BOB51
Ардуино под Си не ассемблер.
Используем то, что принято в референсе.
Прерывание предпочтительно только под короткие операции с флагами и/или короткие фрагменты программного кода.
Для слишком критичного ко времени исполнения участка подпрограммы-обработчика под ассемблером есть прием "условного возврата" (подстановка адреса возврата через стек).
Возможно нечто похожее можно и под Си (без вставок на ассемблере) получить...
А вот этим yield() для простых прожек баловаться как то...
https://alexgyver.ru/lessons/time/
Тем более, что без подключения соответствующей библиотеки ( #include <Scheduler.h> ) yield() работать не будет...
Второе...
"...расположенный внутри неё (yield()) код будет выполняться во время работы любой задержки delay() в программе..."
но это не одно и то же, что
"расположенная внутри функции текущего обработчика прерывания функция delay() будет исполняться"...

Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 13:24:47
codenamehawk
veso74 писал(а):delay() в interrupt прекратит interrupt.
Не прекратит, а CLi не разрешит другие прерывания.
Для точности временной задержки delay заменить на свою задержку.
smacorp писал(а):Не надо делеить в обработчиках прерываний. Независимо от способа. Это учит плохому. Это будет говнокод.
Если работает, то это никому не мешает.
Добавлено after 3 minutes 51 second:
OKF писал(а):Внутри delay() есть yield() - функция позднего связывания. Определив её у себя, можно выполнять операции во время работы delay().
Это предупреждение тем (и не мое), которые этого не знают.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 13:26:08
veso74
Считайте условно нерабочим как происходит действие, которое не было запланировано. (не воспринимайте слово "прекратит" буквально, часто пользуюсь переводчиком).
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 13:29:46
codenamehawk
При входе в прерывание, другие прерывания запрещены и делай их не разрешит, только выход из прерывания или вручную.
Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 13:40:51
BOB51
Тем самым в определенной степени будет нарушена работа устройства.
Псевдопараллельный процесс можно организовать как на дополнительном прерывании по COMP_A (у атмег 328 не задействован референсом) так и на сцепке стандартного референса - используя tone и любое из внешних прерываний для подсчета поступающих на вход прерывания импульсов. Правда там два вывода теряем плюс внешняя перемычка.

Re: Вопрос по программированию задержки внутри прерывания
Добавлено: Сб янв 11, 2025 14:07:44
shonty
BOB51 писал(а):Для слишком критичного ко времени исполнения участка подпрограммы-обработчика под ассемблером есть прием "условного возврата" (подстановка адреса возврата через стек).
BOB51, можно это в коде выразить?