Точность Timer1 как часов реального времени с прерываниями PIC на 16F*

Я использую C с компилятором BoostC. Меня беспокоит, насколько точен мой код. Конфигурация ниже показывает более или менее 1 Гц (проверено невооруженным глазом со светодиодом). (Он использует внешний часовой кристалл 32 кГц для Timer1 на 16f74).

Я надеюсь, что кто-нибудь может сказать мне...

Мой код ниже нуждается в каких-либо корректировках? Какой самый простой способ измерить точность до ближайшего тактового периода процессора? Нужно ли будет заморачиваться со сборкой, чтобы надежно обеспечить точность сигнала 1 Гц?

Я надеюсь, что время, затрачиваемое на выполнение обработчика таймера (и других), даже не учитывается, поскольку таймер всегда ведет отсчет. Пока обработчики никогда не выполняются дольше, чем 1/32 кГц секунды, будет ли сигнал 1 Гц иметь по существу точность 32 кГц Crystal?

Спасибо

#define T1H_DEFAULT 0x80
#define T1L_DEFAULT 0
volatile char T1H = T1H_DEFAULT;
volatile char T1L = T1L_DEFAULT;

void main(void){

    // setup 
    tmr1h = T1H;
    tmr1l = T1L;
    t1con = 0b00001111; // — — T1CKPS1 T1CKPS0 T1OSCEN NOT_T1SYNC TMR1CS TMR1ON
    // ...

    // do nothing repeatedly while no interrupt
    while(1){}
}

interrupt(void) {

    // Handle Timer1
    if (test_bit(pir1, TMR1IF) & test_bit(pie1, TMR1IE)){

            // reset timer's 2x8 bit value
            tmr1h = T1H;
            tmr1l = T1L;

            // do things triggered by this time tick

            //reset T1 interrupt flag 
            clear_bit(pir1, TMR1IF);

    } else 

    ... handle other interrupts

}

person CL22    schedule 25.06.2011    source источник
comment
Здесь у нас есть electronics.stackexchange.com   -  person DipSwitch    schedule 25.06.2011


Ответы (1)


Я вижу некоторые улучшения...

Запуск вашего таймера внутри прерывания неточен. Когда вы устанавливаете счетчик таймера в прерывании...

    tmr1h = T1H;
    tmr1l = T1L;

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

tmr1h = T1H;  //tmr1h  must be still 0!

Или, что еще лучше, просто установите 7-й бит регистра tmr1h. Компилятор должен скомпилировать этот порядок в одну инструкцию asm, например...

bsf    tmr1h, 7

...чтобы не потерять данные в регистре tmr1. Потому что, если это делается с помощью более чем одной инструкции, аппаратное обеспечение может увеличить значение счетчика между выполнением: чтение-изменение-запись.

person GJ.    schedule 25.06.2011
comment
Спасибо, я понимаю, что вы говорите, но, поскольку таймер увеличивается только на 32 кГц, с тактовой частотой 4 МГц, разве это не даст мне около 125 циклов в ISR, прежде чем запись в значения таймера будет грязной? - person CL22; 25.06.2011
comment
Вы не сказали нам частоту основного процессора. Если тактовая частота ЦП составляет 4 МГц, то цикл инструкции составляет 1 МГц, поэтому это всего 30 тактовых импульсов, а задержка прерывания может быть намного больше, чем 30 тактовых импульсов, особенно если вы обрабатываете больше разных прерываний. - person GJ.; 25.06.2011
comment
Спасибо, извините, я знаю, что сейчас это движется в сторону электроники, но, пожалуйста, не могли бы вы подробнее рассказать о том, что представляет собой задержку прерывания? Это просто выполнение кода ISR? Или есть какая-то дополнительная аппаратная задержка? - person CL22; 25.06.2011
comment
Конечно, есть некоторая аппаратная задержка, но она занимает всего несколько программных циклов. Основная проблема заключается в том, что событие переполнения tmr1 возникает, когда программа выполняет другое прерывание, такое как прерывание UART или любое другое. В этой ситуации событие переполнения TMR1 ожидает, что текущее ожидающее прерывания завершит задание и снова включит прерывания. После этого будет выполнено следующее по аппаратному приоритету прерывание ожидания таблицы приоритетов. Конечно в основное время работает tmr1. Таким образом, эта ситуация может занять непредсказуемое количество тактов процессора. - person GJ.; 25.06.2011