|
|
  |
Измерение временных интервалов, с высокой точностью |
|
|
|
Oct 9 2006, 16:06
|

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

|
Цитата(GetSmart @ Oct 9 2006, 14:22)  Цитата(=GM=) Код mov temp,r4;с возможным переносом or temp,r5;во время захвата brne nocarry;не было переноса Плохая идея. Хуже чем было. Там (r5:r4) может быть и 10 и 100, если например выполнялось третье высокоприоритетное прерывание. А после его завершения началось прерывание CAPT. Ничего не понял, поясните. Здесь никакой идеи, просто проверка содержимого r5:r4 на 0, только 0 может показать, что был перенос.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Oct 9 2006, 16:09
|

Гуру
     
Группа: Свой
Сообщений: 4 363
Регистрация: 13-05-05
Из: Москва
Пользователь №: 4 987

|
Цитата(=GM= @ Oct 9 2006, 16:56)  Поясните, что в данном случае вы понимаете под погрешностью и разрешением? И как вы их вычисляете? Мне кажется, всем будет полезно понять разницу в понятиях. Обратимся к посту №1 данной темы. Автор пишет: Цитата Как можно измерить временные интервалы дительностью несколько секунд на AVRах с точностью до микросекунды? Иными словами, опорный генератор не должен иметь отклонение частоты относительно мировых эталонов более 1/(N*1000000), где N -количество секунд в измеряемом интервале (шумы генератора здесь не рассматриваем). Получить такую точность с помощью простого генератора на кварце - сама по себе нетривиальная задача. Когда же мы говорим о временнОм разрешении, то, как Вы верно заметили, под этим подразумевается погрешность метода. Она является абсолютной величиной, и не зависит от измеряемого интервала времени. Суммарная ошибка в первом приближении определяется двумя этими факторами. Цитата(=GM= @ Oct 9 2006, 16:56)  Хотя тут вопрос, может ли помочь тот факт, что кратковременная нестабильность (на секундном интервале) кварцевого генератора достигает 1Е-9..1Е-12? Нет, не поможет. Кратковременная нестабильность дополнительно ухудшает точность опорного генератора, хотя и является величиной "второго порядка малости".
--------------------
Самонадеянность слепа. Сомнения - спутник разума. (с)
|
|
|
|
|
Oct 9 2006, 16:34
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(=GM= @ Oct 9 2006, 17:59)  Хочу немного покритиковать программу.
1) От возникновения прерывания захвата до команды "in AL,TIFR" может пройти от 12 до 15 МЦ, т.е. достаточно много времени, чтобы произошел перенос от переполнения, следовательно, возможна ошибка в определении времени. Вы не учли вот эту проверку: Код in R5, ICR1H tst R5 brne _do_not_correct_result которая происходит перед "in AL, TIFR" Цитата 2) Вполне возможно, что если прерывания TIM1_OVF и TIM1_CAPT возникли в течение указанного периода, то прерывание TIM1_OVF выполнится после TIM1_CAPT и ПОВТОРНО скорректирует результат в r3-r2 (не уверен на все 100, надо проверять). Вот это помагает избежать данной проблеммы: Код out TIFR, AL Цитата 3) Вход в прерывание TIM1_CAPT означает конец интервала измерения ... или начало .... Ну например если мы хотим измерять длительность единичного импульса на входе. Цитата Ну и последнее, в подобных случаях предпочитаю использовать конструкцию Код subi r2,-1 ; sbci r3,-1 ; Вместо эквивалентной Код add R2,сonst1 ; adc R3,сonst0 ; что очевидно лучше, поскольку освобождаются два регистра сonst0 и сonst1. subi на регистрах R0-R15 ?! ню...ню...
|
|
|
|
|
Oct 9 2006, 20:15
|

Местный
  
Группа: Участник
Сообщений: 318
Регистрация: 21-07-06
Из: Минск
Пользователь №: 18 986

|
Цитата Ну и последнее, в подобных случаях предпочитаю использовать конструкцию Код subi r2,-1 ; sbci r3,-1 ; А не так, случайно: Код subi r16,low(-1) sbci r17,high(-1) Просто повезло, что в -1 младший и старший байты равны. но писать так не следует.
Сообщение отредактировал Леонид Иванович - Oct 9 2006, 20:16
--------------------
|
|
|
|
|
Oct 10 2006, 10:43
|

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

|
Цитата(GetSmart @ Oct 9 2006, 15:24)  Цитата(=GM=) Ничего не понял, поясните. Здесь никакой идеи, просто проверка содержимого r5:r4 на 0, только 0 может показать, что был перенос. Я же написал, что там может быть и 10 и 100 и при этом быть перенос. Что Вы не поняли? Что в системе может быть больше чем эти два прерывания? Вы хоть поняли как предыдущая версия программы работала? Как там (в r5-r4) может быть 10 или 100 и быть перенос? Его не может быть или я ничего не понимаю. Перенос может быть, если только в ICR1H-ICR1L (читай r5-r4) было 0хFFFF, а потом стало 0х0000. Никак не 10 или 100. Ладно, отбросим предрассудки и недоразумения(:-), и начнем сначала. 1) Есть переменная в r7-r6-r5-r4, показывающая время. Содержимое регистров r5-r4 отражает содержимое аппаратных регистров захвата, по сути текущее время таймера1 на конец (или начало, не суть) измеряемого интервала. Каждые 65536 мкс содержимое таймера1 обнуляется и возникает перенос, который программно учитывается в регистрах r7-r6. Согласны? 2) Пойдем дальше. Как только возникает конец интервала, тут же происходит захват и мы имеем точное время записи, копируя содержимое ICR1L, ICR1H в r5-r4, и содержимое r3-r2 в r7-r6. Согласны? 3) Однако, если захват произойдет на 65536 микросекунде нашего таймера, возникнет перенос, который еще не учтен в r3-r2, и следовательно, в r7-r6. Как его учесть? Использовать ТЕКУЩИЙ аппаратный перенос от таймера1 НЕЛЬЗЯ, т.к. он никакого отношения к времени захвата не имеет. Согласны? 4) Наличие 0х0000 в r5-r4 означает, что в момент захвата произошло переполнение таймера1, и что перенос следует учесть в r7-r6. Согласны? Ответьте по пунктам, если не трудно. Цитата Что в системе может быть больше чем эти два прерывания? Вы хоть поняли как предыдущая версия программы работала? Я-то понял, а вот вы похоже нет, хотя вы один из авторов(:-). И при чем здесь количество прерываний?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Oct 10 2006, 11:04
|

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

|
Цитата(Леонид Иванович @ Oct 9 2006, 19:15)  А не так, случайно: Код subi r16,low(-1) sbci r17,high(-1) Просто повезло, что в -1 младший и старший байты равны, но писать так не следует. Именно так и надо, так строже, и надёжнее - труднее ошибиться. Но прынцип тот же самый - вычитать минус 1, вместо того, чтобы прибавлять 1. Что очевидно лучше, чем регистровое вычитание, поскольку освобождаются два регистра сonst0 и сonst1. Цитата(singlskv @ Oct 9 2006, 15:34)  subi на регистрах R0-R15 ?! ню...ню... Просто механически повторил ваш код, рука, так сказать, пронесла. А вы что, рады технической описке? Мелочь отметили, а главное пропустили, что не надо впустую инициализировать два регистра, да и сами регистры не нужны? Я вот на форуме стараюсь показать лучшее, что знаю сам, и поучиться лучшему у других.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Oct 10 2006, 11:19
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(=GM= @ Oct 10 2006, 15:04)  Что очевидно лучше, чем регистровое вычитание, поскольку освобождаются два регистра сonst0 и сonst1. Цитата(singlskv @ Oct 9 2006, 15:34)  subi на регистрах R0-R15 ?! ню...ню...
Просто механически повторил ваш код, рука, так сказать, пронесла. А вы что, рады технической описке? Мелочь отметили, а главное пропустили, что не надо впустую инициализировать два регистра, да и сами регистры не нужны? Я вот на форуме стараюсь показать лучшее, что знаю сам, и поучиться лучшему у других. Если использовать subi, то мы занимаем под прерывание дефицитные R16-R32, а их всегда мало. А вот R0-R15 как раз часто бывает в избытке, так что 2 лишних регистра const0 и const1 не очень жалко
|
|
|
|
|
Oct 10 2006, 11:49
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(=GM= @ Oct 10 2006, 14:43)  3) Однако, если захват произойдет на 65536 микросекунде нашего таймера, возникнет перенос, который еще не учтен в r3-r2, и следовательно, в r7-r6. Как его учесть? Использовать ТЕКУЩИЙ аппаратный перенос от таймера1 НЕЛЬЗЯ, т.к. он никакого отношения к времени захвата не имеет. Код <---- ICR1=FFFF момент захвата <---- TCNT1=FFFF TIM1_CAPT: <---- ICR1=FFFF начало обработки прерывания <---- TCNT1=5 <---- TOV1=1 in _Sreg,SREG in R4, ICR1L <---- R4=FF in R5, ICR1H <---- R5=FF tst R5 <---- R5==0 ??? brne _do_not_correct_result <---- переходим без коррекции in AL, TIFR andi AL, (1 << TOV1) breq _do_not_correct_result out TIFR, AL add R2, Const1 adc R3, Const0 _do_not_correct_result: mov R6, R2 mov R7, R3 out SREG,_Sreg reti
|
|
|
|
|
Oct 10 2006, 12:51
|

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

|
Чудак-человек, я согласен, что практически ваша программа будет работать, хотя логика запутанная(:-).
Попробую сконструировать пример, возможно не совсем удачный, хотелось просто показать возможный источник возникновения ошибки.
Пусть одновременно возникло два прерывания: захват и, другое, более приоритетное. Пусть на момент захвата ICR1=00FF. Приоритетное прерывание начнет обрабатываться первым и пусть оно обрабатывается, скажем, 270 мкс. Поскольку таймер работает параллельно и независимо от приоритетного прерывания, возникнет OVF1=1.
Приоритетное прерывание закончило работу, начинает работать ваше прерывание по захвату. Оно проверяет r5=0? Да. Проверяет далее OVF1=1? Да. И корректирует содержимое r3-r2 и, соответственно, r7-r6. А это неправильно. Как-то так.
И последний интересный вопрос, ответ на который я пока не знаю. Если прерывания TIM1_OVF и TIM1_CAPT возникли одновременно, и стало выполняться прерывание TIM1_CAPT, а прерывание TIM1_OVF дожидается своей очереди, вы уверены, что можно его снять, сбросив TOV1? В документации ничего не нашел по этому поводу.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Oct 10 2006, 13:23
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(=GM= @ Oct 10 2006, 16:51)  Пусть одновременно возникло два прерывания: захват и, другое, более приоритетное. Пусть на момент захвата ICR1=00FF. Приоритетное прерывание начнет обрабатываться первым и пусть оно обрабатывается, скажем, 270 мкс. Поскольку таймер работает параллельно и независимо от приоритетного прерывания, возникнет OVF1=1.
Приоритетное прерывание закончило работу, начинает работать ваше прерывание по захвату. Оно проверяет r5=0? Да. Проверяет далее OVF1=1? Да. И корректирует содержимое r3-r2 и, соответственно, r7-r6. А это неправильно. Как-то так. ICR1=00FF TCNT1=00FF пусть прошло 270мкс =010E время обработки другого прерывания ICR1=00FF TCNT1=00FF+010E=020D r5=0 ? Да. OVF1=1 ? нет итого: r3-r2 не корректируем Цитата И последний интересный вопрос, ответ на который я пока не знаю. Если прерывания TIM1_OVF и TIM1_CAPT возникли одновременно, и стало выполняться прерывание TIM1_CAPT, а прерывание TIM1_OVF дожидается своей очереди, вы уверены, что можно его снять, сбросив TOV1? В документации ничего не нашел по этому поводу. фраза из даташита: TOV1 is automatically cleared when the Timer/Counter1 Overflow Interrupt Vector is executed. Alternatively, TOV1 can be cleared by writing a logic one to its bit location.На самом деле Вы привели просто неудачный пример. Проблемма с длинным прерыванием действительно есть, и выглядит она вот так: Int0: <---длинное прерывание >256 тактов ............... TCNT1=0 <--- здесь переполнение TOV1=1 .............. ICR=0101h <--- здесь захват ............. reti CAPT: <--- сюда попадаем сразу после Int0 .............. in r4,ICR1L in r5,ICR1H <--- r5=01 не корректируем, а зря <--- TOV1=1
|
|
|
|
|
Oct 10 2006, 13:25
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(singlskv @ Oct 10 2006, 14:19)  Цитата(=GM= @ Oct 10 2006, 15:04)  Что очевидно лучше, чем регистровое вычитание, поскольку освобождаются два регистра сonst0 и сonst1. Цитата(singlskv @ Oct 9 2006, 15:34)  subi на регистрах R0-R15 ?! ню...ню...
Просто механически повторил ваш код, рука, так сказать, пронесла. А вы что, рады технической описке? Мелочь отметили, а главное пропустили, что не надо впустую инициализировать два регистра, да и сами регистры не нужны? Я вот на форуме стараюсь показать лучшее, что знаю сам, и поучиться лучшему у других. Если использовать subi, то мы занимаем под прерывание дефицитные R16-R32, а их всегда мало. А вот R0-R15 как раз часто бывает в избытке, так что 2 лишних регистра const0 и const1 не очень жалко  Хотел бы отметить два факта. Во-первых просто поразительно насколько у людей разные интересы.  На мой взгляд совсем незначительная проблема вызвала серьёзный интерес и бурную деятельность. Во-вторых. Хотя я (как все) и применяю вычитание вместо сложения, тем не менее я делаю ещё так. Один из регистров в младшей области обзываю Vol0 и очищаю его. Ну и дальше работаю с ним. Это помогает в разных ситуациях. типа sts xxx,Vol0... inc/adc ... add Zl,wl/adc Zh,Vol0 ... Где-то (по моему в PIC) подобное на уровне архитектуры применяется.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|