|
|
  |
Измерение временных интервалов, с высокой точностью |
|
|
|
Oct 10 2006, 14:14
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Ой-Ой-Ой.  Ладно, господа. Я вас примирю. Используем только const0, в которой храним -1. И уже sub/sbc с этой константой и младшими 16 регистрами. Итого теряется толька одын регистр. =GM=Читайте внимательно ПДФ-ы. Там всё есть. При "ручном" сбросе TOV1 прерывание по переполнению уже не обрабатывается. Теперь про ICR1H/ICR1L объясняю в последний раз для особо трудных. В системе есть высокоприоритетное прерывание скажем длительностью 100 мкс. Вдруг оно возникает когда в TIMER=FFE0h. Соответственно оно закончится когда в таймере будет 0044h. Однако (случайно так) захват происходит когда в таймере 0020h. Что мы видим? Что Вы видете? ICR1H/ICR1L = 0020h. TOV1 = 1. Вас это удивляет? Как только высокоприоритетное прерывание заканчивается, то прерывание по переполнению не выполняется (!), а выполняется прерывание по захвату и обнаруживает то, что я уже написал. Вообще, я бы анализировал не совпадение с нулём регистра ICR1H, а только его старший бит. Таким образом максимально расширив диапазон допустимых высокоприоритетных прерываний. Ещё вопросы? ЗЫ. singlskv forever!
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Oct 10 2006, 14:33
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(=GM=) Просто механически повторил ваш код, рука, так сказать, пронесла. А вы что, рады технической описке? Таких описок у Вас тут уже немерено  Не, мы не особо рады. Просто перед начинанием споров и критики вы должны были полностью разобраться в уже написанном коде и только когды вы полностью (!) поняли там каждую команду вы имеете право вносить свои предложения по упрощению. Если это послужит вам уроком, то мы думаю будем таки рады  Цитата(=GM=) Пусть одновременно возникло два прерывания: захват и, другое, более приоритетное. Пусть на момент захвата ICR1=00FF. Приоритетное прерывание начнет обрабатываться первым и пусть оно обрабатывается, скажем, 270 мкс. Поскольку таймер работает параллельно и независимо от приоритетного прерывания, возникнет OVF1=1. Это наверное тоже техническая описка? Только возникла она наверно ещё глубоко в мыслях. Мозг как бы обманул сам себя. PS Без обид. Это я пока по-доброму критикую.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Oct 10 2006, 14:36
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(SasaVitebsk @ Oct 10 2006, 12:25)  Хотел бы отметить два факта. Во-первых просто поразительно насколько у людей разные интересы.  На мой взгляд совсем незначительная проблема вызвала серьёзный интерес и бурную деятельность.  Проблема не такая уж и незначительная. Постоянно натыкаюсь в сети на проекты частотомеров, цифровых шкал, где разработчики бездумно выставляют секундный интервал и подсчитывают количество приходящих импульсов, не пытаясь выжать максимальную точность. На 1 кГц они могут получить ТРИ значащих цифры! Исходя из собственного опыта, скажу, что на 16-мегагерцовой атмеге можно измерить частоту до 3.2 МГц с точностью 0.2 Гц, т.е. с относительной погрешностью порядка 6Е-8. Причем на голой атмеге, не используя всяких прибамбасов в виде фпга и т.д. а если на входе поставить пять D-триггеров, то можно мерить 100 МГц с точностью 8 Гц. Получше, чем у некоторых промышленных частотомеров, как вам такая перспектива, э? Цитата(SasaVitebsk @ Oct 10 2006, 12:25)  Хотя я (как все) и применяю вычитание вместо сложения, тем не менее я делаю ещё так. Один из регистров в младшей области обзываю Vol0 и очищаю его. Ну и дальше работаю с ним. Это помогает в разных ситуациях. типа sts xxx,Vol0... inc/adc ... add Zl,wl/adc Zh,Vol0 ... Я тоже так иногда делаю. Но чаще использую регистры временного хранения. Занес константу, сделал что-то и забыл.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Oct 10 2006, 16:20
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Еще подправил код: - заменил на одну константу ConstFF и sub/sbc - за счет этого ввел новую константу _TOV1 которая является флагом TOV1 в TIFR - что позволило избавиться от AL==R24 в прерывании TIM1_CAPT - подправил код для длинных прерываний, сдвинул в "середину" ICR1H >=7F Код .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 mov R7, ConstFF lsr R7 cp R5, R7 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 ; Timer Overflow: TIM1_OVF: in _Sreg,SREG sub R2, ConstFF sbc R3, ConstFF out SREG,_Sreg reti Если кто найдет баги, телеграфируйте ...
|
|
|
|
|
Oct 10 2006, 17:52
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(=GM= @ Oct 10 2006, 21:15)  Мне кажется, зря вы здесь используете повторно r7, r6. Вдруг основная программа не успеет их обработать, а уже возникнет новое прерывание TIM1_CAPT. Понятно, что хочется съэкономить, но такая экономия может выйти боком(:-) Нет, c R6,R7 там все в порядке. вот этот код будет выполнен в конце прерывания TIM1_CAPT при любых условиях: Код mov R6,R2 mov R7,R3 так что здесь, ИМХО все ОК.
|
|
|
|
|
Oct 10 2006, 18:06
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(=GM= @ Oct 10 2006, 21:15)  Цитата(singlskv @ Oct 10 2006, 15:20)  Еще подправил код:
Что-то мне разонравилось измерение по прерыванию. Наверное, надо делать без всяких прерываний, в фоне(:-). Вам больше не нравятся прерывания ? - Вы просто не умеете их правильно готовить (с) (не мой)
|
|
|
|
|
Oct 10 2006, 20:19
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(singlskv) Код in R5, ICR1H mov R7, ConstFF lsr R7 cp R5, R7 brsh _do_not_correct_result Маленькое упрощение: Код in R5, ICR1H tst R5 brmi _do_not_correct_result Цитата(=GM=) Как там (в r5-r4) может быть 10 или 100 и быть перенос? Его не может быть или я ничего не понимаю. Перенос может быть, если только в ICR1H-ICR1L (читай r5-r4) было 0хFFFF, а потом стало 0х0000. Никак не 10 или 100. ........... Я-то понял, а вот вы похоже нет, хотя вы один из авторов(:-). И при чем здесь количество прерываний? ........... Я вот на форуме стараюсь показать лучшее, что знаю сам, и поучиться лучшему у других. Вы уже наконец поняли о чём я говорил? Если да, то ничего не хотите добавить к этому? Цитата(=GM=) Что-то мне разонравилось измерение по прерыванию. Наверное, надо делать без всяких прерываний, в фоне(:-).  Особенно если учесть, что раньше был другой текст
Сообщение отредактировал GetSmart - Oct 10 2006, 20:41
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Oct 10 2006, 20:58
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
[quote name='GetSmart' date='Oct 11 2006, 00:19' post='163416'] [quote=singlskv] Код in R5, ICR1H mov R7, ConstFF lsr R7 cp R5, R7 brsh _do_not_correct_result [/quote]Маленькое упрощение: Код in R5, ICR1H tst R5 brmi _do_not_correct_result Ой... , Вы правы (вот и я научился чему то новому в этом топике  ) Уже не помню почему, но у меня стойко закрепилось в мозгу, что после tst Rxx нужно использовать breq/brne, jz/jnz, и т.д. Спасибо...
|
|
|
|
|
Oct 10 2006, 22:32
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(SasaVitebsk @ Oct 10 2006, 16:25)  Хотел бы отметить два факта. Во-первых просто поразительно насколько у людей разные интересы.  На мой взгляд совсем незначительная проблема вызвала серьёзный интерес и бурную деятельность.  Дык задача многосторонняя, от того и интерес. ;> В системе с одноуровневым КП и таймером с "окном" ~1-10% от интервала измерений, обслуживать несколько прерываний и при этом не терять точность. Нельзя сказать, что это тривиальная задача для AVR. Ну и плюс простота кода - не нужно долго вникать. =GM=- это конечно здорово, что вы попытались упростить код, правильно мыслите, однако прислушайтесь к совету GetSmart - перед всякой критикой нужно полностью разобраться в том, что уже есть, иначе критика вызывает улыбку. GetSmartЯ таки все так же против увеличения латентности других прерываний и использования проверки последнего бита. 256 тактов "запаса" еще как-то понятно, а вот на что может понадобиться больше - уже нет. Тем паче "флагманские" прерывания (которые могут потребовать относительно длительной обработки) обладают более низким приоритетом чем T1_CAPT. Половина таймера это на самом деле очень много. И если в системе есть обработчики такой длительности ~32k тактов, то это значит, что мы можем ошибиться уже в обратную сторону - "через круг таймера".
|
|
|
|
|
Oct 10 2006, 23:11
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
defunctСкучали тут без Вас  А почему все думают, что у АВР одноуровневой КП? Может уже я чего-то не знаю? Цитата(defunct) Я таки все так же против увеличения латентности других прерываний и использования проверки последнего бита. Так... Вы - против, я - за. Что будем с этим делать? Ограничение только в том, что любое допустимое в системе прерывание обязано занимать время меньшее, чем минимум времени между двумя исследуемыми импульсами. А уж сколько оно будет на практике, 100 мкс или 30 мс - это должен учитывать разработчик конкретного устройства. Эта программа даёт ему такую возможность вплоть до 32 мс. Поясните, плиз, как можно ошибиться уже в обратную сторону?
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Oct 10 2006, 23:14
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(GetSmart @ Oct 11 2006, 02:01)  А почему все думают, что у АВР одноуровневой КП? Может уже я чего-то не знаю? А почему "думают"? ;> Об этом в ДШ сказано. When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is executed. .... When the AVR exits from an interrupt, it will always return to the main program and execute one more instruction before any pending interrupt is served.
Если к примеру сравнить с C51, то в нем предусмотрено два уровня, L0, L1. Когда выполняется обработчик L0, то другие прерывания с приоритетом L0 не могут быть вызваны, зато прерывание с приоритетом L1 - может. В AVR такого нет по определению, а установка флага I внутри обработчика прерывания, можно назвать не иначе как "глюкодром"  , ведущий к deadlock основной программы. Цитата Так... Вы - против, я - за. Что будем с этим делать? Ничего  оставим как есть - 2 варианта. Не бывает единственно верных решений. Цитата Поясните, плиз, как можно ошибиться уже в обратную сторону? по тактам начиная с такта i: 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 - начало входа в обработчик (не менее 4х тактов) T1_ICAP, TCNT1 = 0xFFFB, TOV1 = 0 i + 0x8001 - первая команда обработчика T1_ICAP, TCNT1 = 0xFFFF, TOV1 = 0 i + 0x8002 - вторая команда обработчика T1_ICAP, TOV1 = 1 <------ ! ну и коррекция рез-тата +0x10000, т.к. попадаем под условие коррекции (ICR < 32k, TOV=1). Эта одна из возможных иллюстраций. На самом деле все ухудшается еще и наличием более высокоприоритетных чем T1_ICAP прерываний от T2 и INTx и т.п.
|
|
|
|
|
Oct 10 2006, 23:57
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(GetSmart @ Oct 11 2006, 02:34)  Не, ну не надо так уж клеймить АВР. Не "клеймлю" я его ;> AVR - отличный процессор. Просто я не сторонник изощренных путей написания программ. На мой взгляд, надо подстраиваться под железо и писать соответствующие обработчики прерываний. Для AVR они должны быть короткими, т.к. нет многоуровневого КП. Если же стоит обратная задача - подобрать железо для программы, то она должна решаться соответствующим образом - выбором оптимального железа на стадии проектирования. Цитата Минус только в отсутствии аппаратного запоминания текущего приоритета и запрета низкоприоритетных прерываний и текущего. Это не минус, это фича  Для многих задач это плюс т.к. одноуровневый КП избавляет программиста от некоторых проблем синхронизации. Цитата При большом желании можно легко (!) сделать двухуровневой КП (трёх) если вручную запрещать текущее прерывание, а потом устанавливать флаг I. Плохо только что стека маловато. Можно, но не нужно. Проще просто подобрать другой камень когда это действительно надо.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|