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

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

Сообщение codenamehawk »

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

Сообщение BOB51 »

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

Сообщение shonty »

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

Сообщение Starichok51 »

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

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

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

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

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

Сообщение Demiurg »

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

Сообщение 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
Это не хвост, это антенна
Сообщения: 1431
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

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

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

Сообщение electroget »

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

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

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

Понял, спасибо.
Это не хвост, это антенна
Сообщения: 1492
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

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

Сообщение electroget »

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

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

Сообщение BOB51 »

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

Сообщение shonty »

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

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

Сообщение Demiurg »

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

Сообщение shonty »

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

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

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

Сообщение Demiurg »

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

Сообщение 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
Это не хвост, это антенна
Сообщения: 1431
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

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

Сообщение BOB51 »

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

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