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

Обсуждаем контроллеры компании Atmel.
codenamehawk
Вымогатель припоя
Сообщения: 528
Зарегистрирован: Вт фев 09, 2010 17:52:26

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

Сообщение codenamehawk »

electroget писал(а):Точность вообще не критична. Это делается для установки времени задержки срабатывания электронного предохранителя.
В моем представлении нет ничего более важного, чем предохранитель.
А так проще всего организовать задержку при помощи таймера.
Реклама
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15571
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

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

Сообщение BOB51 »

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

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

Сообщение shonty »

BOB51 писал(а):Это для ассемблера , а не для Си
а мне и нужно под ассемблер.
BOB51 писал(а):А под асмом весьма много в старых проектах примеров было...
ну если не сложно напиши.. но не срочно.
Аватара пользователя
Starichok51
Модератор
Сообщения: 19053
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

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

Сообщение Starichok51 »

во, к примеру, как у меня сделана подстановка адреса возврата в прерывании для таймера1:

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

;--- Таймер1 ---
ldi R16, low(RAMEND)
out SPL, R16 
ldi R16, low(main)
push R16
ldi R16, high(main)
push R16
reti
перезаписываю вершину стека и пишу в стек адрес возврата.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
electroget
Друг Кота
Сообщения: 4651
Зарегистрирован: Ср сен 30, 2020 16:51:47
Откуда: РФ

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

Сообщение 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);
}

Но так она тоже не работает!
Реклама
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

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

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

Сообщение 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();

И учтите, что если следующий вызов прерывания, наступит раньше, чем закончится ожидание, перед выключением, то задержка начнётся заново, как бы отодвинется по времени.
Последний раз редактировалось codenamehawk Сб янв 11, 2025 17:19:28, всего редактировалось 2 раза.
OKF
Это не хвост, это антенна
Сообщения: 1393
Зарегистрирован: Вт июн 07, 2011 08:03:18

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

Сообщение OKF »

[uquote="codenamehawk",url="/forum/viewtopic.php?p=4670393#p4670393"]Главное >= , а не ==
Не всегда словишь миллисекунду.[/uquote]
Особенно, если millis() имеет свойство пропускать миллисекунды.)
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение 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); // Включаем внешнее прерывание.
Аватара пользователя
electroget
Друг Кота
Сообщения: 4651
Зарегистрирован: Ср сен 30, 2020 16:51:47
Откуда: РФ

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

Сообщение electroget »

Разделите на куски

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

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

Понял, спасибо.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

Советую посмотреть в сторону программных таймеров. А также поиграться с аппаратными таймерами. Поделать разные тестовые задачи. Чтобы вы научились работать с аппаратными таймерами. Всякие генераторы, мигалки.
Аватара пользователя
electroget
Друг Кота
Сообщения: 4651
Зарегистрирован: Ср сен 30, 2020 16:51:47
Откуда: РФ

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

Сообщение electroget »

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

С аппаратными таймерами я знаком. Например, я делал таймеры на CD4541 и на CD4060 делал.
А программные таймеры это вы какие имели в виду?
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15571
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

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

Сообщение BOB51 »

Имелись ввиду аппаратные таймеры начинки МК.
Но там надо весьма аккуратно действовать, дабы не навредить - Т1 иТ2 отвечают за исполнение некоторых функций референса.
8)
Аватара пользователя
shonty
Мучитель микросхем
Сообщения: 473
Зарегистрирован: Ср янв 11, 2012 18:20:26

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

Сообщение shonty »

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

Ну как смог объяснил :dont_know:
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

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

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

Сообщение shonty »

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

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

Добавлено after 2 minutes 42 seconds:
Но только он уже будет скорее программно-аппаратный.. переменную же проверять нужно на "0"
сорри :dont_know:
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

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

Сообщение Demiurg »

shonty, Повторяю. Интернет. Поисковики. Программные таймеры.
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15571
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

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

Сообщение 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 секунду
 //..........
}
данный вариант работает с нанками и про-мини.
OKF
Это не хвост, это антенна
Сообщения: 1393
Зарегистрирован: Вт июн 07, 2011 08:03:18

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

Сообщение OKF »

[uquote="BOB51",url="/forum/viewtopic.php?p=4670448#p4670448"]данный вариант работает с нанками и про-мини.[/uquote]А ничего что analogWrite может использовать таймер0 и OCR0A в частности?
Зачем лезть к железу (особенно если не понимаешь!), когда Ардуино тебе уже предоставляет средства для работы со временами? От микросекунд до long(!) миллисекунд!
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15571
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

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

Сообщение BOB51 »

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

Вернуться в «AVR»