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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Работа таймера TMR0 (PIC16)
xemul
сообщение May 29 2011, 17:28
Сообщение #31



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SKov @ May 29 2011, 20:48) *
Предзагрузка делается не так: TMR0 = TMR0 + 100; а вот так TMR0 = 100;

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

Цитата(sargein @ May 29 2011, 21:14) *
Код
volatile unsigned char tmp100;
...

Go to the top of the page
 
+Quote Post
sargein
сообщение May 29 2011, 17:51
Сообщение #32


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



xemul, согласен, забыл про это sm.gif
Go to the top of the page
 
+Quote Post
SKov
сообщение May 29 2011, 18:01
Сообщение #33


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(xemul @ May 29 2011, 21:28) *
Первый вариант позволяет таки учесть время, прошедшее с момента возникновения прерывания до момента собственно его обработки.

Не совсем так, т.к. при загрузке TMR0 сбрасывается прескалер.
Тогда уж логично сбрасывать не только прескалер, а и сам основной счетчик.
В этом случае мы как раз и получаем второй вариант.Ну, на самом деле это в принципе одно и то же (первый и второй вариант). Просто второй вариант действительно предзагрузка, а первый - предсуммирование или преддобавка, что звучит уж совсем коряво wink.gif
Относительно "равномерно размазанного" интервала я не понял.
Если предзагрузку ставить вначале ППОП (до ветвлений и других участков ППОП с неопределенным временем исполнения),
то никакой "размазаности" не будет. Будет четкий период.
Go to the top of the page
 
+Quote Post
xemul
сообщение May 29 2011, 19:00
Сообщение #34



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SKov @ May 29 2011, 22:01) *
Не совсем так, т.к. при загрузке TMR0 сбрасывается прескалер.
Тогда уж логично сбрасывать не только прескалер, а и сам основной счетчик.
В этом случае мы как раз и получаем второй вариант.Ну, на самом деле это в принципе одно и то же (первый и второй вариант). Просто второй вариант действительно предзагрузка, а первый - предсуммирование или преддобавка, что звучит уж совсем коряво wink.gif
Относительно "равномерно размазанного" интервала я не понял.
Если предзагрузку ставить вначале ППОП (до ветвлений и других участков ППОП с неопределенным временем исполнения),
то никакой "размазаности" не будет. Будет четкий период.

Рассмотрите случай с несколькими источниками прерываний, когда прерывание от таймера возникает после проверки его флага, но внутри ППОП.
Сброс прескейлера, в предположении, что он равномерно размазан на все состояния прескейлера, учитывается совершенно отдельно - типа "TMR0 += TMR0_PRESET + 1;" (или, ещё точнее "TMR0 += TMR0_PRESET + 0.5;" - т.е. 1 добавляется через раз).
Go to the top of the page
 
+Quote Post
SKov
сообщение May 29 2011, 19:46
Сообщение #35


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(xemul @ May 29 2011, 23:00) *
Рассмотрите случай с несколькими источниками прерываний, когда прерывание от таймера возникает после проверки его флага, но внутри ППОП.
Сброс прескейлера, в предположении, что он равномерно размазан на все состояния прескейлера, учитывается совершенно отдельно - типа "TMR0 += TMR0_PRESET + 1;" (или, ещё точнее "TMR0 += TMR0_PRESET + 0.5;" - т.е. 1 добавляется через раз).

Случай нескольких прерываний можно заменить, например, случаем, когда в основной программе есть куски с запретом прерываний.
Другими словами, мы говорим о случае, когда время реакции на прерывания непредсказуемо.
В этом случае надо смотреть на конкретный код программы. Если задержка реакции укладывается в несколько "тиков" таймера, тогда суммирование может нас спасти и обеспечить точность периода прерываний в пределах одного тика таймера.
А если задержка может быть большая, то вообще теряется смысл предустановки.
Можно рассмотреть и другой случай. Пусть задержка лежит в районе одного тика таймера плюс-минус несколько тактов Fosc/4.
В этом случае прибавление константы дает нам "дрожание" периода прерываний примерно на величину одного тика таймера.
А если мы выполняем загрузку таймера константой, то "дрожание" периода имеет величину всего лишь нескольких тактов Fosc/4.
Так что бывают случаи, когда загрузка лучше суммирования wink.gif

Go to the top of the page
 
+Quote Post
xemul
сообщение May 30 2011, 06:51
Сообщение #36



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SKov @ May 29 2011, 23:46) *
Так что бывают случаи, когда загрузка лучше суммирования wink.gif

Я могу обосновать чиста математически, что загрузка в любом случае будет не лучше суммирования в смысле получения минимальной средней (или средней квадратичной - без разницы) ошибки формирования некоторого периода на любом числе периодов.
Случай, когда загрузка будет равна по ошибке суммированию, вообще один - прерывания только от таймера с минимальным прескейлером, никаких критических секций в коде.
Из очевидных минусов загрузки - собственно загружаемую константу придётся подрихтовать ручками, чтобы учесть задержку от возникновения прерывания до момента загрузки, или вставлять каким-либо образом этот учёт в считалку препроцессора. При суммировании оно учитывается само, и остаётся только решить, компенсировать ли сброс прескейлера или и так сойдёт.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 30 2011, 07:29
Сообщение #37


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Спасибо за гору инфы! Еще бы переварить... rolleyes.gif
Добавил квалификатор volatile а всем переменным, используемым в ППОП. От предзагрузки таймера временно отказался, пока не разберусь, что происходит. Пока мне точность не нужна.
Никак не докопаюсь, для чего нужен
Код
if (T0IF){}

ППОП и так вызывается при появлении прерывания по переполнению TMR0.
Также не пойму, как в некоторых случаях работает оператор while. В книге по микроС сказано:
Цитата
Ключевое слово while используется для организации условных циклов. Синтаксис оператора while:
while (expression) statement. Оператор statement (тело цикла) выполняется раз за разом пока величина выражения expression не станет ложной. Проверка производится перед выполнением оператора statement. Таким образом, если expression ложно в самом первом проходе, цикл не выполняется.

У Кернигана и Ритчи иная точка зрения:
Цитата
while (выражение) оператор.
Здесь вначале вычисляется выражение. Если оно не равно нулю, выполняется оператор, а затем выражение вычисляется снова. Эти действия повторяются до тех пор, пока выражение не станет равным нулю. после этого управление передается на следующий оператор.

И где истина?

Сообщение отредактировал loghir - May 30 2011, 07:33
Go to the top of the page
 
+Quote Post
SKov
сообщение May 30 2011, 07:40
Сообщение #38


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(xemul @ May 30 2011, 10:51) *
Я могу обосновать чиста математически, что загрузка в любом случае будет не лучше суммирования в смысле получения минимальной средней (или средней квадратичной - без разницы) ошибки формирования некоторого периода на любом числе периодов.

Интересна не столько средняя ошибка, сколько ее дисперсия. Она определяет "дрожание" периода прерываний.
Я выше приводил пример, когда время задержки между событием, вызывающим прерывание и моментом загрузки гуляет около одного
тика таймера.(тик таймера = период срабатывания прескалера). Будем считать, что идеальным вариантом для нас является суммирование прескалера, когда задержка равна точно одному тику. Этот лишний тик мы учтем в прибавляемой константе. Это будет соответствовать нулевой ошибке.
Если время задержки в какой-то момент оказалось чуть-чуть меньше тика таймера,
то ошибка при суммирование таймера будет равна почти одному тику из-за обнуления прескалера, который к этому моменту накопил почти целый тик.
Если задержка чуть-чуть больше одного тика, то при суммировании будет ошибка небольшая. Короче говоря, ошибка при суммировании будет определяться состоянием прескалера на момент суммировния. В среднем это примерно половина тика.
В случае загрузки константы в моем примере дрожание периода определяется только интервалом времени, в котором гуляет задержка.
Это интервал между "чуть-чуть меньше тика" и "чуть-чуть больше тика".
Разница между этими моментами времени может быть существенно меньше времени тика таймера (и даже его половины).
И следовательно, дисперсия периода будет небольшой. Чиста математически wink.gif


Цитата(loghir @ May 30 2011, 11:29) *
Никак не докопаюсь, для чего нужен
Код
if (T0IF){}
.

Флаг запроса взводится автоматически при возникновении события, могущего вызвать прерывание.
А сбрасывать его должен сам программер в ППОП.
Сложность в том, что вы попадаете в одно и то же ППОП при срабатывнии прерываний от нескольких разных источников.
Вы должны определить, какой источник вас "позвал" в ППОП. Это делается опросом флагов запроса прерывания
(по-умному это называется "полинг прерываний".)
Если у вас разрешен только один источник прерываний, то эта проверка не нужна.
Цитата
Также не пойму, как в некоторых случаях работает оператор while. В книге по микроС сказано:
У Кернигана и Ритчи иная точка зрения:
И где истина?

Истина в вине wink.gif В смысле - оба источника правы. Т.к. "Ложь" кодируется нулем, а все остальное - "Правда"! wink.gif
Go to the top of the page
 
+Quote Post
xemul
сообщение May 30 2011, 08:18
Сообщение #39



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SKov @ May 30 2011, 11:40) *
Интересна не столько средняя ошибка, сколько ее дисперсия.

Дисперсия == (средняя квадратичная ошибка)^2.
Цитата
Она определяет "дрожание" периода прерываний.

Занятное определение, ну да ладно.
Мне это было интересно во времена, когда у пиков система прерываний отсутствовала как класс, а строить какие-то диспетчеры задач и формировать интервалы всё равно приходилось. Повозил немного карандашом, пришёл к выводу... С тех пор математика (точнее, арифметика) работы таймеров не изменилась. Но у каждого кулика своё болото.sm.gif

Цитата(loghir)
Добавил квалификатор volatile а всем переменным, используемым в ППОП.

Он нужен только переменным, _модифицируемым_ в прерываниях.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение May 30 2011, 08:28
Сообщение #40


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Не встречал задач, где предзагрузка таймера в комбинации с прескалером была бы хорошим решением. Без прескалера - это я понимаю.
Go to the top of the page
 
+Quote Post
SKov
сообщение May 30 2011, 08:42
Сообщение #41


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(xemul @ May 30 2011, 12:18) *
Дисперсия == (средняя квадратичная ошибка)^2.

Ну, это если "чиста математически". wink.gif
Квадратичная ошибка, да еще и в квадрате - это сильно! wink.gif
А если посмореть в букваре (можно в Википедии), то можно убедиться, что
Дисперсия ошибки == средний квадрат отклонения от средней ошибки.
Чувствуете разницу?
Go to the top of the page
 
+Quote Post
loghir
сообщение May 30 2011, 14:32
Сообщение #42


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Вот что получилось:
Код
void init (void)
{
// настройка TMR0 на 100 Hz (сотые доли секунды).
// регистр OPTION
T0CS = 0;    // bit 5 TMR0 Выбор источника сигнала 0 - Fosc/4 (внутренний); 1 - подача на T0CKI
T0SE = 0;    // bit 4 TMR0 Выбор фронта приращения TMR0 при внешнем тактовом сигнале (0-передний фронт)
PSA  = 0;    // bit 3 Выбор включения предделителя: 0 - перед TMR0, 1 - перед WDT
PS2  = 1;    // bit 2 Настройка предделителя на 15 Гц
PS1  = 1;    // bit 1 Настройка предделителя на 15 Гц
PS0  = 1;    // bit 0 Настройка предделителя на 15 Гц
TMR0 = 0;      // предзагрузка TMR0, сбрасывается при переполнении.
// конец настройки TMR0 на 100 Hz (сотые доли секунды).
}


Код
void interrupt isr (void)
{
if (T0IF)    // опрос флага прерывания по переполнению TMR0 (чтобы не сработало от другого источника)
{    
while (45 - 1) // выполняется до тех пор, пока ( ) не равно 0. Задержка на 15 Гц * 45. Т.е. на 3 сек.
{
    T0IF = 0;            // сброс флага прерывания по переполнению TMR0
}
time1 = time1 + 1;        // это число выводится 7-сегментный индикатор.
T0IF = 0;                 // сброс флага прерывания по переполнению TMR0
}    
}

Вот только не срабатывает! Как был "0" на индикаторе, так и остался.
Вариант
Код
...
volatile unsigned char tmp100 = 45;
volatile unsigned char time1 = 0;
...
void interrupt isr (void)
{
if (T0IF)    // опрос флага прерывания по переполнению TMR0 (чтобы не сработало от другого источника)
{    
while (tmp100) // выполняется до тех пор, пока tmp100 не равно 0. Задержка на 15 Гц * 45. Т.е. на 3 сек.
{
    tmp100 = tmp100 - 1;    // изменение переменной-задержки
    T0IF = 0;                // сброс флага прерывания по переполнению TMR0
}
time1 = time1 + 1;        // это число выводится 7-сегментный индикатор.
tmp100 = 45;            // обнуление счетчика
T0IF = 0;                 // сброс флага прерывания по переполнению TMR0
}    
}

не изменяет скорость счета при изменении tmp100.
Попытка написать
Код
void interrupt isr (void)

после main() вызывает ощибку при компиляции.

Сообщение отредактировал loghir - May 30 2011, 14:33
Go to the top of the page
 
+Quote Post
SKov
сообщение May 30 2011, 15:28
Сообщение #43


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(loghir @ May 30 2011, 18:32) *
Вот что получилось:
...
while (45 - 1)

Это что такое? Бесконечный цикл?
У вас проблемы не с микроконтроллером или с прерываниями.
У вас проблемы с элементарным программированием.
Go to the top of the page
 
+Quote Post
sargein
сообщение May 30 2011, 15:37
Сообщение #44


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



Цитата(loghir @ May 30 2011, 17:32) *
while (45 - 1)


офигенное условие cranky.gif

Я же на прошлой странице привел фактически готовое решение, зачем столько хрени пихать в обработчик прерываний?
Go to the top of the page
 
+Quote Post
sergeeff
сообщение May 30 2011, 15:56
Сообщение #45


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Коллеги!

Уважаемый loghir не хочет сам ничего делать (читать, изучать, советы слушать). Поэтому, не поддавайтесь на его стиль вытягивания не мытьем, так катаньем, готового результата и лучше всего, просто перестаньте реагировать на его вопросы.
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 Текстовая версия Сейчас: 19th July 2025 - 16:34
Рейтинг@Mail.ru


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