Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Менеджер прерываний
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
ivainc1789
В задаче на ATmega16 есть необходимость посчитать кол-во импульсов на пине T1 за калиброванный интервал времени. Для этого организуется таймер1 как 24р. счетчик импульсов и необходимо сделать калиброванный интервал времени. Есть два подхода:
1. Сделать интервал без дополнительных ресурсов, запретив все прерывания и разрешив только от таймера 1 для инкремента 8р. старшего байта 24р. таймера по его переполнению.
2. Использовать другой таймер для "изготовления" калиброванного интервала.
3. Ваш вариант.

Интерес пока представляет первый вариант. ИМХО, в AVR очень тяжело запретить на небольшое время все прерывания, разрешив некоторые. Нужно мудрить некий менеджер прерываний, для чего вручную: сохранять статус текущих, потом все запрещать, потом разрешать необходимые. Все это как-то коряво и долго... Есть ли более простой подход для решения задачи?
alexander55
Цитата(ivainc1789 @ Sep 7 2007, 14:41) *
В задаче на ATmega16 есть необходимость посчитать кол-во импульсов на пине T1 за калиброванный интервал времени. Для этого организуется таймер1 как 24р. счетчик импульсов и необходимо сделать калиброванный интервал времени. Есть два подхода:
1. Сделать интервал без дополнительных ресурсов, запретив все прерывания и разрешив только от таймера 1 для инкремента 8р. старшего байта 24р. таймера по его переполнению.
2. Использовать другой таймер для "изготовления" калиброванного интервала.
3. Ваш вариант.

Интерес пока представляет первый вариант. ИМХО, в AVR очень тяжело запретить на небольшое время все прерывания, разрешив некоторые. Нужно мудрить некий менеджер прерываний, для чего вручную: сохранять статус текущих, потом все запрещать, потом разрешать необходимые. Все это как-то коряво и долго... Есть ли более простой подход для решения задачи?

1.Используйте режим захвата
2.Таймер 1 подсчета считает по кругу импульсы, а по прерыванию от другого таймера считывается содержимое Таймера1. Затем высчитываеие разность спредыдущим съемом.
Выбирайте сами.
ivainc1789
Цитата(alexander55 @ Sep 7 2007, 15:24) *
1.Используйте режим захвата

Жаль, но источник импульсов подключен к пину T1 и плата уже сделана и собрана, поэтому несколько неудобно использовать режим захвата. ИМХО, второй вариант в данном случае предпочтительней. Спасибо.
alexander55
Цитата(ivainc1789 @ Sep 7 2007, 16:05) *
Жаль, но источник импульсов подключен к пину T1 и плата уже сделана и собрана, поэтому несколько неудобно использовать режим захвата. ИМХО, второй вариант в данном случае предпочтительней. Спасибо.

Я стараюсь вначале подумать, а потом сделать (мы все разные).
defunct
Цитата
2. Использовать другой таймер для "изготовления" калиброванного интервала.

Я бы остановился на этом варианте.
Только это у меня был бы не "калибровочный" таймер, а системный таймер, который бы отмерял интервалы в 1ms или 10ms.

Цитата
Нужно мудрить некий менеджер прерываний, для чего вручную..

Все зависит от точности которую вы хотите получить.
Не исключен вариант, что и без "мудрежа", с разрешенными всеми прерываниями получится приемлемая точность.
Coolrunner
А зачем режим захвата? Т1 - это нога внешнего тактирования таймера, вот и считайте этим таймером на здоровьеsmile.gif. А интервал отмеряйте другим, и по прерыванию от него, считывайте значение счетчика.
ivainc1789
Цитата(Coolrunner @ Sep 8 2007, 22:15) *
А зачем режим захвата? Т1 - это нога внешнего тактирования таймера, вот и считайте этим таймером на здоровьеsmile.gif. А интервал отмеряйте другим, и по прерыванию от него, считывайте значение счетчика.

Сделал уже... smile.gif Все отлично работает!!! На ноге ICP другой модуль сидит, там оно нужнее... smile.gif
ivainc1789
И все же задам еще один вопрос здесь, чтобы не плодить отдельные топики. Теперь задача ставится несколько по-другому: необходимо считать длительность ОДНОГО периода на пине T1. Fbq = 11059200 Гц, на входе период 1.6 мкс. Код:
Код
  __disable_interrupt();
  do {} while (PIN(T1IN));// синхронизация с сигналом (фронт 01)  
    do {} while (!PIN(T1IN));
  Tmr1Start;
  do {} while (PIN(T1IN));do {} while (!PIN(T1IN));// один период на пине
  Tmr1Stop;
  __enable_interrupt();

На первый взгляд, должны в таймере получить Tin/(1/Fbq) = 1.6e-6*11059200 = 17.69, но на самом деле получаем 21, иногда 24. Источник сигнала - автогенератор. Вы скажете, что автогенератор нестабилен? Но чем тогда объяснить тот факт, что примерно на 10 исходов 21 приходится один 24. И НИКАКИХ ДРУГИХ РЕЗУЛЬТАТОВ за все время измерений/наблюдений!!! Есть ли здесь тонкости?
Хочу сразу оговориться, что не собираюсь измерять такой период таким образом! Это просто отдельный вопрос не нашедший объяснения, не более того!
=AVR=
Все предельно просто - в зависимости от того, на какую фазу цикла ожидания придется физический фронт, и будет плясать "измеренное" время. Чтобы этого не было, следует использовать Capture
defunct
Цитата(ivainc1789 @ Sep 9 2007, 14:08) *
Есть ли здесь тонкости?

Есть, тут уже действуют времена исполнения команд.
Поэтому лучше ловить не длительность одного импульса, а длительность нескольких идущих подряд импульсов, например 100, результирующую длительность делить на 100.
alexander55
Цитата(defunct @ Sep 9 2007, 17:53) *
Есть, тут уже действуют времена исполнения команд.
Поэтому лучше ловить не длительность одного импульса, а длительность нескольких идущих подряд импульсов, например 100, результирующую длительность делить на 100.

Я согласен, но с одной оговоркой. Если у автора топика разовое или конечное измерение, то это некорректно. Автору видней.
defunct
Цитата(alexander55 @ Sep 10 2007, 09:01) *
Если у автора топика разовое или конечное измерение, то это некорректно. Автору видней.

Бесспорно
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.