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

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


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

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



Есть некий системный таймер, построенный на аппаратном таймере контроллера и расширенный его программным счетчиком (по переполнению таймера) (пример - 32-ух разрядный счетчик микросекунд системного времени). Задача - чтение на лету его значения. Пока без остановки таймера это сделать у меня не получается (периодически получалась рассинхронизация переполнения счетчика аппаратного таймера и еще не инкрементированного старшего слова).
Но при останове таймера происходит потеря точности счета. Приходится корректировать значение. Т.е. все довольно сложно. Какие еще могут быть варианты?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
=GM=
сообщение Nov 3 2006, 11:19
Сообщение #2


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(Alechin @ Nov 3 2006, 10:50) *
Есть некий системный таймер, построенный на аппаратном таймере контроллера и расширенный его программным счетчиком (по переполнению таймера) (пример - 32-ух разрядный счетчик микросекунд системного времени). Задача - чтение на лету его значения. Пока без остановки таймера это сделать у меня не получается (периодически получалась рассинхронизация переполнения счетчика аппаратного таймера и еще не инкрементированного старшего слова).
Но при останове таймера происходит потеря точности счета. Приходится корректировать значение. Т.е. все довольно сложно. Какие еще могут быть варианты?

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


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Alechin
сообщение Nov 3 2006, 12:46
Сообщение #3


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

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



Цитата
Если переполнение таймера обрабатывается прерыванием, то возможен такой вариант. Запрещаете прерывания, читаете содержимое таймера и остальных байт и сохраняете их в памяти, затем разрешаете прерывания. Теперь спокойно анализируете содержимое таймера, если оно равно 0, то значит было переполнение, следовательно надо добавить перенос к старшим байтам, сохраненным в памяти, ни в коем случае не байты системного времени. Если оно не равно 0, значит переполнение уже учтено прерыванием, просто используете ваше текущее время по своему усмотрению.

Делал такой вариант - все равно проскакивают сбои - ведь пока читали одно из значений могло измениться. И непонятно, когда появился флаг переполнения до чтения таймера или после (у меня чтение значения таймера возможно и в прерывании с более высоким приоритетом, чем прерывание по перепролнению). А понятие "маленькое" растяжимо. Такой вариант уменьшил число сбоев многократно, но не исключил их (я по этому таймеру вычисляю период между метками, подаваемыми на прерывания - до этого раз в пять-шесть секунд были сбои, с данным вариантом раз в 20-30 секунд, с остановом - не дождался сбоя).
Go to the top of the page
 
+Quote Post
CDT
сообщение Nov 3 2006, 13:11
Сообщение #4


Местный
***

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



Цитата(Alechin @ Nov 3 2006, 15:46) *
(я по этому таймеру вычисляю период между метками, подаваемыми на прерывания - до этого раз в пять-шесть секунд были сбои, с данным вариантом раз в 20-30 секунд, с остановом - не дождался сбоя).

А если по подробней о задаче и поискать другой алгоритм (способ,метод) измерения?
- какова тактовая частота контроллера и обязана ли она быть такой?;
- период поступления "меток"?;
- потребная точность измерения (только реально, а не "чем лучше тем лучше"?;
- этот таймер меряет только это или еще для чего-то нужен?;
- остальные таймеры заняты?;
- почему обязательно "на лету"?;
- а что за контроллер то?


--------------------
Опыт - чудесная вещь: легко использовать, можно продать, трудно пропить.
Go to the top of the page
 
+Quote Post
Alechin
сообщение Nov 3 2006, 13:37
Сообщение #5


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

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



Цитата
А если по подробней о задаче и поискать другой алгоритм (способ,метод) измерения?
- какова тактовая частота контроллера и обязана ли она быть такой?;
- период поступления "меток"?;
- потребная точность измерения (только реально, а не "чем лучше тем лучше"?;
- этот таймер меряет только это или еще для чего-то нужен?;
- остальные таймеры заняты?;
- почему обязательно "на лету"?;
- а что за контроллер то?

Контроллер - M128L на 8 МГц. Выше нельзя - 3-ех Вольтовая.
Задача - измерять частоту сигналов по 8-ми (пока 4-ем) входам. Частота - от 1 кГц (экстрим, обычно 100 Гц) до 0.5 Гц т.е. от 10 мсек до 2 сек (пропаданием сигнала считаю его отсутствие в течение 3 сек). При этом по каждому сигналу необходимо вести счет времени нахождения его частоты в заданном диапазоне (5 диапазонов).
Кроме этого еще куча задач - не скоростных (RTC, дисплей, RF), поэтому реально свободен только один 16-ти разрядный таймер.
Сделано так: на таймере (Т1) построен счетчик системного времени: TCNT1 - младшее слово, WORD переменная - старшее слово, инкрементируемое по перемполнению таймера (т.е. DWORD). Таймер тактируется 1 МГц (делитель на 8). Т.е. очень удобно - имеем 32-ух разрядный счетчик микросекунд (системное время, которое можно также использовать для нужд основной программы).
Обработчики прерывания по каждому вх. сигналу просто считывают значение системного времени, вычисляют разницу с запомненным системным временем предыдущего вызова и ВНИМАНИЕ: добавляют эту разницу к счетчику времени нахождения в соотв. диапазоне частот. Все работает четко, много времени не занимает. Но при ошибках в чтении значения системного таймера счетчики времени работы в заданном диапазоне увеличиваются сразу на очень большое число (т.е. разность системных времен при рассинхронизации старшего и младшего слова получается большой). Это сразу заметно: счетчик тикает по секундам - вдруг раз - пара часов добавилась.
Останавливать таймер не очень хорошо - так как при этом накапливается ошибка (получилось 2 мкс на чтение значения таймера). Надо оценить, насколько она велика, может плюноть на нее.
В принципе за секунду имеем 100 * 4 прерывания - минимум 400 чтений таймера - почти 1 мсек.
На измерении частоты (периода) это не должно сказываться - там время накопления ошибки не превышает периода сигнала, а вот при накоплении статистики (времени работы в диапазоне частот) - может сказаться - время накопления статистики - месяцы.

Утомил?
Может я не прав и зря все это замутил?
Go to the top of the page
 
+Quote Post
CDT
сообщение Nov 7 2006, 05:31
Сообщение #6


Местный
***

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



О точности измерения частоты опять промолчали.

Если:
Цитата(Alechin @ Nov 3 2006, 16:37) *
Задача - измерять частоту сигналов по 8-ми (пока 4-ем) входам. Частота - от 1 кГц
то
Цитата
В принципе за секунду имеем 100 * 4 прерывания - минимум 400 чтений таймера - почти 1 мсек.
это не совсем так.

Что бы правильно считать таймер не останавливая надо что бы он не менялся за время чтения.
Минимальная обработка прерывания до считывания как минимум состоит из
Код
push rTmp
in rTmp,sreg
push rTmp
in rTmp,tcntL
in rTmpH,tcntH
, что составляет (10+1...3)*0,125=1,625 мкс, т.е в Вашем случае изменение таймера почти гарантировано (еще не известно, чего туда транслятор напихал).
Простое увеличение К деления прескайлера уменьшит, но не исключит такую вероятность. Соответственно, если во время чтения tcntL в таймере было 01FF, то после чтения tcntH получим 02ff (или 00ff в зависимости от направления счета). Еще противней, если значение будет FFFF
Если до чтения таймера нет переходов (время выполнения кода стабильное) можно проанализировать значение младшего байта и откорректировать считанное значение.

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


--------------------
Опыт - чудесная вещь: легко использовать, можно продать, трудно пропить.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 05:47
Сообщение #7


Гуру
******

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



Цитата(CDT @ Nov 7 2006, 12:31) *
О точности измерения частоты опять промолчали.
Если:
Цитата(Alechin @ Nov 3 2006, 16:37) *

Задача - измерять частоту сигналов по 8-ми (пока 4-ем) входам. Частота - от 1 кГц
то
Цитата
В принципе за секунду имеем 100 * 4 прерывания - минимум 400 чтений таймера - почти 1 мсек.
это не совсем так.
Что бы правильно считать таймер не останавливая надо что бы он не менялся за время чтения.
Минимальная обработка прерывания до считывания как минимум состоит из
Код
push rTmp
in rTmp,sreg
push rTmp
in rTmp,tcntL
in rTmpH,tcntH
, что составляет (10+1...3)*0,125=1,625 мкс, т.е в Вашем случае изменение таймера почти гарантировано.
Простое увеличение К деления прескайлера уменьшит, но не исключит такую вероятность. Соответственно, если во время чтения tcntL в таймере было 01FF, то после чтения tcntH получим 02ff (или 00ff в зависимости от направления счета). Еще противней, если значение будет FFFF
Если до чтения таймера нет переходов (время выполнения кода стабильное) можно проанализировать значение младшего байта и откорректировать считанное значение.
Че то дяденька Вы не в ту степь городите... извиняюсь за выражения.
Вот выдержка из даташита ATmega32 (касается всех AVR с 16-бит ТС): 16-bit Timer/Counter1->
Accessing 16-bit Registers (Page 87): When the low byte of a 16-bit register is read by the CPU, the high byte of the 16-bit register is copied into the temporary register in the same clock cycle as the low byte is read.
То бишь, когда мы читаем младший байт 16-и разрядного регистра, старший байт автоматом копируется в спэшл фо ю сделанный temporary-регистр, при чем, в том же самом цикле, соответственно мы всегда будем иметь нормальное мгновенное значение счетчика ТС1

PS: Си компиляторы об этом знают, то бишь можно делать так: unsigned int cpount = TCNT1, ассемблеру это не ведомо, по этому надо сначала считывать младший байт, за тем старший...


--------------------
Go to the top of the page
 
+Quote Post
CDT
сообщение Nov 7 2006, 06:36
Сообщение #8


Местный
***

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



Цитата(prottoss @ Nov 7 2006, 08:47) *
[ Че то дяденька Вы не в ту степь городите... извиняюсь за выражения.
Вот выдержка из даташита ATmega32 (касается всех AVR с 16-бит ТС): 16-bit Timer/Counter1->
Accessing 16-bit Registers (Page 87): When the low byte of a 16-bit register is read by the CPU, the high byte of the 16-bit register is copied into the temporary register in the same clock cycle as the low byte is read.
То бишь, когда мы читаем младший байт 16-и разрядного регистра, старший байт автоматом копируется в спэшл фо ю сделанный temporary-регистр, при чем, в том же самом цикле, соответственно мы всегда будем иметь нормальное мгновенное значение счетчика ТС1

Да, запамятовал. Эти грабли из другого огорода.
Тогда для начала надо выяснить: таймер неправильно читается или обрабатывается?
И продолжить цитату:
Код
It is important to notice that accessing 16-bit registers are atomic operations. If an interrupt
occurs between the two instructions accessing the 16-bit register, and the interrupt
code updates the temporary register by accessing the same or any other of the 16-bit
Timer Registers, then the result of the access outside the interrupt will be corrupted.
Therefore, when both the main code and the interrupt code update the temporary register,
the main code must disable the interrupts during the 16-bit access.


--------------------
Опыт - чудесная вещь: легко использовать, можно продать, трудно пропить.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 06:54
Сообщение #9


Гуру
******

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



Цитата(CDT @ Nov 7 2006, 13:36) *
Тогда для начала надо выяснить: таймер неправильно читается или обрабатывается? И продолжить цитату:
Код
It is important to notice that accessing 16-bit registers are atomic operations...
Ну дык здесь говорится, что, если есть прерывание, в котором значение счетчика может считываться, считывание значения счетчика в основном цикле программы может быть неверным, так как код в прерывании затрет этот самый временный регистр..


--------------------
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 07:04
Сообщение #10


Гуру
******

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



2 Alechin

Че й то я так и не понял проблемы. Я делаю вот так:

Код
/* системное время */
ULONG g_SysTIME_ms; /* милисекунды */



/* данные датчика */
typedef struct
{
   ULONG Time[2]; /* массив начального и конечного времени  */
   UCHAR Start; /* Индекс стартового времени в массиве времени */
} Pulse_Status_t;

Pulse_Status_t Pulse;



/*****************************************************************************
Обработчик прерывания ТС1 по сравнению TCCR1A
******************************************************************************/
#ifndef __DEBUG__
#pragma optimize = s 9/* оптимизация по скорости */
#endif /* #ifndef __DEBUG__ */



#pragma vector = TIMER1_COMPA_vect
__interrupt void TIMER1_COMPA_isr(void)
{
   g_SysTIME_ms++;
}



/*****************************************************************************
Обработчик прерывания INT0(1,2)
******************************************************************************/
#ifndef __DEBUG__
#pragma optimize = s 9/* оптимизация по скорости */
#endif /* #ifndef __DEBUG__ */



#pragma vector = SPEED_SENSOR_ISR
__interrupt void SPEED_SENS_isr(void)
{
   /* запоминаем текущее время */
    Pulse.Time[Pulse.Start] = MAKEULONG(LOWORD(g_SysTIME_ms),TCNT1);

    /* формируем новый индекс для стартового времени */
    Pulse.Start ^= 1;
}




Таким образом имею время между двумя импульсами, ну а дальше, в основном цикле запрещаю прерывание от INT0 считываю значения START и STOP и поперли дальше. Вместо INT0 можно поставить INT от порта и наворотить еще масса чего, чтоб получить то ж самое от 8-и датчиков


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


дятел
*****

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



2 prottoss
Цитата(prottoss @ Nov 7 2006, 10:04) *
Код
#pragma vector = SPEED_SENSOR_ISR
__interrupt void SPEED_SENS_isr(void)
{
   /* запоминаем текущее время */
    Pulse.Time[Pulse.Start] = MAKEULONG(LOWORD(g_SysTIME_ms),TCNT1);

    /* формируем новый индекс для стартового времени */
    Pulse.Start ^= 1;
}

У Вас точно такая же проблемма в коде что и у автора топика.
Что будет если в этой строке MAKEULONG(LOWORD(g_SysTIME_ms),TCNT1) Вы
считаете значение TCNT1=0 ?
А означать это будет переполнение таймера, то есть Вы получите время на
1ms меньше чем реальное.

2 Alechin
Вы попробовали подправленный код из поста #10 ?
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 14:06
Сообщение #12


Гуру
******

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



Цитата(singlskv @ Nov 7 2006, 20:49) *
2 prottoss
У Вас точно такая же проблемма в коде что и у автора топика.
Что будет если в этой строке MAKEULONG(LOWORD(g_SysTIME_ms),TCNT1) Вы
считаете значение TCNT1=0 ?
А означать это будет переполнение таймера, то есть Вы получите время на
1ms меньше чем реальное.
Да...на самом деле. Значит в функции, возвращающей значение периода необходимо добавить проверку младшего слова на значение ХХ, если меньше, то прибавлять к конечному результату еще одну 1000...


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


дятел
*****

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



Цитата(prottoss @ Nov 7 2006, 17:06) *
Цитата(singlskv @ Nov 7 2006, 20:49) *
2 prottoss
У Вас точно такая же проблемма в коде что и у автора топика.
Что будет если в этой строке MAKEULONG(LOWORD(g_SysTIME_ms),TCNT1) Вы
считаете значение TCNT1=0 ?
А означать это будет переполнение таймера, то есть Вы получите время на
1ms меньше чем реальное.
Да...на самом деле. Значит в функции, возвращающей значение периода необходимо добавить проверку младшего слова на значение ХХ, если меньше, то прибавлять к конечному результату еще одну 1000...

Нет, не в функции возвращающей значение периода, а в прерывании.
В Вашем случае это будет выглядеть примерно так:
Код
#pragma vector = SPEED_SENSOR_ISR
__interrupt void SPEED_SENS_isr(void)
{
   WORD lo = TCNT1;
   WORD hi = LOWORD(g_SysTIME_ms);

   if (((TIFR & (1 << OCF1A)) != 0)&&(lo<1000)) hi++; //  OCR1A/2 =1000

    Pulse.Time[Pulse.Start] = MAKEULONG(hi,lo);
    Pulse.Start ^= 1;
}
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 14:37
Сообщение #14


Гуру
******

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



Цитата(singlskv @ Nov 7 2006, 21:22) *
В Вашем случае это будет выглядеть примерно так:
Код
#pragma vector = SPEED_SENSOR_ISR
__interrupt void SPEED_SENS_isr(void)
{
   WORD lo = TCNT1;
   WORD hi = LOWORD(g_SysTIME_ms);

   if (((TIFR & (1 << OCF1A)) != 0)&&(lo<1000)) hi++; //  OCR1A/2 =1000

    Pulse.Time[Pulse.Start] = MAKEULONG(hi,lo);
    Pulse.Start ^= 1;
}


Да нет уж, тогда делать не так. Лучше уж сделать в прерывании три регистровых переменных и последовательно считать в них значение TC1 и TIFR, потом спокойно все это сохранить в память, а уж разгребать потом в процедуре GetState. По крайней мере можно будет знать сколько тактов ошибки - всего 2



Цитата(singlskv @ Nov 7 2006, 21:34) *
Цитата(=GM= @ Nov 7 2006, 17:24) *

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

Да, это сильное решение a14.gif
Особенно красиво оно будет работать, когда одно внешнее прерывание будет
считывать двумя командами регистр TCNT , и между этими командами возникнет
другое внешнее прерывание blink.gif
Да уж, решение...


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


дятел
*****

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



Цитата(prottoss @ Nov 7 2006, 17:37) *
Цитата(singlskv @ Nov 7 2006, 21:22) *
В Вашем случае это будет выглядеть примерно так:
Код
#pragma vector = SPEED_SENSOR_ISR
__interrupt void SPEED_SENS_isr(void)
{
   WORD lo = TCNT1;
   WORD hi = LOWORD(g_SysTIME_ms);

   if (((TIFR & (1 << OCF1A)) != 0)&&(lo<1000)) hi++; //  OCR1A/2 =1000

    Pulse.Time[Pulse.Start] = MAKEULONG(hi,lo);
    Pulse.Start ^= 1;
}


Да нет уж, тогда делать не так. Лучше уж сделать в прерывании три регистровых переменных и последовательно считать в них значение TC1 и TIFR, потом спокойно все это сохранить в память, а уж разгребать потом в процедуре GetState. По крайней мере можно будет знать сколько тактов ошибки - всего 2

Ну можно конечно TIFR и в память писать, это уже кому как удобно.

А количество тактов ошибки все равно непредсказуемо, например в ситуации
когда одновременно пришло несколько внешних прерываний.
Именно по этой причине идет сравнение (lo<1000).
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 15:23
Сообщение #16


Гуру
******

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



Цитата(singlskv @ Nov 7 2006, 21:56) *
А количество тактов ошибки все равно непредсказуемо, например в ситуации
когда одновременно пришло несколько внешних прерываний.
Именно по этой причине идет сравнение (lo<1000).
Почему это не предсказуемо? У нас не предсказуемо значение софтверного слова счетчика до момента, пока мы не считали TCNT и пока мы не проанализировали OCF1A, потому что с периода входа в прерывание INT и до считывания TIFR счетчик мог переполнится, и, естественно, g_SysTIME_ms, тоже должно быть инкременированно. То что будет после считывания TIFR и TCNT1 нас уже не касается, это будущее состояние . То бишь OCF1A является 16-ым разрядом TCNT1 и нулевым разрядом g_SysTIME_ms. Считывая его и счетчик TCNT мы как раз и имеем полныое представление о программно-аппаратном счетчике. И ошибкf будет всего один такт TCNT1 (я ошибся в прошлом посте, сказав, что 2 такта)


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


дятел
*****

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



Цитата(prottoss @ Nov 7 2006, 18:23) *
Цитата(singlskv @ Nov 7 2006, 21:56) *
А количество тактов ошибки все равно непредсказуемо, например в ситуации
когда одновременно пришло несколько внешних прерываний.
Именно по этой причине идет сравнение (lo<1000).
Почему это не предсказуемо? У нас не предсказуемо значение софтверного слова счетчика до момента, пока мы не считали TCNT и пока мы не проанализировали OCF1A, потому что с периода входа в прерывание INT и до считывания TIFR счетчик мог переполнится, и, естественно, g_SysTIME_ms, тоже должно быть инкременированно. То что будет после считывания TIFR и TCNT1 нас уже не касается, это будущее состояние . То бишь OCF1A является 16-ым разрядом TCNT1 и нулевым разрядом g_SysTIME_ms. Считывая его и счетчик TCNT мы как раз и имеем полныое представление о программно-аппаратном счетчике. И ошибкf будет всего один такт TCNT1 (я ошибся в прошлом посте, сказав, что 2 такта)

Представте себе что одновременно пришло 2 внешних прерывания.
Выполнятся начнет то, которое приоритетнее. А второе прерывание начнет выполняться
только после окончания первого, то есть для второго прерывания ошибка будет равна
времени работы первого прерывания + время входа во второе прерывание до момента
считывания TCNT.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Nov 7 2006, 16:30
Сообщение #18


Гуру
******

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



Цитата(singlskv @ Nov 7 2006, 23:18) *
Представте себе что одновременно пришло 2 внешних прерывания. Выполнятся начнет то, которое приоритетнее. А второе прерывание начнет выполняться только после окончания первого, то есть для второго прерывания ошибка будет равна времени работы первого прерывания + время входа во второе прерывание до момента
считывания TCNT.
Если суммарное время прерываний больше периода счета счетчика TCNT1, тогда конечно - но это 1 МС! Конечно, если писать прерывания в стиле avr123 ), тада да. А если нет, что тогда? У нас счетчик считает в реалтайме, по этому каждое прерывание получит свое значения и только в одном из прерываний будет установлен 16-ый бит софтварного счетчика - OCF1A. Кроме того, что я это представлял, я еще моделировал различные ситуации с данной проблемой в AVRStudio...


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


дятел
*****

Группа: Свой
Сообщений: 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
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 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

Сообщений в этой теме
- Alechin   Как считать значение аппаратно-программного таймера...   Nov 3 2006, 10:50
|- - singlskv   Покажите свой код. Попробуем подправить.   Nov 3 2006, 15:01
||- - Alechin   Цитата(singlskv @ Nov 3 2006, 18:01) Пока...   Nov 3 2006, 19:37
||- - singlskv   Цитата(Alechin @ Nov 3 2006, 22:37) А чег...   Nov 3 2006, 20:24
|- - Alechin   ЦитатаЧе й то я так и не понял проблемы. Я делаю в...   Nov 7 2006, 12:34
||- - prottoss   Цитата(Alechin @ Nov 7 2006, 19:34) Отлич...   Nov 7 2006, 12:54
||- - =GM=   Цитата(Alechin @ Nov 7 2006, 12:34) У мен...   Nov 7 2006, 14:24
||- - singlskv   Цитата(=GM= @ Nov 7 2006, 17:24) Попробуй...   Nov 7 2006, 14:34
||- - =GM=   Цитата(singlskv @ Nov 7 2006, 14:34) Цита...   Nov 7 2006, 15:36
|- - singlskv   Цитата(prottoss @ Nov 7 2006, 19:52) Цита...   Nov 7 2006, 17:02
|- - prottoss   Цитата(singlskv @ Nov 8 2006, 00:02) Совт...   Nov 7 2006, 17:18
|- - singlskv   Цитата(prottoss @ Nov 7 2006, 20:18) Мне ...   Nov 7 2006, 18:41
|- - prottoss   Цитата(singlskv @ Nov 8 2006, 01:41) Вы о...   Nov 7 2006, 19:06
|- - singlskv   Цитата(prottoss @ Nov 7 2006, 22:06) КодU...   Nov 7 2006, 19:55
|- - prottoss   Цитата(singlskv @ Nov 8 2006, 02:55) Толь...   Nov 7 2006, 20:14
|- - singlskv   Цитата(prottoss @ Nov 7 2006, 23:14) Хм, ...   Nov 7 2006, 20:38
|- - prottoss   Цитата(singlskv @ Nov 8 2006, 03:38) Цита...   Nov 7 2006, 21:06
- - singlskv   Цитата(Alechin @ Nov 3 2006, 13:50) Есть ...   Nov 3 2006, 11:20
- - xemul   имхо, при входе в п/п обработки прерываний по вход...   Nov 3 2006, 16:34
- - prottoss   Может быть вот так? Код__interrupt void SPEED_SENS...   Nov 7 2006, 14:48
- - prottoss   Продолжая свой пост, скажу, что счетчик TCNT1 инкр...   Nov 7 2006, 16:10
- - ARIM   Цитата(Alechin @ Nov 3 2006, 13:50) Есть ...   Nov 8 2006, 07:00
- - ARIM   Цитата(Alechin @ Nov 3 2006, 13:50) Какие...   Nov 8 2006, 07:44
|- - prottoss   Цитата(ARIM @ Nov 8 2006, 14:44) Цитата(A...   Nov 8 2006, 08:09
|- - ARIM   Цитата(prottoss @ Nov 8 2006, 11:09) Цита...   Nov 8 2006, 08:46
|- - defunct   Цитата(ARIM @ Nov 8 2006, 11:46) или возь...   Nov 9 2006, 17:09
|- - prottoss   Цитата(ARIM @ Nov 8 2006, 15:46) или возь...   Nov 9 2006, 17:40
|- - ARIM   Цитата(prottoss @ Nov 9 2006, 20:40) Цита...   Nov 10 2006, 06:51
|- - prottoss   Цитата(ARIM @ Nov 10 2006, 13:51) Цитата(...   Nov 10 2006, 12:40
|- - ARIM   Цитата(prottoss @ Nov 10 2006, 15:40) Цит...   Nov 10 2006, 12:59
|- - prottoss   Цитата(ARIM @ Nov 10 2006, 19:59) АРМ был...   Nov 10 2006, 13:19
- - prottoss   Вчера проверил все то, что выкладывал выше на трех...   Nov 9 2006, 16:49
- - Alechin   Цитата(prottoss @ Nov 9 2006, 19:49) А чт...   Nov 9 2006, 19:00
- - singlskv   Цитата(Alechin @ Nov 9 2006, 22:00) Цитат...   Nov 9 2006, 19:27
- - prottoss   Цитата(singlskv @ Nov 10 2006, 02:27) Цит...   Nov 10 2006, 12:13


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

 


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


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