реклама на сайте
подробности

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Как считать значение аппаратно-программного таймера...
singlskv
сообщение Nov 7 2006, 16:47
Сообщение #31


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Nov 7 2006, 19:30) *
У нас счетчик считает в реалтайме, по этому каждое прерывание получит свое значения и только в одном из прерываний будет установлен 16-ый бит софтварного счетчика - OCF1A.

Нет, OCF1A будет выставлен во ВСЕХ внешних прерываниях, если за время
выполнения одного прерывания возникнет флаг другого, и т.д.
Дело в том, что у внешних прерываний выше приоритет, и пока
не выполнятся ВСЕ ждущие высокоуровневые прерывания, прерывание таймера по
сравнению не отработает.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 16:52
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(singlskv @ Nov 7 2006, 23:47) *
Нет, OCF1A будет выставлен во ВСЕХ внешних прерываниях, если за время
выполнения одного прерывания возникнет флаг другого, и т.д.
Дело в том, что у внешних прерываний выше приоритет, и пока
не выполнятся ВСЕ ждущие высокоуровневые прерывания, прерывание таймера по
сравнению не отработает.
Согласен, если в первом внешнем прерывании выставится флаг OCF1A, то это скажет всем последующим, что софт-слово времени надо скорректировать на 1 - и это будет правильно


--------------------
Go to the top of the page
 
+Quote Post
singlskv
сообщение Nov 7 2006, 17:02
Сообщение #33


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Nov 7 2006, 19:52) *
Цитата(singlskv @ Nov 7 2006, 23:47) *
Нет, OCF1A будет выставлен во ВСЕХ внешних прерываниях, если за время
выполнения одного прерывания возникнет флаг другого, и т.д.
Дело в том, что у внешних прерываний выше приоритет, и пока
не выполнятся ВСЕ ждущие высокоуровневые прерывания, прерывание таймера по
сравнению не отработает.
Согласен, если в первом внешнем прерывании выставится флаг OCF1A, то это скажет всем последующим, что софт-слово времени надо скорректировать на 1 - и это будет правильно

Совт-слово можно корректировать прямо в прерывании со сбросом флага OCF1A (TOV1),
тогда в последующих за ним прерываниях корректировка не понадобится.

P.S только имейте ввиду, что сейчас кое-кто придет и скажет что так делать низя...
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 17:18
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(singlskv @ Nov 8 2006, 00:02) *
Совт-слово можно корректировать прямо в прерывании со сбросом флага OCF1A (TOV1), тогда в последующих за ним прерываниях корректировка не понадобится.
P.S только имейте ввиду, что сейчас кое-кто придет и скажет что так делать низя...
Мне все равно, кто счас придет... Он не пуп земли, и послать его далеко мне очень легко...

По поводу корректировки в прерывании - я сторонник делать все что можно за пределами прерывания, а прерывание должно быстро отработать и освободить место другому, что бы не было пауз в 1 мс)))...

Дак я не понял, с моей идеей Вы согласны, или нет? Так, как я предлагаю - и волки сыты и овцы целы). Дело в том, что у меня счас тоже проект, в котором МК должен мерить импульсы от датчика скорости((( В ТЗ - от ИНТ0 и с точностю десятки микросекунд. А ТС1 выполняет роль системных часов. Вот и изгаляюсь тоже. Но похоже что, то что я придумал, работает - опять же, если суммарное время поступивших внешних прерываний не превысит 1 мс...

И я не пойму, а что делать низя? Что вы имели в виду?


--------------------
Go to the top of the page
 
+Quote Post
singlskv
сообщение Nov 7 2006, 18:41
Сообщение #35


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Nov 7 2006, 20:18) *
Мне все равно, кто счас придет... Он не пуп земли, и послать его далеко мне очень легко...
Он и так далеко, Oxford UK smile.gif
Цитата
По поводу корректировки в прерывании - я сторонник делать все что можно за пределами прерывания, а прерывание должно быстро отработать и освободить место другому, что бы не было пауз в 1 мс)))...

Ну дык это всего лишних тактов 10-15
Цитата
Дак я не понял, с моей идеей Вы согласны, или нет? Так, как я предлагаю - и волки сыты и овцы целы).

Вы о сохранении TIFR в памяти или о сохраниени TCNT и TIFR в регистрах в соседних командах ?
Если первое, то согласен, только сравниваем младшее слово с 1000 при коррекции.
А если второе, то ИМХО это нам ничего не дает.
Представте себе что во время выполнения не относящегося к нашему делу прерывания
происходит запрос на прерывание от таймера, а затем через какое-то время(пока еще
не закончилось другое прерывание) происходит запрос на прерывание INT.
Когда закончится другое прерывание, первым будет обработанно INT, при этом
значение в TCNT будет уже довольно большим, а флаг OCF1A, будет выставлен.
А теперь другая ситуация.
Представте себе что во время выполнения не относящегося к нашему делу прерывания
происходит запрос на прерывание INT.После окончания прерывания, начнется обработчик INT,
но при считывании значений мы получили TCNT=1999 и выставленный флаг OCF1A.

В каком из этих двух вариантов Вы будете производить коррекцию, а в каком нет ?

Может быть все-таки так надежнее:
if (((TIFR & (1 << OCF1A)) != 0)&&(lo<1000)) hi++; // OCR1A/2 =1000
Кстати, точно такуюже проверку мы можем делать и с данными сохранеными в памяти.

Цитата
Дело в том, что у меня счас тоже проект, в котором МК должен мерить импульсы от датчика скорости((( В ТЗ - от ИНТ0 и с точностю десятки микросекунд. А ТС1 выполняет роль системных часов.

В таком варианте, когда нужно мерить только от одного датчика, значительно проще и
надежнее пользоваться пином ICP1 и прерыванием захвата таймера, правда коррекцию
старшего слова все равно необходимо предусмотреть.
Цитата
И я не пойму, а что делать низя? Что вы имели в виду?

Ну я как раз считаю что можно (корректировать старшее слово системного таймера с
одновременным сбросом флага OCF1A(TOV1) в любом месте программы в том числе
и в других прерываниях, единственное ограничение, запрет всех прерываний на
время корректировки.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 19:06
Сообщение #36


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(singlskv @ Nov 8 2006, 01:41) *
Вы о сохранении TIFR в памяти или о сохраниени TCNT и TIFR в регистрах в соседних командах ?
Если первое, то согласен, только сравниваем младшее слово с 1000 при коррекции.
А если второе, то ИМХО это нам ничего не дает.
Я о сохранении TIFR и TCNT в соседних командах , а потом в памяти - дальнейший анализ в основном цикле

Цитата(singlskv @ Nov 8 2006, 01:41) *
Представте себе что во время выполнения не относящегося к нашему делу прерывания
происходит запрос на прерывание от таймера, а затем через какое-то время(пока еще
не закончилось другое прерывание) происходит запрос на прерывание INT.
Когда закончится другое прерывание, первым будет обработанно INT, при этом
значение в TCNT будет уже довольно большим, а флаг OCF1A, будет выставлен.
Нам важно, если делать, как я, только одно значение TCNT - 1999. Если флаг OCF1A - установлен, мы будем в любом случае корректировать софт-слово, если, при этом значение счетчика 1999, мы будем корректировать (в сохраненной переменной) - устанавливать в 0
Цитата(singlskv @ Nov 8 2006, 01:41) *
А теперь другая ситуация.
Представте себе что во время выполнения не относящегося к нашему делу прерывания
происходит запрос на прерывание INT.После окончания прерывания, начнется обработчик INT,
но при считывании значений мы получили TCNT=1999 и выставленный флаг OCF1A.

То же самое, что и выше



Вот код, который я набросал для процедуры считывания периода:

Код
UINT SPEED_SENS_GetState(void)
{
   /* запрещаем прерывание */
   GICR &= ~SPEED_SENSOR_ISR_ENABLE;

    /* считываем значения */
    register ULONG stop = Pulse.Time[Pulse.Start ^ 1];
    register ULONG start = Pulse.Time[Pulse.Start];
    register UCHAR tifr_stop = Pulse.TIFR_reg[Pulse.Start ^ 1];
    register UCHAR tifr_start = Pulse.TIFR_reg[Pulse.Start];

    /* разрешаем прерывание */
    GICR |= SPEED_SENSOR_ISR_ENABLE;

    /* корректируем результат по состоянию флага OCF1A
    на момент считывания значений времени */
    if(tifr_stop & (1 << OCF1A))
    {
       stop += 65536;
        if(SYSTIMER_COMPARE_VAL == LOWORD(stop))
           stop -= SYSTIMER_COMPARE_VAL;
    }
    if(tifr_start & (1 << OCF1A))
    {
       start += 65536;
        if(SYSTIMER_COMPARE_VAL == LOWORD(start))
           start -= SYSTIMER_COMPARE_VAL;
    }

    /* считаем разность (STOP - START)*/
    stop = (LOWORD(stop) >> 1) + /* преобразуем в мкс */
       (HIWORD(stop) * 1000);
start = (LOWORD(start) >> 1) + /* преобразуем в мкс */
       (HIWORD(start) * 1000);

    /* преобразуем в Герцы и возвращаем */
    return (UINT)(((LONGLONG)10000000) / abs(stop - start));
}




Цитата(singlskv @ Nov 8 2006, 01:41) *
Цитата

Дело в том, что у меня счас тоже проект, в котором МК должен мерить импульсы от датчика скорости((( В ТЗ - от ИНТ0 и с точностю десятки микросекунд. А ТС1 выполняет роль системных часов.

В таком варианте, когда нужно мерить только от одного датчика, значительно проще и
надежнее пользоваться пином ICP1 и прерыванием захвата таймера, правда коррекцию
старшего слова все равно необходимо предусмотреть.
Не факт, что завтра мне не дадут задание довесить еще один датчик... или 8 на весь порт...


--------------------
Go to the top of the page
 
+Quote Post
singlskv
сообщение Nov 7 2006, 19:55
Сообщение #37


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Nov 7 2006, 22:06) *
Код
UINT SPEED_SENS_GetState(void)
{
   /* запрещаем прерывание */
   GICR &= ~SPEED_SENSOR_ISR_ENABLE;

    /* считываем значения */
    register ULONG stop = Pulse.Time[Pulse.Start ^ 1];
    register ULONG start = Pulse.Time[Pulse.Start];
    register UCHAR tifr_stop = Pulse.TIFR_reg[Pulse.Start ^ 1];
    register UCHAR tifr_start = Pulse.TIFR_reg[Pulse.Start];

    /* разрешаем прерывание */
    GICR |= SPEED_SENSOR_ISR_ENABLE;

    /* корректируем результат по состоянию флага OCF1A
    на момент считывания значений времени */
    if(tifr_stop & (1 << OCF1A))
    {
       stop += 65536;
        if(SYSTIMER_COMPARE_VAL == LOWORD(stop))
           stop -= SYSTIMER_COMPARE_VAL;
    }
    if(tifr_start & (1 << OCF1A))
    {
       start += 65536;
        if(SYSTIMER_COMPARE_VAL == LOWORD(start))
           start -= SYSTIMER_COMPARE_VAL;
    }

    /* считаем разность (STOP - START)*/
    stop = (LOWORD(stop) >> 1) + /* преобразуем в мкс */
       (HIWORD(stop) * 1000);
start = (LOWORD(start) >> 1) + /* преобразуем в мкс */
       (HIWORD(start) * 1000);

    /* преобразуем в Герцы и возвращаем */
    return (UINT)(((LONGLONG)10000000) / abs(stop - start));
}

Ну так вроде будет работать,
просто сравнение в прерывании с cерединой диапазона счетчика
таймера - это более общий подход, который работает и в варианте
использования ICP1 и прерывания захвата таймера.
Только вот это я недопонял:
Код
    if(tifr_stop & (1 << OCF1A))
    {
       stop += 65536;
        if(SYSTIMER_COMPARE_VAL == LOWORD(stop))
           stop -= SYSTIMER_COMPARE_VAL;
    }

Почему мы добавляем 65536, а вычитаем только 1999 blink.gif
Хотя это конечно детали. smile.gif
Цитата
Не факт, что завтра мне не дадут задание довесить еще один датчик... или 8 на весь порт...

Ну тогда Вам и автору данного топика следует рассмотреть следующий вариант:
1. Подключаем датчики к соответствующим INTx.
2. Каждый пин INTx через диод подключаем к ICP1.
3. В каждом прерывании INTx считываем значение ICR1 вместо TCNT1.
4. Делаем корректировку по середине диапазона(можно в обработчике INTx, а можно и
в основном цикле, кому как больше нравится)

Понятно, что при перекрытии прерываний считанное из ICR1 значение будет отличаться
от реального момента прерывания, но:
1. Такой подход даст нам более надежный имунитет от "других прерываний"
2. Общая (средняя) ошибка вычисления длительностей при
перекрытии прерываний существенно уменьшится.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 20:14
Сообщение #38


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(singlskv @ Nov 8 2006, 02:55) *
Только вот это я недопонял:
Код
    if(tifr_stop & (1 << OCF1A))
    {
       stop += 65536;
        if(SYSTIMER_COMPARE_VAL == LOWORD(stop))
           stop -= SYSTIMER_COMPARE_VAL;
    }

Почему мы добавляем 65536, а вычитаем только 1999 blink.gif
Хотя это конечно детали. smile.gif


Хм, я же объясняю, если флаг установлен, к СТАРШЕМУ слову прибавляем 1

Код
stop += 65536;
Если число в TCNT = 1999, TCNT = 0

Код
if(SYSTIMER_COMPARE_VAL == LOWORD(stop))
           stop -= SYSTIMER_COMPARE_VAL;

Цитата
Ну тогда Вам и автору данного топика следует рассмотреть следующий вариант:
1. Подключаем датчики к соответствующим INTx.
2. Каждый пин INTx через диод подключаем к ICP1.
3. В каждом прерывании INTx считываем значение ICR1 вместо TCNT1.
4. Делаем корректировку по середине диапазона(можно в обработчике INTx, а можно и
в основном цикле, кому как больше нравится)

Понятно, что при перекрытии прерываний считанное из ICR1 значение будет отличаться
от реального момента прерывания, но:
1. Такой подход даст нам более надежный имунитет от "других прерываний"
2. Общая (средняя) ошибка вычисления длительностей при
перекрытии прерываний существенно уменьшится.
Хрен редьки не слаще: Во первых диоды денех стоять, во вторых ловить флаг переполнения хардварного счетчика тоже нада


--------------------
Go to the top of the page
 
+Quote Post
singlskv
сообщение Nov 7 2006, 20:38
Сообщение #39


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(prottoss @ Nov 7 2006, 23:14) *
Хм, я же объясняю, если флаг установлен, к СТАРШЕМУ слову прибавляем 1

Код
stop += 65536;
Если число в TCNT = 1999, TCNT = 0

Код
if(SYSTIMER_COMPARE_VAL == LOWORD(stop))
           stop -= SYSTIMER_COMPARE_VAL;

Да, я забыл что у Вас так хитро организован счетчик.

Цитата
Хрен редьки не слаще: Во первых диоды денех стоять, во вторых ловить флаг переполнения хардварного счетчика тоже нада

Насчет диодов, это я слегка погорячился, там внешнюю логику надо ставить,
но зато, можно получать 8 каналов, и при этом почти без ошибки.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 21:06
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(singlskv @ Nov 8 2006, 03:38) *
Цитата
Хрен редьки не слаще: Во первых диоды денех стоять, во вторых ловить флаг переполнения хардварного счетчика тоже нада

Насчет диодов, это я слегка погорячился, там внешнюю логику надо ставить,
но зато, можно получать 8 каналов, и при этом почти без ошибки.
Вот-вот, к тому же плата уже давно готовая и в серии...


--------------------
Go to the top of the page
 
+Quote Post
ARIM
сообщение Nov 8 2006, 07:00
Сообщение #41


Частый гость
**

Группа: Свой
Сообщений: 94
Регистрация: 14-04-05
Из: Россия
Пользователь №: 4 130



Цитата(Alechin @ Nov 3 2006, 13:50) *
Есть некий системный таймер, построенный на аппаратном таймере контроллера и расширенный его программным счетчиком (по переполнению таймера) (пример - 32-ух разрядный счетчик микросекунд системного времени). Задача - чтение на лету его значения.

Попробуйте защелкивать значение таймера в ICP регистр. не прочитал всю тему было об этом уже.

Сообщение отредактировал ARIM - Nov 8 2006, 07:06
Go to the top of the page
 
+Quote Post
ARIM
сообщение Nov 8 2006, 07:44
Сообщение #42


Частый гость
**

Группа: Свой
Сообщений: 94
Регистрация: 14-04-05
Из: Россия
Пользователь №: 4 130



Цитата(Alechin @ Nov 3 2006, 13:50) *
Какие еще могут быть варианты?

Каскадировать два 8-ми битных и один 16-ти битный таймеры. получим аппаратный 32-х разрядный.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 8 2006, 08:09
Сообщение #43


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(ARIM @ Nov 8 2006, 14:44) *
Цитата(Alechin @ Nov 3 2006, 13:50) *

Какие еще могут быть варианты?

Каскадировать два 8-ми битных и один 16-ти битный таймеры. получим аппаратный 32-х разрядный.
...да, а если они все у Вас заняты разбейте плату молотком...


--------------------
Go to the top of the page
 
+Quote Post
ARIM
сообщение Nov 8 2006, 08:46
Сообщение #44


Частый гость
**

Группа: Свой
Сообщений: 94
Регистрация: 14-04-05
Из: Россия
Пользователь №: 4 130



Цитата(prottoss @ Nov 8 2006, 11:09) *
Цитата(ARIM @ Nov 8 2006, 14:44) *
Цитата(Alechin @ Nov 3 2006, 13:50) *

Какие еще могут быть варианты?

Каскадировать два 8-ми битных и один 16-ти битный таймеры. получим аппаратный 32-х разрядный.
...да, а если они все у Вас заняты разбейте плату молотком...

или возьмите LPC21xx.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 9 2006, 16:49
Сообщение #45


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Вчера проверил все то, что выкладывал выше на трех ИНТах, работает как часы, погрешность (я не использовал FLOAT в вычислениях) +-1 Гц.
А что автор топика примолк, решил проблемцу так же, как я предлагал, или еще че получше напридумывал?


--------------------
Go to the top of the page
 
+Quote Post

4 страниц V  < 1 2 3 4 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 08:57
Рейтинг@Mail.ru


Страница сгенерированна за 0.01512 секунд с 7
ELECTRONIX ©2004-2016