Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: MegaAVR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Duduka
[font=Times New Roman][size=4]
Привет, всем посетителям форума!
Возникла проблема с мегой 128...Может кто-нибудь из специалистов обратит внимание и разъяснит неопытному пользователю в чем проблема?

А вопрос в следующем...пытаюсь измерить период с точностью до 0,1 мкс. Для этого задействована пара счетчиков (вариантов уже накопилось множество, поэтому прикладываю самый простой на, мой взгляд). Измеряемый диапазон частот 600 Гц-2,5 кГц

Используется два таймера:
-Т/С0-генерирует 102, 4 кГц, при каждом совпадении счетного регистра осуществляется инкремент регистров-результата;
-Т/С2-считает импульсы с датчика-для обеспечения заданной точности 100*Т .
Как только досчитали до 100 останавливаем , обнуляем таймеры и передаем по ком порту на комп.
Мегу тактирую 7,3728 МГц (реально 7,3724 МГц)

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

Работаю с STK500/501, AVR Studio 4.12 и самодельным Jtag ICE.
В качестве сигнала с датчика использую кварц STK500.
IgorKossak
Цитата(Duduka @ Feb 28 2007, 10:49) *
Используется два таймера:
-Т/С0-генерирует 102, 4 кГц, при каждом совпадении счетного регистра осуществляется инкремент регистров-результата;
-Т/С2-считает импульсы с датчика-для обеспечения заданной точности 100*Т .
Как только досчитали до 100 останавливаем , обнуляем таймеры и передаем по ком порту на комп.
Мегу тактирую 7,3728 МГц (реально 7,3724 МГц)

Приведите фрагмент кода.
Duduka
[font=Times New Roman][size=4]

А прикрепленный файл не подходит?
IgorKossak
1. Прерывание OC2addr_int: не содержит инструкции reti или я что-то не понял?
2. В прерывании OC0addr_int: строка cpi numberL,0xFF явно лишняя.
3. С Вашими настройками нулевого таймера полная каша. Проверьте то ли Вы пишете и в те ли регистры.
SasaVitebsk
Прерывания ни когда не дадут точный временной интервал. В зависимости от применяемых в программе команд у вас будет дрожание от 1 до 3 тактов. На частоте 7.3728 это составит от 0.136 до 0.4 мкс соответственно.

Для измерения точных интервалов требуется

1) "ворота генерировать аппаратным способом. На худой конец можно попробовать с помощью таймера, но с аппаратным выводом по OC1A к примеру или на другую ножку. То есть ворота должны быть сформированы аппаратно!
2) чтение можно осуществлять ч/з ворота по захвату (например ч/з ic3a).

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

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

Соответственно формируем аппаратно частоту заполнения и подаём ч/з ворота на вход захвата. Если частота велика, то пропускаем ч/з счётчик. Если скважность меньше двух, то необходима ещё схема типа запускаемого одновибратора, с целью успеть считать данные до момента повторного открытия ворот.

Прерывания могут быть только по переполнению.
Duduka
Цитата(IgorKossak @ Feb 28 2007, 13:42) *
1. Прерывание OC2addr_int: не содержит инструкции reti или я что-то не понял?
2. В прерывании OC0addr_int: строка cpi numberL,0xFF явно лишняя.
3. С Вашими настройками нулевого таймера полная каша. Проверьте то ли Вы пишете и в те ли регистры.


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

rjmp wait_write

но при таком выходе из п/п мне следовало бы заново проинициализировать стек?!

По поводу лишней строчки согласна, т.к. проверяю состояние флага Z.

А вот, что за каша в настройках нулевого таймера??

out ASSR,zero; выбираем синхронный режим
ldi temp,0x23 ; модуль счета
out OCR0,temp ;
ldi temp,0x99 ; режим работы
out TCCR0,temp ;
out TCNT0,zero ; обнуляем счетный регистр

В чем ошибка?
Duduka
Цитата(SasaVitebsk @ Feb 28 2007, 14:17) *
Прерывания ни когда не дадут точный временной интервал. В зависимости от применяемых в программе команд у вас будет дрожание от 1 до 3 тактов. На частоте 7.3728 это составит от 0.136 до 0.4 мкс соответственно.

Для измерения точных интервалов требуется

1) "ворота генерировать аппаратным способом. На худой конец можно попробовать с помощью таймера, но с аппаратным выводом по OC1A к примеру или на другую ножку. То есть ворота должны быть сформированы аппаратно!
2) чтение можно осуществлять ч/з ворота по захвату (например ч/з ic3a).

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

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

Соответственно формируем аппаратно частоту заполнения и подаём ч/з ворота на вход захвата. Если частота велика, то пропускаем ч/з счётчик. Если скважность меньше двух, то необходима ещё схема типа запускаемого одновибратора, с целью успеть считать данные до момента повторного открытия ворот.

Прерывания могут быть только по переполнению.


Если я правильно понимаю, пусть:

-Т/С0- генерирует импульсы заполнения ...пусть 102,4 кГц, которые можно "снимать" с выхода ОС0 и пдавать на другой счетчик.
-Т/С2 организует временные ворота, на его вход поступают импульсы с датчика, считает до 100, сбрасывается, меняется значение на выходной ножке, по которому счетчик, считающий импульсы заполнения, сохраняет полученные значения;
-Т/С3- собственно считает импульсы заполнения.

Так?
IgorKossak
Цитата(Duduka @ Feb 28 2007, 16:15) *
По поводу прерывания: да инструкции действительно нет, но там есть команда

rjmp wait_write

но при таком выходе из п/п мне следовало бы заново проинициализировать стек?!

Да если бы только в этом дело. Сейчас может этого и хватит, но при минимальном развитии программы такой подход крайне неэлегантен. Поэтому подпрограммы и прерывания (особенно) желательно завершать штатным образом. Да и на С в будущем проще будет портировать.
Цитата(Duduka @ Feb 28 2007, 16:15) *
По поводу лишней строчки согласна, т.к. проверяю состояние флага Z.

Строчка не столько лишняя, сколько ошибочная, т. к. инкремент старшей части надо делать при переходе младшей в 0х00, а не в 0xFF.
Цитата(Duduka @ Feb 28 2007, 16:15) *
А вот, что за каша в настройках нулевого таймера??

out ASSR,zero; выбираем синхронный режим
ldi temp,0x23 ; модуль счета
out OCR0,temp ;
ldi temp,0x99 ; режим работы
out TCCR0,temp ;
out TCNT0,zero ; обнуляем счетный регистр

В чем ошибка?

Здесь я имел в виду навороченность настроек TCCR0.
На мой взгляд управлять выходом OC0 нет необходимости, т. к. Вы принудительно дёргаете shinad,inter0. Настройка в этом случае будет выглядеть как ldi temp,0x09.
Проверьте, может я и не прав.
Duduka
Да, вы правы, ненчего лишний раз дергать вывод...
но так как мне хотелось видеть (для проверки), что генерирует счетчик, думаю в таком случае
ldi temp,0x19.

Спасибо за ваши советы! Только вот общий вопрос по теме остается неразрешенным...погрешность каким-то образом зависит от количества выполняемых инструкций между пуском и остановкой счетчиков??
SasaVitebsk
Цитата(Duduka @ Feb 28 2007, 12:49) *
А вопрос в следующем...пытаюсь измерить период с точностью до 0,1 мкс. Для этого задействована пара счетчиков (вариантов уже накопилось множество, поэтому прикладываю самый простой на, мой взгляд). Измеряемый диапазон частот 600 Гц-2,5 кГц


Давайте переведём 600 Гц - период 1666.7мкс (411Ah единиц с шагом 0.1мкс)
2.5кГц - 400.0 (FA0h единиц с шагом 0.1мкс)

Таким образом вам необходимо посчитать импульсы частотой 1/0.1мкс = 10МГц и для этого достаточно 16-ти битного таймера. Из приведенного видно что на частоте 7372800 вы не получите данную точность без внешних элементов.

Необходимо применить кварц с частотой не менее 10МГц.

Если мы применим кварц 10 МГц, то необходимо следующее.

1) Настроить выход меги в режиме генерации CLK.
2) Применить 1533ли1 к примеру (Если мерим длит. положительного импульса). Если надо определять что мерить полож или отриц, то незначительно сложнее не всё поместится на одной ЛА3 или 74hc00.
3) Измеряемый сигнал подать на 1 ногу а заполнение на вторую. С выхода (третья нога) на вход захвата шеснадцатибитного таймера (например IC1A).
4) Также измеряемый сигнал подаём на вход INT0 к примеру.
5) Настраиваем прерывание от INT0 на прерывание по перепаду в 0.
6) Настраиваем таймер один канал а на захват.

Алгоритм измерения следующий.
По прерыванию от Int0 (конец полож импульса измеряемого сигнала - измерение закончилось) мы читаем значение ICR1A, что и является значением периода измеренного сигнала (можно выводить). И сбрасываем значение ICR1A таймера (начинаем новый отсчёт)



Программу вашу не читал. Пока без надобности. Необходимо что бы вы сами поняли что хотите сделать и внятно смогли другим объяснить.




Да... упустил одну деталь которую сам же и писал... smile.gif

На частоте 10MHz ваша однокристалка не сосчитает импульсы 10MHz. По этому изменения следующие (тоже писал в предыдущем посте).

Между выходом мелкосхемы и счётным входом однокристалки необходимо поставить доп счётчик. К примеру ИЕ7 а его выходы (4 штуки) на свободные входы однокристалки. При чтении необходимо читать ICR1A (старшие 16 разрядов) и входы счётчика (младшие 4). В остальном нет отличий.
bodja74
Саша ,у таймера есть прерывание по захвату,так что все шаманство с INT можно отбросить,
счетчик посчитает импульсы ,но не решит проблемы с их длиной ,тут правда не ясно ,что важнее ,посчитать частоту или длину.
IgorKossak
Действительно, варианта с Input Capture было бы вполне достаточно.
При этом реакция на прерывание должна уложиться в 200 мкс, чего хватит с головой даже в случае применения вытесняющей RTOS в проекте.
Поскольку задача решается аппаратно, то от времени сидения программы в прерывании погрешность не зависит.
Ну и кварц, разумеется должен быть не менее 10 МГц (в идеальных условиях), а лучше 16 МГц.
Рассуждения здесь следующие. Поскольку средство Input Capture синхронизируется тактовой частотой МК, то погрешность отлавливания фронта (или спада) импульса может достигать 0,1 мкс (на 10 МГц). Для измерения периода таких событий нужно два. Поэтому в худшем случае будет 0,2 мкс при тех же 10 МГц.
Это так, навскидку, без применения сложных статистических методов.
SasaVitebsk
Согласен с обоими. Конечно любой разработчик при заказе 0.1 уменьшит для надёжности. Писал на скорую руку перед рыбалкой. Хотя быть может это уже с запасом.
=GM=
Поскольку входной сигнал асинхронен по отношению к системной частоте, погрешность измеряемого периода может достигать плюс-минус одного клока. При клоке=10 Мгц это будет плюс-минус 0.1 мкс.

Так что измерения с точностью 0.1 мкс (фактически +-0.05 мкс) можно достичь только с частотой заполнения 20 МГц.
SasaVitebsk
Цитата(=GM= @ Mar 2 2007, 03:30) *
Поскольку входной сигнал асинхронен по отношению к системной частоте, погрешность измеряемого периода может достигать плюс-минус одного клока. При клоке=10 Мгц это будет плюс-минус 0.1 мкс.

Так что измерения с точностью 0.1 мкс (фактически +-0.05 мкс) можно достичь только с частотой заполнения 20 МГц.


Я понимаю о чём вы пишете.

Да действительно. Можно конечно пробовать уменьшить данную ошибку программно. Хотя это будет громоздко.

Тем не менее в неинтелектуальных частотомерах обычно используется заполнение удобное для счёта. Наверное они вводят инструментальную погрешность в 2 единицы заполнения.

Как выход здесь можно использовать внешний генератор меток на 20Мгц. С одним счётчиком достаточно использовать мегу на 7372800
=GM=
Цитата(SasaVitebsk @ Mar 2 2007, 00:32) *
Цитата(=GM= @ Mar 2 2007, 03:30) *

Поскольку входной сигнал асинхронен по отношению к системной частоте, погрешность измеряемого периода может достигать плюс-минус одного клока. При клоке=10 Мгц это будет плюс-минус 0.1 мкс.

Так что измерения с точностью 0.1 мкс (фактически +-0.05 мкс) можно достичь только с частотой заполнения 20 МГц.

Я понимаю о чём вы пишете.
Да действительно. Можно конечно пробовать уменьшить данную ошибку программно. Хотя это будет громоздко.
Тем не менее в неинтелектуальных частотомерах обычно используется заполнение удобное для счёта. Наверное они вводят инструментальную погрешность в 2 единицы заполнения.
Как выход здесь можно использовать внешний генератор меток на 20Мгц. С одним счётчиком достаточно использовать мегу на 7372800

Выше я говорил об измерении ОДНОГО периода измеряемой частоты. А вот если мерять целое количество периодов, скажем за период порядка секунды, будет совсем другая картина.

Оценим погрешность. Измерение целого числа М периодов входного сигнала Тх с точностью +- один клок будет равно N периодам клока To=1/Fclk, т.е.

Tx*M+-То = N*To,

отсюда Tx=To*(N+-1)/M==To*N/M+-To/M. Последнее слагаемое определяет ошибку.

Для входной частоты 600 Гц и периода наблюдения в 1 с ошибка определения периода входной частоты будет +-(1е-6/7.3724)/600=+-0.226 нс.

Как видим погрешность существенно ниже требуемой, так что можно уменьшить время наблюдения.
Оценка даёт минимальное время наблюдения порядка 5 мс.

To Duduka Для измерения частот нужен только микроконтроллер, никаких дополнительных элементов. Меряете длительность целого числа периодов входной частоты, потом делите её на число периодов, получаете искомый период входной частоты с известной точностью.

Вполне возможно, что в вашей программе достаточно изменить сравнение переменной count3 не с 2, а с числом 100..200, проверьте, я особо не вникал. Ну и деление придётся добавить, а лучше сравнивать с числом 128 или даже 256, тогда и делить не надо будет, просто отбросите младший байт. Вот как-то так...
Duduka
Цитата(SasaVitebsk @ Feb 28 2007, 23:48) *
Цитата(Duduka @ Feb 28 2007, 12:49) *

А вопрос в следующем...пытаюсь измерить период с точностью до 0,1 мкс. Для этого задействована пара счетчиков (вариантов уже накопилось множество, поэтому прикладываю самый простой на, мой взгляд). Измеряемый диапазон частот 600 Гц-2,5 кГц


Давайте переведём 600 Гц - период 1666.7мкс (411Ah единиц с шагом 0.1мкс)
2.5кГц - 400.0 (FA0h единиц с шагом 0.1мкс)

Таким образом вам необходимо посчитать импульсы частотой 1/0.1мкс = 10МГц и для этого достаточно 16-ти битного таймера. Из приведенного видно что на частоте 7372800 вы не получите данную точность без внешних элементов.

Необходимо применить кварц с частотой не менее 10МГц.

Если мы применим кварц 10 МГц, то необходимо следующее.

1) Настроить выход меги в режиме генерации CLK.
2) Применить 1533ли1 к примеру (Если мерим длит. положительного импульса). Если надо определять что мерить полож или отриц, то незначительно сложнее не всё поместится на одной ЛА3 или 74hc00.
3) Измеряемый сигнал подать на 1 ногу а заполнение на вторую. С выхода (третья нога) на вход захвата шеснадцатибитного таймера (например IC1A).
4) Также измеряемый сигнал подаём на вход INT0 к примеру.
5) Настраиваем прерывание от INT0 на прерывание по перепаду в 0.
6) Настраиваем таймер один канал а на захват.

Алгоритм измерения следующий.
По прерыванию от Int0 (конец полож импульса измеряемого сигнала - измерение закончилось) мы читаем значение ICR1A, что и является значением периода измеренного сигнала (можно выводить). И сбрасываем значение ICR1A таймера (начинаем новый отсчёт)



Программу вашу не читал. Пока без надобности. Необходимо что бы вы сами поняли что хотите сделать и внятно смогли другим объяснить.




Да... упустил одну деталь которую сам же и писал... smile.gif

На частоте 10MHz ваша однокристалка не сосчитает импульсы 10MHz. По этому изменения следующие (тоже писал в предыдущем посте).

Между выходом мелкосхемы и счётным входом однокристалки необходимо поставить доп счётчик. К примеру ИЕ7 а его выходы (4 штуки) на свободные входы однокристалки. При чтении необходимо читать ICR1A (старшие 16 разрядов) и входы счётчика (младшие 4). В остальном нет отличий.



Очень интересное предложение!Но на мой взгляд имея в своем распоряжении мегу 128, с 4-мя встроенными таймерами обвешиваться таким к-ом микросхем ....абсурдно...

Что касается частоты тактовой 10...16 Мгц и оганизации временных ворот используя один период измеряемого сигнала (извиняюсь, не описала при постановке вопроса), то к сожалению в данном случае в моем распоряжении микросхема ATmega128L, с пониженным энергопотреблением (один из критериев выбора оной микросхемы), которая может тактироваться 8 МГц (мах); так же является необходимым измерять именно по 100 периодам, одного мало, т.к. данный сигнал в реальности будет идти не с генератора, а с датчика. Необходимо усреднение для точности измерений.

Если говорить об аппаратной реализации, используя входы захвата счетчиков (идея описана в седьмом сообщении)это проблемы не решает...имеем ту же самую погрешность в 0,2 мкс...которая меняется в зависимости от к-ва выполняемых инструкций между запуском и остановкой счетчиков!
Duduka
[quote name='=GM=' date='Mar 2 2007, 16:44' post='218520']
[quote name='SasaVitebsk' post='218217' date='Mar 2 2007, 00:32']
[quote name='=GM=' post='218210' date='Mar 2 2007, 03:30']

Вполне возможно, что в вашей программе достаточно изменить сравнение переменной count3 не с 2, а с числом 100..200, проверьте, я особо не вникал. Ну и деление придётся добавить, а лучше сравнивать с числом 128 или даже 256, тогда и делить не надо будет, просто отбросите младший байт. Вот как-то так...
[/quote]

wait_signal:



sbis pind,T2 ;ждем сигнал с датчика
rjmp wait_signal

inc count3
cpi count3,0x02
brne wait_signal

out SFIOR,zero ; для запуска счетчиков

Знаете GM, содержимое регистра count3, сравниваю с 2 для того, что бы лучше синхронизировать работу счетчиков, т.е. на самом деле мне хотелось, чтобы в тот момент, когда на ножку Т2 пришел сигнал запутить счетчики.Чтобы не оказаться на середине импульса...или в конце...только, кажись просчет...этот цикл проблемы не решает...

Есть вариант и по внешнему прерыванию запускать, по нарастающему фронту...погрешность таже и характер изменения этой погрешности тоже случайный...
=GM=
Цитата(Duduka @ Mar 2 2007, 14:57) *
Знаете GM, содержимое регистра count3, сравниваю с 2 для того, что бы лучше синхронизировать работу счетчиков, т.е. на самом деле мне хотелось, чтобы в тот момент, когда на ножку Т2 пришел сигнал запутить счетчики.Чтобы не оказаться на середине импульса...или в конце...только, кажись просчет...этот цикл проблемы не решает...

Есть вариант и по внешнему прерыванию запускать, по нарастающему фронту...погрешность таже и характер изменения этой погрешности тоже случайный...

Сделайте простую программу без прерываний по следующему алгоритму.

1) Проверить, что уровень входного сигнала нулевой. Если нет, то подождать.

2) Дождаться перехода входного сигнала из 0 в 1. Запустить таймер. Обнулить счётчик периодов M.

3) Дождаться перехода входного сигнала из 1 в 0.

4) Дождаться перехода входного сигнала из 0 в 1. Инкрементировать счётчик периодов M.

5) Если количество периодов равно заданному, остановить таймер. Если нет, перейти к п. 3.

6) Взять значение таймера N и вычислить период по формуле Tx=To*N/M.

Пусть количество периодов М=100. Даже, если у вас будет ошибка в 40 клоков в определении периода входной частоты, что само по себе маловероятно, это надо хорошо постараться, на си скажем писать, или под какой-нибудь микроосью программу запускать, так вот, даже тогда погрешность будет в диапазоне +-0.05 мкс, что вам и требуется. Кстати, таймер можно пустить по прерываниям, ну и добавить пару старших байт к таймеру, а то не хватит ему ёмкости...

Ну вот вам программа минимум(:-).

Потом, когда освоите процесс, переходите на аппаратные средства, которые есть в аврках, icr, например. Потом поймёте, что и таймер не надо включать и выключать, а просто вычитать из нового значения старое значение и запоминать новое на месте старого.

По оформлению постов, чтобы было более читабельно. Старайтесь, чтобы количество тегов <quote> и </quote> было чётным, также важен их порядок, ну и за их вложенностью тоже следите. Угловые скобки, естественно, надо заменить на квадратные.
SasaVitebsk
smile.gif Да... Лоханулся... Измерять N-периодов мне почему-то в голову не пришло. sad.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.