Как настроить внутренний генератор в PIC16F616?

Я хочу использовать внутренний генератор в PIC16F616 в конфигурации 8 МГц и включить функцию ввода-вывода RA4и RA5. Прочитал даташит, не могу найти что не так.

Насколько я понимаю из приведенной ниже информации, TMR0должно увеличиваться каждые 500 нс, и должно создаваться прерывание при переполнении с «0xFF» на «0x00». Тем не менее, RA4вывод переключается примерно каждые 20 секунд.

Из даташита:

5.1.1

8-битный режим таймера

При использовании в качестве таймера модуль Timer0 будет увеличивать каждый цикл инструкции (без предварительного делителя).

Режим таймера выбирается путем сброса бита T0CS регистра OPTION в «0».

Также;

Примечание . Значение, записываемое в регистр TMR0, можно изменить, чтобы учесть задержку в два командных цикла при записи TMR0.

Блок-схема предварительного делителя TIMER0/WDT

Вот мой код, мой компилятор MPLAB XC8. :

#include <xc.h>
__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & CP_OFF & IOSCFS_8MHZ & BOREN_ON);

void interrupt myInterrupt(void)
{
    if (T0IE && T0IF)
    {
        RA4 = ~RA4;
        TMR0 = 254;
        T0IF = 0;
    }
}

void main()
{
    TRISA = 0;
    ANSEL = 0;

    PSA = 1; // Prescaler Assignment bit : 1 = Prescaler is assigned to the WDT, 0 = Prescaler is assigned to the Timer0 module
    T0CS = 0; // T0CS: TMR0 Clock Source Select bit : 0 = Internal instruction cycle clock (FOSC/4), 1 = Transition on T0CKI pin
    T0IE = 1; //T0IE: Timer0 Overflow Interrupt Enable bit
    GIE = 1; //GIE: Global Interrupt Enable bit

    while (1);
}
Это _config () правильно? это '|' оператор вместо оператора '&'?
будьте осторожны, некоторые компиляторы используют защиту от записи.
@sandundhammika, руководство пользователя MPLAB XC8 говорит:Multiple attributes can be selected by ANDing them together.

Ответы (2)

Установка фиксированного значения TMR0 в подпрограмме прерывания — плохая идея, если вы хотите надежное периодическое прерывание. Вы устанавливаете его на 254. Это создает 2 мертвых цикла, а затем требуется еще 2 цикла для переполнения. Условие прерывания будет установлено задолго до того, как процессор сможет вернуться и вбить в таймер еще 254. Вы используете компилятор (не делайте этого при просмотре отдельных инструкций), поэтому вы не знаете, сколько инструкций есть для выхода из процедуры прерывания и сколько есть для входа. 20 мкс подразумевает 40 командных циклов. Это звучит высоко, но опять же, вы используете компилятор , поэтому вы уже сказали, что не заботитесь об эффективности, и отказались от права считать циклы.

Если вы хотите убедиться, что PIC работает с правильной тактовой частотой, дайте таймеру 0 работать в свободном режиме, не касаясь его. Это должно прерывать каждые 256 командных циклов или каждые 128 мкс.

Если вам нужно надежное периодическое прерывание, первой реакцией должно быть использование таймера 2. Вот для чего он нужен и почему он имеет встроенный регистр периода. Если вам нужен таймер 2 для чего-то другого, вы все равно можете использовать таймер 0, но добавлять в него каждое прерывание, а не сбрасывать его значение. Таким образом, время с момента, когда таймер переносится, до момента, когда вы его переписываете, не теряется. Кроме того, не ожидайте смехотворно короткого периода, такого как 4 цикла инструкций. PIC не может так быстро войти в прерывание и выйти из него, даже без сохранения состояния.

Вы не можете писать на C без компилятора, поэтому я сдаюсь :) Кажется, мои регистры конфигурации и код в порядке, и он дает то, что должен, однако мои ожидания неверны. Я никогда не прикасался ни к одному таймеру, кроме timer0, так как я начал с микроконтроллеров, я собираюсь взглянуть на другие. Спасибо за отличный ответ.
'TMR0 = 254;' , я думаю, что это неправильно!
@sandundhammika, нет, мое исходное значение TMR0 было 235, и оно не сработало так, как рассчитывалось, по причинам, упомянутым Олином.

Простое изменение места прерывания пустоты myInterrupt(void) после основной функции.

Не могли бы вы объяснить, как и почему это решение?