Перейти к содержанию
    

Измерение временных интервалов

i - переход на длительный обработчик (пусть будет Uart0) TCNT1 = 0x7FFE

i + 0x1 - срабатывание захвата TIF1 = 1, ICR = 0x7FFF, TOV1 = 0.

i + 0x7FF8 - Uart0 обработка завершена выполнение RETI (4 такта), TCNT1 = FFF6, TOV1 = 0

i + 0x7FFC - возврат в основную, выполнение хотя бы одной команды, TCNT1 = 0xFFFA

i + 0x7FFD - начало входа в обработчик (11 тактов) T1_ICAP, TCNT1 = 0xFFFB, TOV1 = 0

i + 0x8008 - первая команда обработчика T1_ICAP, TOV1 = 1 <------ !

ну и коррекция рез-тата +0x10000, т.к. попадаем под условие коррекции (ICR < 32k, TOV=1).

Ну зачем же такой "экстремальный" пример приводить? Который, кстати, алгоритм-то не дискредитирует :) Я же не обещал ровно до 32К тактов дополнительного прерывания. Ваш пример всего-лишь указывает, что максимальное время прерывания = 32К-хх тактов. Скажем 31К или 32000 такта 100% хватит для работоспособности проги. А в Вашей версии будет то же самое = 256-хх тактов.

Вобщем недостатка как такового в моей версии и нету. Блин :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще подправил код:

Что-то мне разонравилось измерение по прерыванию. Наверное, надо делать без всяких прерываний, в фоне(:-).

Вам больше не нравятся прерывания ?

- Вы просто не умеете их правильно готовить (с) (не мой) :)

А что там уметь? Прерывание, оно и в Африке-прерывание(:-).

По делу. Выразился не так, как хотел. Мне не нравится длинное прерывание, которое вдруг стало накладываться на наши два. Откуда бы ему взяться в задаче по измерению временного интервала? Поэтому предлагаю сделать откат назад и исключить третье прерывание.

 

Теперь поясню, почему пропал мой предыдущий текст, а то народ уже и этим тычет(:-). Вчера к концу рабочего дня набрал почти ведро маслят, представьте, в октябре! Ну я разволновался, как же дилишез(:-), вследствие такого события случайно удалил почти весь текст. А хотел ведь просто добавить то, что вы увидели.

 

Вот еще один вопросик, требующий внимания. Автор топика намеревался измерять длительность секундных импульсов, а не период. Т.е., есть передний фронт импульса, длительность импульса и задний фронт импульса. Время начала импульса наша программа измерит, а как быть со спадом? Может быть перенастраивать ICES1 при первом входе в прерывание TIM_CAPT или есть более короткий путь?

 

И моим оппонентам на будущее. Я говорю то, что говорю, не надо искать второго смысла, ОК? И замечайте смайлики иногда.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне кажется, зря вы здесь используете повторно r7, r6. Вдруг основная программа не успеет их обработать, а уже возникнет новое прерывание TIM1_CAPT. Понятно, что хочется съэкономить, но такая экономия может выйти боком(:-)

Нет, c R6,R7 там все в порядке.

вот этот код будет выполнен в конце прерывания TIM1_CAPT при любых условиях:

    mov   R6,R2
    mov   R7,R3

так что здесь, ИМХО все ОК.

Ну раз так, вот вам еще экономия. Не используйте регистры r5-r4 в прерывании, храните результат непосредственно в регистрах icr1h-icr1l. Будет сохранно, как в банке ... до следующего захвата.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну раз так, вот вам еще экономия. Не используйте регистры r5-r4 в прерывании, храните результат непосредственно в регистрах icr1h-icr1l. Будет сохранно, как в банке ... до следующего захвата.

А как Вы в основной программе планируете узнавать что произошел второй захват ? :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Автор топика намеревался измерять длительность секундных импульсов, а не период. Т.е., есть передний фронт импульса, длительность импульса и задний фронт импульса. Время начала импульса наша программа измерит, а как быть со спадом? Может быть перенастраивать ICES1 при первом входе в прерывание TIM_CAPT или есть более короткий путь?
Ну дык у АВР есть возможность вызывать прерывание по любому изменению состояния входа. Надо только при запуске правильно инициализироваться (учесть текущее состояние), а дальше - понеслась.

 

Ведро маслят... Это многое объясняет... Как-нить при случае тоже ляпну такое :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прошу прощения за оффтоп, но для самого автора темы проблема давно уже как не актуальна (1-й пост - 2-го июня)... :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прошу прощения за оффтоп, но для самого автора темы проблема давно уже как не актуальна (1-й пост - 2-го июня)... :biggrin:

ну точно OFF - в топку :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прошу прощения за оффтоп, но для самого автора темы проблема давно уже как не актуальна (1-й пост - 2-го июня)... :biggrin:

 

___________

Please, don't kill me :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Минус только в отсутствии аппаратного запоминания текущего приоритета и запрета низкоприоритетных прерываний и текущего.

Это не минус, это фича ;)

Для многих задач это плюс т.к. одноуровневый КП избавляет программиста от некоторых проблем синхронизации.

Конечно, гарантия непрерываемости текущего обработчика прерываний даёт возможность, например, использовать некоторые регистры или ячейки памяти в качестве общих временных для всех обработчиков прерываний без сохранения их предыдущего состояния, а также ограничивает размер стека - это удобно. С другой стороны, на ранних AVR-ках с аппаратным стеком (на 3 вложенных вызова подпрограмм и прерываний) иначе и быть не могло. А далее памяти прибавили, но основу ядра менять не стали...

 

При большом желании можно легко (!) сделать двухуровневой КП (трёх) если вручную запрещать текущее прерывание, а потом устанавливать флаг I. Плохо только что стека маловато.

Можно, но не нужно. Проще просто подобрать другой камень когда это действительно надо.

Зачем выбирать другой камень, если вопрос лишь в доработке софта ?

Менять камень нужно лишь в случае, если он не удовлетворяет требованиям к железу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так... Вы - против, я - за. Что будем с этим делать?

Ничего :) оставим как есть - 2 варианта.

Не бывает единственно верных решений.

Осмелюсь предложить следующее решение:

.def  ConstFF = R8
.def  _TOV1   = R9
.def  _Sreg   = R10
....
    clr   ConstFF
    dec   ConstFF
    ldi   R16, (1 << TOV1)
    mov   _TOV1, R16
....

; Input Capture:
TIM1_CAPT:
    in    _Sreg,SREG 
    in    R4, ICR1L
    in    R5, ICR1H
    cp    R5, _TOV1
    brsh  _do_not_correct_result
    in    R6, TIFR
    and   R6, _TOV1
    breq  _do_not_correct_result
    out   TIFR, R6
    sub   R2, ConstFF
    sbc   R3, ConstFF
_do_not_correct_result:
    mov   R6, R2
    mov   R7, R3
    out   SREG,_Sreg
; <-- 32bit Result R7-R6-R5-R4 (MSB R7)
    reti

Здесь уже кому как повезет, куда _TOV1 попадет в TIFR, такой и будет запас

для длинных прерываний.

Да и код, ИМХО становится намного понятнее :biggrin:

 

А если серьезно, то запас для других прерываний нужно оставлять в зависимости

от конкретной задачи.

Например, вместо TIM1_OVF мы можем использовать TIM1_CAPTA со значением

OCR1A<32K и тогда запас должен быть другим, тогда будет рулить такой код:

    in    R4, ICR1L
    in    R5, ICR1H
    in    R7, OCR1AH
    lsr   R7
    cp    R5, R7
    brsh  _do_not_correct_result

Ну конечно на определенном диапазоне значений OCR1A

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну раз так, вот вам еще экономия. Не используйте регистры r5-r4 в прерывании, храните результат непосредственно в регистрах icr1h-icr1l. Будет сохранно, как в банке ... до следующего захвата.

А как Вы в основной программе планируете узнавать что произошел второй захват ? :)

А вы у GetSmart спросите, он всё знает(:-). Спокойно, GetSmart, шютю я(:-)

 

Чуть посерьёзнее. Я вам про экономию регистров в прерывании говорю, "которых всегда не хватает", а вы плавно меняете тему. Какая разница, где хранить время текущего захвата, в регистрах r7-r6-r5-r4 или в r7-r6-icr1h-icr1l? Никакой разницы нет. Почти. Зато экономится два регистра!

 

Ну а по делу, думаю есть несколько подходов.

 

1) Есть две переменные, скажем, oldTime и newTime (ваши r7-r6-r5-r4). Прерывание захвата должно переписывать содержимое newTime в oldTime, и только затем обновлять newTime. Основная программа в любое удобное для себя время(:-) определяет длительность интервала, просто вычитая содержимое oldTime из newTime.

 

2) Прерывание захвата чередует признак начала измерения и конца измерения, (можно просто счетчик на регистре, признак-младший бит), а основная программа доделывает остальное.

 

Автор топика намеревался измерять длительность секундных импульсов, а не период. Т.е., есть передний фронт импульса, длительность импульса и задний фронт импульса. Время начала импульса наша программа измерит, а как быть со спадом? Может быть перенастраивать ICES1 при первом входе в прерывание TIM_CAPT или есть более короткий путь?
Ну дык у АВР есть возможность вызывать прерывание по любому изменению состояния входа. Надо только при запуске правильно инициализироваться (учесть текущее состояние), а дальше - понеслась.

Неправильно. В том то и дело, что не один раз при запуске программы надо инициализироваться, а каждый раз при входе в захват(:-(. Потому что на четных захватах вы ловите переход 0-1 (начало импульса), а на нечетных захватах вы ловите 1-0 (конец импульса). Я и спрашивал, перенастраивать ICES1 каждый раз или есть другой способ, попроще?

 

Ведро маслят... Это многое объясняет... Как-нить при случае тоже ляпну такое :)

GetSmart, хорош бурчать, это у вас так что проявляется(:-)? Не злитесь, ляпните что-нибудь или тяпните, разрядка придёт, поверьте(:-). Добавлю специально для вас. Напротив моих окон стоит бангало, под ним живет более 20 диких кроликов, смешные такие...А недавно видел как ворона ссорилась с белкой, наскакивали друг на друга, прям как вы на меня(:-).

 

GetSmart, жена маслята уже посолила, вот. Белые тут тоже водятся, но ехать далеко, в Нью Форист, неохота...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

GetSmart, хорош бурчать, это у вас так что проявляется(:-)?
Это веселуха. Заметьте, над другими тоже. А вообще, люблю "поржать" над чужими глупостями. Это после длииинного отпуска у меня такой бзик. Должен пройти.

Я и спрашивал, перенастраивать ICES1 каждый раз или есть другой способ, попроще?
Нету.
А вы у GetSmart спросите, он всё знает(:-)
Нее, я мало знаю. На всём форуме я очень мало где появляюсь. То есть знаю совсем немного тем, но обычно очень глубоко.

 

Больше всего меня прикололо это: когда вам показали как безболезненно доработать прогу возможностью обработки дополнительных прерываний вы выдали фразу, что вам прерывания не нравятся и надо делать вообще без них. Надо было видеть моё лицо :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А недавно видел как ворона ссорилась с белкой, наскакивали друг на друга, прям как вы на меня(:-).

Дык, эта, если смотреть со стороны, здесь все замечания вам по делу были сказаны, а вы все в шутку да в обидку воспринимаете..

Что ни пост - то перл:

 

особливо это:

Какая разница, где хранить время текущего захвата, в регистрах r7-r6-r5-r4 или в r7-r6-icr1h-icr1l?

Ну уж никак не в аппаратно зависимых регистрах, которые нам абсолютно неподконтрольны.

Вы что, правда не понимаете, что можно не успеть вычитать icr1h-icr1l до того как случится следующий захват? либо например наткнуться на ситуацию когда в момент вычитки L, произойдет следующий захват.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что ни пост - то перл: особливо это:

Какая разница, где хранить время текущего захвата, в регистрах r7-r6-r5-r4 или в r7-r6-icr1h-icr1l?

Ну уж никак не в аппаратно зависимых регистрах, которые нам абсолютно неподконтрольны.

Вы что, правда не понимаете, что можно не успеть вычитать icr1h-icr1l до того как случится следующий захват? либо например наткнуться на ситуацию когда в момент вычитки L, произойдет следующий захват.

Я и не такие перлы могу выдавать(:-). Но вообще-то, в нашем случае никакой разницы на самом деле нет, посудите сами, как только произошел захват, возникло прерывание, в котором регистры icr1h-icr1l читаются и переписываются в r5-r4, т.е. и icr1h-icr1l, и r5-r4 изменяются практически одновременно (макс разница 32 мс, если есть длинное прерывание). Естественно предполагается, что вы должны успеть обработать r7-r6-r5-r4 до следующего захвата, который может случиться через секунду (по условию задачи). Ну и спрашивается, зачем тратить два регистра МК, если можно с таким же успехом хранить данные в регистрах захвата?

 

Если же вы не успели, то произойдет новый захват, r5-r4 тоже испортятся, так что тут ничто не поможет, какая разница, что испорчено? Как меру борьбы, в прерывании можно сразу сохранять время захвата в озу, но опять же сохранять можно прямо из регистров захвата, r5-r4 тут не нужны.

 

Вы-то сами понимаете, что при наличии длинного прерывания наступит крах вашей системы прерываний, если, скажем, возникнет два прерывания захвата в течение 65 мс?

 

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

 

Возможно, кому-то достаточно измерять импульсы от 32 мс до секунд и с длинными прерываниями, согласен, тогда забудьте о сказанном выше. Я бы сказал так, что постановка первоначальной задачи была нечеткой, отсюда все недоразумения.

 

Что ещё? На справедливую критику не обижаюсь, с несправедливой борюсь по мере сил(:-), и посмеяться и пошутить люблю, но по-доброму.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я и не такие перлы могу выдавать(:-). Но вообще-то, в нашем случае никакой разницы на самом деле нет, посудите сами, как только произошел захват, возникло прерывание, в котором регистры icr1h-icr1l читаются и переписываются в r5-r4, т.е. и icr1h-icr1l, и r5-r4 изменяются практически одновременно (макс разница 32 мс, если есть длинное прерывание). Естественно предполагается, что вы должны успеть обработать r7-r6-r5-r4 до следующего захвата, который может случиться через секунду (по условию задачи). Ну и спрашивается, зачем тратить два регистра МК, если можно с таким же успехом хранить данные в регистрах захвата?

 

Если же вы не успели, то произойдет новый захват, r5-r4 тоже испортятся, так что тут ничто не поможет, какая разница, что испорчено?

Затем, что прерывание может произойти именно в момент вычитки значения, и мы можем прочитать недостоверные данные.

 

Если же рез-тат будет храниться в r7-r6-r5-r4, то мы можем запретить флаг I при обращении к этой 32х битной переменной, и тем самым обезопасить себя от последствий описанного случая.

 

Учить матчасть :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

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

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...