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

 
 
> Снова о TMR1 в PIC, Реализация Timer1_Errata на си
stas00n
сообщение Jun 8 2011, 11:19
Сообщение #1


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

Группа: Участник
Сообщений: 181
Регистрация: 26-11-10
Пользователь №: 61 198



Коллеги, прошу пардону если этот вопрос уже изжеван, но не сочтите за труд - объясните для "особо одаренных". Заметил в своем девайсе на PIC16LF628A незначительное (но больше расчетного) отставание часов - решил разобраться. Часы реализованы "классически" - прерывания по переполнению TMR1 в режиме асинхронного счета от внешнего кварца 32768 Гц:
Код
volatile signed long int actualTime;

void interrupt isr (void){
//...
if    (TMR1IF && TMR1IE){                        //    TMR1 Handler
TMR1H |= 0x80;                                //Загрузка таймера для получения периода 1с.
actualTime++;
}
//...
}

Выкурил микрочиповскую еррату по этому вопросу, и выяснил, что если загружать регистры таймера в неподходящий момент, то таймер может пропустить один такт. Это понятно. Поскольку у меня в основном коде периодически запрещаются прерывания на относительно долгие промежутки времени, ясно что такие неподходящие моменты имеют место быть. Решил сделать как написано в еррате - прежде чем загружать регистры таймера, дождаться его очередного приращения. Это тоже понятно. Но хоть убей не пойму, ЗАЧЕМ дрыгать клок с внешнего на системный и обратно, зачем выключать/включать таймер:

Код
BTFSC    TMR1L,0
GOTO     $-1
BTFSS    TMR1L,0
GOTO     $-1             ;Timer has just incremented, 31 μs before next rising edge to
                         ;complete reload
Update:
BCF     T1CON,TMR1CS     ;Select system clock for Timer1
BSF     TMR1H,7          ;Timer1 high byte 0x80
BCF     T1CON,TMR1ON     ;Timer1 off
BSF     T1CON,TMR1C      ;Select external crystal
BSF     T1CON,TMR1ON     ;Timer1 on


Разве недостаточно просто делать запись в TMR1 сразу же после инкремента последнего:
Код
void interrupt isr (void){
//...
if    (TMR1IF && TMR1IE){                        //    TMR1 Handler
while (TMR1L == TMR1L){                              // Ожидание инкремента TMR1
;
}
TMR1H |= 0x80;                                //Загрузка таймера для получения периода 1с.

actualTime++;
}
//...
}

В дизассемблере это выглядит так:
Код
93:                while (TMR1L == TMR1L){
   223    1283     BCF STATUS, 0x5
   224    080E     MOVF TMR1L, W
   225    060E     XORWF TMR1L, W
   226    1903     BTFSC STATUS, 0x2
   227    2A23     GOTO 0x223
94:               ;
95:                }
96:                TMR1H |= 0x80;    
   228    178F     BSF TMR1H, 0x7


Или я морочу голову себе и людям и надо сделать точно так как в примере из ерраты?
Go to the top of the page
 
+Quote Post



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

 


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


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