Страница 2 из 9

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 14:11:52
codenamehawk
electroget писал(а):Точность вообще не критична. Это делается для установки времени задержки срабатывания электронного предохранителя.
В моем представлении нет ничего более важного, чем предохранитель.
А так проще всего организовать задержку при помощи таймера.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 14:23:23
BOB51
[uquote="shonty",url="/forum/viewtopic.php?p=4670352#p4670352"]..., можно это в коде выразить?[/uquote]
Это для ассемблера , а не для Си - в Си прямое управление стеком штука весьма для спецов...
У меня в Си недостаточный уровень.
:(
А под асмом весьма много в старых проектах примеров было...
Кстати...
Измерение времени я б таки по pulseln() c внешней обвязкой (перемычками) и прерыванием соорудил...
:roll:
У топикстартера похоже не АВРка, а LGT - там лучше без вычитывания даташитов в "отсебятину" не влазить...

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 14:33:24
shonty
BOB51 писал(а):Это для ассемблера , а не для Си
а мне и нужно под ассемблер.
BOB51 писал(а):А под асмом весьма много в старых проектах примеров было...
ну если не сложно напиши.. но не срочно.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 14:49:01
Starichok51
во, к примеру, как у меня сделана подстановка адреса возврата в прерывании для таймера1:

Код: Выделить всё

;--- Таймер1 ---
ldi R16, low(RAMEND)
out SPL, R16 
ldi R16, low(main)
push R16
ldi R16, high(main)
push R16
reti
перезаписываю вершину стека и пишу в стек адрес возврата.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 15:32:17
electroget
Попытался сделать задержку после обработки прерывания:

if (intFlag) {
intFlag = false; // сбрасываем флаг
startDelay = !intFlag; // присваиваем значение переменной
Serial.println("Interrupt!");
Serial.println(startDelay);
}

static unsigned long previousMillis = 0; // Переменная для хранения предыдущего времени
const long interval = delayFront; // Интервал в миллисекундах
unsigned long currentMillis = millis(); // Получаем текущее время

// Если прошло необходимое количество времени и флаг прерывания сброшен, то включаем цифровой выход 3

if ((currentMillis - previousMillis == interval) and (startDelay = true)) {
digitalWrite(3, HIGH);
}

Но так она тоже не работает!

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 16:43:52
Demiurg
Когда стоит задача внешнее прерывании, а потом выставить пин и задержка в десятки, сотни мс, то алгоритм такой:
В обработчике внешнего прерывания отключить это прерывание. Чтобы наверняка, ещё флаг внешнего прерывания пристукнуть, выставляем порт. Если основной цикл пробегается достаточно быстро (я не знаю ваш проект, насколько загружен основной цикл), то выставляем флаг, что эй, я импульс поймал, в основном цикле мы это флаг увидели, выставляем требуемую задержку.
Если же основной цикл загружен, то после выставления пина, выставляем нужную задержку. В прерывании таймера, когда время вышло, сбрасываем пин. Даём по шапке флагу внешнего прерывания, включаем внешнее прерывания. Все начинается заново. Ждем внешнее прерывание.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 17:02:05
codenamehawk
electroget писал(а):if ((currentMillis - previousMillis == interval) and (startDelay = true)) {
digitalWrite(3, HIGH);
}
Разделите на куски

Код: Выделить всё

if (startDelay == true)
{
  if (millis() - previousMillis >= interval)
 {
     digitalWrite(3, HIGH);
 }
}
Главное >= , а не ==
Не всегда словишь миллисекунду.

Добавлено after 17 minutes 25 seconds:
startDelay должна быть volatile.
А в прерывании, надо запомнить время старта.
prevMillis = millis();

И учтите, что если следующий вызов прерывания, наступит раньше, чем закончится ожидание, перед выключением, то задержка начнётся заново, как бы отодвинется по времени.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 17:07:09
OKF
[uquote="codenamehawk",url="/forum/viewtopic.php?p=4670393#p4670393"]Главное >= , а не ==
Не всегда словишь миллисекунду.[/uquote]
Особенно, если millis() имеет свойство пропускать миллисекунды.)

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 17:35:26
Demiurg
Псевдокод

Interrupt handler:
Вход в прерывание:
set_bit (TIFR, EXT_FLG); // Для верности прибиваем флаг внешнего прерывания.
clr_bit (TIMSK, EXT_FLG); // Отключаем внешнее прерывание.

Два варианта. Если основной цикл быстро крутится.
set_bit (PORTx, PIN); // Выставляем пин.
set_bit (FLAGS, FLG_EI_YA_IMPULS_POIMAL);
В основном цикле проверяем этот флаг, ставим нужную задержку. Крутимся дальше, походу проверяем вышло ли время. Если вышло:
clt_bit (PORTx, PIN); // Сбрасываем пин.
set_bit (TIFR, EXT_FLG); // Для верности прибиваем флаг внешнего прерывания.
set_bit (TIMSK, EXT_FLG); // Включаем внешнее прерывание.
Все начинается заново. Ждём импульс.

Если основной цикл тяжёлый.
Там же в обработчике прерывания:
set_bit (PORTx, PIN); // Выставляем пин.
Настраиваем, включаем таймер. Ждём в прерывании таймера, когда закончится задержка.
clt_bit (PORTx, PIN); // Сбрасываем пин.
set_bit (TIFR, EXT_FLG); // Для верности прибиваем флаг внешнего прерывания.
set_bit (TIMSK, EXT_FLG); // Включаем внешнее прерывание.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 17:39:08
electroget
Разделите на куски

Код: Выделить всё

if (startDelay == true)
{
  if (millis() - previousMillis >= interval)
 {
     digitalWrite(3, HIGH);
 }
}
Главное >= , а не ==
Не всегда словишь миллисекунду.

Понял, спасибо.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 17:42:26
Demiurg
Советую посмотреть в сторону программных таймеров. А также поиграться с аппаратными таймерами. Поделать разные тестовые задачи. Чтобы вы научились работать с аппаратными таймерами. Всякие генераторы, мигалки.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 18:08:46
electroget
[uquote="Demiurg",url="/forum/viewtopic.php?p=4670415#p4670415"]Советую посмотреть в сторону программных таймеров. А также поиграться с аппаратными таймерами.[/uquote]

С аппаратными таймерами я знаком. Например, я делал таймеры на CD4541 и на CD4060 делал.
А программные таймеры это вы какие имели в виду?

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 18:32:55
BOB51
Имелись ввиду аппаратные таймеры начинки МК.
Но там надо весьма аккуратно действовать, дабы не навредить - Т1 иТ2 отвечают за исполнение некоторых функций референса.
8)

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 18:34:49
shonty
electroget писал(а):С аппаратными таймерами я знаком. Например, я делал таймеры на CD4541 и на CD4060 делал.
Нее..
Аппаратные таймеры, это которые в МК настраиваются при помощи регистров и работают автономно, не зависимо от программы.
А программные, это тупо цикл прокручивается энное количество раз. За счёт программы.

Ну как смог объяснил :dont_know:

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 18:35:15
Demiurg
Под аппаратными таймерами я имел в виду таймеры МК AVR. TIMER0, 1,2 и так далее. Не микросхемы. А таймеры внутри МК.
Программные таймеры. Интернет. Поисковики.
Пояснение. Аппаратных таймеров у МК AVR раз два и обчелся. А если нам нужно 10-20 таймеров? Как быть? Времянки единицы мс, десятки, сотни, секунды и так далее. Тут как раз и используются программные таймеры.
Как пример. Советую прочитать цикл статей Татарчевского.
Тут начало.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 18:43:40
shonty
Demiurg писал(а): А если нам нужно 10-20 таймеров? Как быть?
или изменять сравнение, или изменять переменную которая декрементируется при переполнении.

Добавлено after 2 minutes 40 seconds:
декрементом переменной 255 таймеров запросто))

Добавлено after 2 minutes 42 seconds:
Но только он уже будет скорее программно-аппаратный.. переменную же проверять нужно на "0"
сорри :dont_know:

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 18:57:19
Demiurg
shonty, Повторяю. Интернет. Поисковики. Программные таймеры.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 19:00:24
BOB51
В отношении ардуино с АВРками обычно ставится вторая точка на системном таймере и от нее уже все остальные псевдопараллельные счетчики:
настройка инициализации (в результате прерывание раз в 1мС)

Код: Выделить всё

cli(); //noInterrupts();
 OCR0A = 127; TIMSK0 |= (1<<OCIE0A); tim_F = 0;
sei(); //interrupts();
и само прерывание (к примеру):

Код: Выделить всё

ISR(TIMER0_COMPA_vect)
{
 static int cntt = 0;
 cntt++;
 if(cntt == 1000){ tim_F = 1; cntt = 0; } // тайм-слот в 1 секунду
 //..........
}
данный вариант работает с нанками и про-мини.

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Сб янв 11, 2025 20:56:27
OKF
[uquote="BOB51",url="/forum/viewtopic.php?p=4670448#p4670448"]данный вариант работает с нанками и про-мини.[/uquote]А ничего что analogWrite может использовать таймер0 и OCR0A в частности?
Зачем лезть к железу (особенно если не понимаешь!), когда Ардуино тебе уже предоставляет средства для работы со временами? От микросекунд до long(!) миллисекунд!

Re: Вопрос по программированию задержки внутри прерывания

Добавлено: Вс янв 12, 2025 00:12:24
BOB51
Выводы D5,D6 - T0 ~980Hz
Выводы D9,D10 - T1 ~490Hz
Выводы D3,D11 - T2 ~490Hz
Есть из чего выбирать (где можно игнорировать использование).
Зачем и что используется - это уже вопрос конкретной задачи и предпочтений.
8)