Например TDA7294

Форум РадиоКот :: Просмотр темы - Вопрос по программированию задержки внутри прерывания
Форум РадиоКот
https://radiokot.ru/forum/

Вопрос по программированию задержки внутри прерывания
https://radiokot.ru/forum/viewtopic.php?f=57&t=196331
Страница 1 из 9

Автор:  electroget [ Сб янв 11, 2025 09:15:30 ]
Заголовок сообщения:  Вопрос по программированию задержки внутри прерывания

Доброго времени суток уважаемые коты.

Сам я в программировании специалистом совсем не являюсь, поэтому хочу спросить мнение у специалистов. Накропал для Ардуины вот такой код:

Спойлер
Код:
#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) получается что не подходит.

Автор:  veso74 [ Сб янв 11, 2025 10:51:08 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

delay() не работает в interrupt, а micros() и millis() не меняет свое значение в interrupt, но все три функции работает вне interrupt.
Насколько критично время импульса? Также обработайте ситуацию: в течение времени после прерывания произошло новое прерывание (в зависимости от алгоритма вашего устройства: 1. оно должно или 2. не должно продлить время или проигнорировать новое прерывание). В первом варианте снова пропустите временной период, а во втором случае можете просто остановить прерывания cli(); и продолжить позже sei();.

Автор:  electroget [ Сб янв 11, 2025 11:01:08 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

delay() не работает в interrupt, а micros() и millis() не меняет свое значение в interrupt, но все три функции работает вне interrupt.


То есть, если я уже после обработки прерывания вставлю код с функцией millis() и после этого дам команду digitalWrite(3, HIGH); то межу прерыванием и включением выхода 3 получится необходимый мне интервал времени задержки?

Автор:  veso74 [ Сб янв 11, 2025 11:04:54 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

Да.
При наличии флага в прерывании реакця будет задержана на несколько такт, пока не войдет в loop. Вот почему спросил о критичности времени. Есть вариации на включения в прерывание и выключения в цикле по истечении времени. Выбирайте согласно своему алгоритму.
---
Реакция мог бы быть с задержки - вижу, что пшете сообщения в Serial в цикле без каких-либо условий.

Автор:  electroget [ Сб янв 11, 2025 11:10:30 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

veso74,
Точность вообще не критична. Это делается для установки времени задержки срабатывания электронного предохранителя. Интервалы будут задаваться внешним переключателем: 1,2,5,10,50,100,200 миллисекунд.
Скажите, а выполнение прерывания нужно обязательно специальной командой останавливать? В каком месте кода её нужно вставлять?

Автор:  veso74 [ Сб янв 11, 2025 11:13:45 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

Для предохранителя: измените проверки if .. if ... if на if ... else if ... else if ... или на switch-case. И lcd.print и Serial.println() - ето медленные функции. Напишите их хотя бы с условием, что не пишет каждой раз в loop.

Одно сообщение не даст объяснения :). Необходимо чтение и понимание и множество тестов и проверок, пока не установите на место в первый раз.

Автор:  electroget [ Сб янв 11, 2025 11:18:54 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

lcd.print и Serial.println() - ето медленные функции. Напишите их хотя бы с условием, что не пишет каждой раз в loop.


Это я всё конечно уберу когда программа заработает как надо. Вы мне пожалуйста ещё скажите про прекращение работы прерывания. Выполнение прерывания нужно обязательно специальной командой останавливать? В каком месте кода её нужно вставлять?

Автор:  veso74 [ Сб янв 11, 2025 11:26:56 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

Это решите сами. Зависит от выбранного алгоритма.
noInterrupts(); или cli(); -> запрещаем прерывания
interrupts(); или sei(); -> разрешаем прерывания

Автор:  electroget [ Сб янв 11, 2025 11:33:49 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

veso74,
Понял, спасибо. Буду пробовать сделать.

Автор:  codenamehawk [ Сб янв 11, 2025 12:38:08 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

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/

Автор:  veso74 [ Сб янв 11, 2025 12:53:00 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

И с каких это пор она не работает в прерывании?
...

wiring.c, строка 83.
Изображение
delay() в interrupt прекратит interrupt. Необходимы и другие корректировки.
Проще использовать собственную задержку вне interrupt.

Автор:  smacorp [ Сб янв 11, 2025 12:55:26 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

Не надо делеить в обработчиках прерываний. Независимо от способа. Это учит плохому. Это будет говнокод.

Автор:  veso74 [ Сб янв 11, 2025 12:58:46 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

Совершенно верно. Некоторые компиляторы/IDE даже не допускают этого. Они уже "умные" :).
Изображение
Не должно быть и медленные операции, такие как печать на ЖК-дисплее, на другой тип, в Serial порте, а также медленные вычисления, напр. с float, циклами и т. д.

Автор:  OKF [ Сб янв 11, 2025 13:05:34 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

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."

Ну почему же). Внутри delay() есть yield() - функция позднего связывания. Определив её у себя, можно выполнять операции во время работы delay().

Добавлено after 4 minutes 3 seconds:
delay() в interrupt прекратит interrupt.

Да ладно! Вы невнимательны.)

Автор:  BOB51 [ Сб янв 11, 2025 13:06:58 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

Ардуино под Си не ассемблер.
Используем то, что принято в референсе.
Прерывание предпочтительно только под короткие операции с флагами и/или короткие фрагменты программного кода.
Для слишком критичного ко времени исполнения участка подпрограммы-обработчика под ассемблером есть прием "условного возврата" (подстановка адреса возврата через стек).
Возможно нечто похожее можно и под Си (без вставок на ассемблере) получить...
:roll:

А вот этим yield() для простых прожек баловаться как то...
https://alexgyver.ru/lessons/time/
Тем более, что без подключения соответствующей библиотеки ( #include <Scheduler.h> ) yield() работать не будет...
Второе...
"...расположенный внутри неё (yield()) код будет выполняться во время работы любой задержки delay() в программе..."
но это не одно и то же, что
"расположенная внутри функции текущего обработчика прерывания функция delay() будет исполняться"...
8)

Автор:  codenamehawk [ Сб янв 11, 2025 13:24:47 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

veso74 писал(а):
delay() в interrupt прекратит interrupt.

Не прекратит, а CLi не разрешит другие прерывания.
Для точности временной задержки delay заменить на свою задержку.

smacorp писал(а):
Не надо делеить в обработчиках прерываний. Независимо от способа. Это учит плохому. Это будет говнокод.

Если работает, то это никому не мешает.

Добавлено after 3 minutes 51 second:
OKF писал(а):
Внутри delay() есть yield() - функция позднего связывания. Определив её у себя, можно выполнять операции во время работы delay().

Это предупреждение тем (и не мое), которые этого не знают.

Автор:  veso74 [ Сб янв 11, 2025 13:26:08 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

Считайте условно нерабочим как происходит действие, которое не было запланировано. (не воспринимайте слово "прекратит" буквально, часто пользуюсь переводчиком).

Автор:  codenamehawk [ Сб янв 11, 2025 13:29:46 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

При входе в прерывание, другие прерывания запрещены и делай их не разрешит, только выход из прерывания или вручную.

Автор:  BOB51 [ Сб янв 11, 2025 13:40:51 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

Тем самым в определенной степени будет нарушена работа устройства.
:tea:
Псевдопараллельный процесс можно организовать как на дополнительном прерывании по COMP_A (у атмег 328 не задействован референсом) так и на сцепке стандартного референса - используя tone и любое из внешних прерываний для подсчета поступающих на вход прерывания импульсов. Правда там два вывода теряем плюс внешняя перемычка.
:tea:

Автор:  shonty [ Сб янв 11, 2025 14:07:44 ]
Заголовок сообщения:  Re: Вопрос по программированию задержки внутри прерывания

BOB51 писал(а):
Для слишком критичного ко времени исполнения участка подпрограммы-обработчика под ассемблером есть прием "условного возврата" (подстановка адреса возврата через стек).
BOB51, можно это в коде выразить?

Страница 1 из 9 Часовой пояс: UTC + 3 часа
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/