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

 
 
> Как считать значение аппаратно-программного таймера...
Alechin
сообщение Nov 3 2006, 10:50
Сообщение #1


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

Группа: Свой
Сообщений: 158
Регистрация: 27-06-05
Из: Химки, Моск.обл.
Пользователь №: 6 334



Есть некий системный таймер, построенный на аппаратном таймере контроллера и расширенный его программным счетчиком (по переполнению таймера) (пример - 32-ух разрядный счетчик микросекунд системного времени). Задача - чтение на лету его значения. Пока без остановки таймера это сделать у меня не получается (периодически получалась рассинхронизация переполнения счетчика аппаратного таймера и еще не инкрементированного старшего слова).
Но при останове таймера происходит потеря точности счета. Приходится корректировать значение. Т.е. все довольно сложно. Какие еще могут быть варианты?
Go to the top of the page
 
+Quote Post
4 страниц V  < 1 2 3 4 >  
Start new topic
Ответов (30 - 44)
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
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


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


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