5
\$\begingroup\$

I want to use the internal oscillator in PIC16F616 in 8 MHz configuration and have the I/O function on RA4 and RA5. I've read through the datasheet, and I cannot find what I am doing wrong.

As far as I understand from the below information, TMR0 should increment every 500 ns, and it should create an interrupt when it overflows from "0xFF" to "0x00". However, RA4 pin toggles about every 20 us.

From the datasheet:

5.1.1

8-BIT TIMER MODE

When used as a timer, the Timer0 module will increment every instruction cycle (without prescaler).

Timer mode is selected by clearing the T0CS bit of the OPTION register to ‘0’.

Also;

Note: The value written to the TMR0 register can be adjusted, in order to account for the two instruction cycle delay when TMR0 is written.

Block Diagram of the TIMER0/WDT Prescaler

Here is my code, my compiler is 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);
}
\$\endgroup\$
  • \$\begingroup\$ Is that _config() is correct? is that '|' operator instead '&' operator? \$\endgroup\$ – Standard Sandun Apr 18 '12 at 18:13
  • \$\begingroup\$ be careful on this some compilers use write protect thing. \$\endgroup\$ – Standard Sandun Apr 18 '12 at 18:14
  • \$\begingroup\$ @sandundhammika, MPLAB XC8 user guide says: Multiple attributes can be selected by ANDing them together. \$\endgroup\$ – abdullah kahraman Apr 19 '12 at 5:29
2
\$\begingroup\$

Setting TMR0 to a fixed value in the interrupt routine is a bad idea if you want a reliable periodic interrupt. You are setting it to 254. That creates 2 dead cycles and then it needs 2 more cycles to overflow. The interrupt condition will be set long before the processor can come back and stuff another 254 into the timer. You are using a compiler (don't do that when looking at individual instructions), so you don't know how many instructions there are to exit the interrupt routine and how many there are on entry. 20 µs implies 40 instruction cycles. That sounds high, but again, you're using a compiler so you've already said you don't care about efficiency and have given up the right to count cycles.

If you want to verify that the PIC is running at the right clock rate, let timer 0 free run without touching it. That should interrupt every 256 instruction cycles, or every 128 µs.

If you want a reliable periodic interrupt, the first reaction should be to use timer 2. That's what it's there for and why it has a built in period register. If you need timer 2 for something else, you can still use timer 0 but add into it each interrupt, not reset its value. That way the time from when the timer wraps to when you re-write it doesn't get lost. Also, don't expect a rediculously short period like 4 instruction cycles. The PIC can't get into and out of a interrupt that fast, even without saving state.

\$\endgroup\$
  • \$\begingroup\$ You cannot write in C without a compiler, so I give up there :) Seems my configuration registers and code is fine, and it gives what it should, however, my expectations are wrong. I have never touched any timer but timer0 since I've started with microcontrollers, I am going to have a look at the others. Thanks for the great answer. \$\endgroup\$ – abdullah kahraman Apr 19 '12 at 14:38
  • \$\begingroup\$ 'TMR0 = 254;' , I think there's the wrong ! \$\endgroup\$ – Standard Sandun Apr 19 '12 at 20:40
  • \$\begingroup\$ @sandundhammika, nope, my original TMR0 value was 235, and it didn't work as calculated, because of the reasons Olin mentioned. \$\endgroup\$ – abdullah kahraman Apr 20 '12 at 20:16
-1
\$\begingroup\$

Simple change place for void interrupt myInterrupt(void) after main function.

\$\endgroup\$
  • 4
    \$\begingroup\$ Could you explain how and why is that the solution? \$\endgroup\$ – abdullah kahraman Sep 12 '12 at 12:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.