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

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

Здравствуйте!

Как можно измерить временные интервалы дительностью несколько секунд на AVRах с точностью до микросекунды? При том что кварц стоит на 1 МГц? Емкости таймера-счетчика 16 бит для такой задачи не хватает...

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


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

А инкрементировать ещё одни (старшие) 16 бит по переполнению таймера вам слабо?

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


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

А инкрементировать ещё одни (старшие) 16 бит по переполнению таймера вам слабо?

А считывать значения периода с разрешением 1мкс при тактовой 1МГц он будет успевать? :)

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


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

C точностью до микросекунды с кварцем на 1Мгц никак.

А я бы сказал - элементарно, но на AVR. Для PIC не знаю точно, есть у них функция захвата и есть ли делитель у таймера? То есть инкрементируется таймер от 1 МГц или от делителя 1/4 или ещё как. Если от 1 МГц и есть захват, то этого достаточно. Ну и интервал не должен быть очень маленьким. Внутри него должно успеть обработаться прерывание.

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


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

А инкрементировать ещё одни (старшие) 16 бит по переполнению таймера вам слабо?
Можно подробнее чуточку? Какие старшие 16 бит? Подскажите, пожалуйста, как это можно сделать?

Я пытался реализовать это так:

По внешнему прерыванию ставлю таймер в режим сравнения на 50К (+обнуление по переполнению) и по прерыванию увеличиваю значение 32-битной переменной в ОЗУ на эти самые 50к. После ещё одного внешнего прерывания останавливаю таймер и остаток (содержимое TCNTn) добавляю к этой же переменной (после чего обнуляю TCNTn). Но: в результате, хоть я и подаю на вход импульсы постоянной длительности, значения на выходе пляшут как будет бы у меня генератор случайных чисел =(

Изменено пользователем AVR

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


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

Чё-то я ослеп. Речь как раз об AVR. Берёте Мегу8, она с захватом. Всё получится с точностью 1 мкс, если интервалы будут хотя бы 10 и более мкс. Это если писать на асме. Если на си, то раза в 3 большие интервалы.

 

Вроде бы правильно делаете. Может какая мелкая ошибка. Прикрепите исходник, я посмотрю. Кстати, когда обнуляете таймер, обнуляете ещё переменную?

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


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

Чё-то я ослеп. Речь как раз об AVR. Берёте Мегу8, она с захватом. Всё получится с точностью 1 мкс, если интервалы будут хотя бы 10 и более мкс. Это если писать на асме. Если на си, то раза в 3 большие интервалы.

 

Вроде бы правильно делаете. Может какая мелкая ошибка. Прикрепите исходник, я посмотрю. Кстати, когда обнуляете таймер, обнуляете ещё переменную?

 

Получится, но с одной оговоркой:

 

не всегда будет указанная точность.

 

Нельзя выйти на точность в 1мкс в случае когда прерывание таймера "по захвату" сработает одновременно с прерыванием таймера "по переполнению" либо по "сравнению" для увеличения старшей части 32-х битного счетчика времени.

 

 

Можно подробнее чуточку? Какие старшие 16 бит? Подскажите, пожалуйста, как это можно сделать?

Пример, с учетом того, что Timer1 уже настроен на работу в режиме Input Capture с генерацией прерываний по CAPT и по OVF.

В таком виде как в примере - нельзя выполнять команды условного перехода и арифметические команды в основном цикле программы.

 

 

.def  AL = R24
.def  Const0 = R8
.def  Const1 = R9

....
   ldi  AL, 1
   mov  Const1, AL
   clr  Const0
...

; обработчик Input Capture:
TIM1_CAPT:
    in    R4, ICR1L
    in    R5, ICR1H
    mov   R6, R2
    mov   R7, R3
    tst   R5
    brne  _do_not_correct_result
    in    AL, TIFR
    andi  AL, (1 << TOV1)
    breq  _do_not_correct_result
    add   R6, Const1
    adc   R7, Const0
_do_not_correct_result:
; <-- 32-х битный результат в четверке регистров R7-R6-R5-R4 (MSB R7)
    reti
     

; обработчик Timer Overflow:
TIM1_OVF:
     add R2, Const1; Инкрементировать старшие 16 бит 32-х битного счетчика
     adс R3, Const0; учет переноса.
     reti

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


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

Нельзя выйти на точность в 1мкс в случае когда прерывание таймера "по захвату" сработает одновременно с прерыванием таймера "по переполнению" либо по "сравнению" для увеличения старшей части 32-х битного счетчика времени.

Ну почему же? Захват же аппаратный. Немного дополнительных проверок в коде могут отличить в какой момент сработал захват если он сработал рядом (чуть раньше, чуть позже) с прерыванием по переполнению. А если захват аппаратный и прерывание по переполнению, то таймер никогда не останавливается и "захватывается" точное значение. Поэтому я бы рекомендовал делать прерывание именно по переполнению.

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


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

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

Да все так, доп проверка для ((ICR > 0) и (ICR < длительность обработчика OVF))

Все равно есть ситуации где точность 1mks на двух прерываниях обеспечить не реально.

Ну представьте захвачен ICR = 0.

Что делать? Было отработано прерывание по переполнению или нет? А бог его знает. Если CAPT сработал в момент перехода на обработку OVF - то было, если раньше - то не было. А теряется не много ни мало всего лишь 64k mks ;>

 

т.е. думаю нужно вводить еще прерывание OC, с OCR = 64k/2, чтобы точно знать о природе ICR=0.

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


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

Ну представьте захвачен ICR = 0. Что делать? Было отработано прерывание по переполнению или нет?

Да ладно Вам! Для этого нужно прочитать TIFR и понять обработалось уже прерывание по переполнению или нет.

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


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

Ну представьте захвачен ICR = 0. Что делать? Было отработано прерывание по переполнению или нет?

Да ладно Вам! Для этого нужно прочитать TIFR и понять обработалось уже прерывание по переполнению или нет.

Действительно :a14:

"А ларчик то просто открывался" :)

 

(подправил код примера с учетом Вашего последнего поста.)

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


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

Надо только в прерывании захвата смотреть, если число маленькое (<100) то проверять TIFR, а если большое, то не проверять. Иначе тоже может сглючить.

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


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

Надо только в прерывании захвата смотреть, если число маленькое (<100) то проверять TIFR, а если большое, то не проверять. Иначе тоже может сглючить.

Там это учтено:

 

tst r1

brne ...

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


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

Там это учтено:

Да, я это написал когда ещё не было.

 

Кстати, 16 бит таймера и 8 старших бит счётчика в регистре дадут уже период в 16 секунд. Может этого будет достаточно?

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


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

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

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

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

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

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

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

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

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

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