PIC16F684 Las interrupciones del temporizador 2 se producen mucho más rápido de lo esperado

2

TL; DR: el temporizador 2 se interrumpe (1: 4 postscaler, PR2 = 0x3F) que ocurre a aproximadamente 139 kHz en lugar de los 19.5 kHz esperados. Cambiar el valor de la escala 1 a 1 no tiene efecto.

Estoy usando un microcontrolador PIC16F684 para un proyecto y he estado luchando para que funcione. Para depurar, he reducido mi código a casi nada: usando la interrupción del temporizador 2 para alternar un pin.

No estoy usando preescalador (1: 1), un escalador posterior de 1: 4 y un valor de período de PR2=0x3F . También estoy usando un cristal de 20 MHz. Por lo tanto, esperaría que la frecuencia de interrupción fuera:

(FOSC/4) / (PR2+1) / postscaler = (20 MHz / 4) ÷ (0x3F + 1) ÷ 4 = 19.5 kHz

Además, el período sería el inverso de eso, o 51.2 nosotros.

En mi ISR, establezco un pin alto, agrego algo de tiempo de retardo (estableciendo una variable igual a cero) y borro el pin. Por lo tanto, espero ver estos pulsos cada 51.2 nos.

En su lugar, mi osciloscopio muestra pulsos cada 7.2 nosotros. Tomando el inverso, eso corresponde a una frecuencia de aproximadamente 139 kHz.

Otro dato interesante es que si cambio T2CON de modo que el valor de puntuación posterior es 1: 1 (es decir, T2CON=0b00000000 ) en lugar de 1: 4, el resultado es exactamente igual : pulsos cada 7,2 nosotros. Al rehacer mi cálculo anterior, esperaría una frecuencia de 78.125 kHz, o un período de 12.8 nosotros.

Solo para eliminar esta posibilidad, he ejecutado otros programas en este chip PIC y se han comportado como se esperaba, con la sincronización correcta. Pero ninguno de esos otros programas usó Timer 2. Entonces, el chip en sí y el cristal probablemente no sean el problema.

Cualquier sugerencia sería apreciada. Me temo que será algo vergonzosamente obvio, pero he revisado la hoja de datos varias veces y parece que no puedo encontrar ningún problema obvio.

Aquí está mi código:

#include <xc.h>

#pragma config FOSC = HS        //oscillator selection; external crystal on pins 15 and 16
#pragma config WDTE = OFF       //disable watchdog Timer
#pragma config PWRTE = OFF      //power-up timer disabled
#pragma config MCLRE = OFF      //use MCLR pin (internally tied to Vdd) as a digital input
#pragma config CP = OFF         //code protection disabled
#pragma config CPD = OFF        //data code protection disabled
#pragma config BOREN = OFF      //disable Brown-Out Reset
#pragma config IESO = OFF       //disable Internal External Switchover
#pragma config FCMEN = OFF      //disable Fail-safe Clock Monitor

#define TestPin RA0
char k;

void main (void)
{
    //ground unused pins (as outputs)
    TRISC=0b00000000;
    PORTC=0b00000000;
    TRISA=0b00111000;       //RA3 always reads HI; RA4 and RA5 read HI in HS mode
    PORTA=0b00111000;

    PR2=0x3F;               //Timer 2 period
    T2CON=0b00011000;       //Timer 2 off; 1:1 prescaler, 1:4 postscaler

    PIR1bits.TMR2IF=0;      //clear Timer 2 interrupt flag
    INTCONbits.PEIE=1;      //enable peripheral interrupts (e.g., PWM)
    PIE1bits.T2IE=1;        //enable Timer 2 interrupt
    T2CONbits.TMR2ON=1;     //turn on Timer 2
    INTCONbits.GIE=1;       //turn on all interrupts
    while(1);               //hang up, wait for interrupts
}

void interrupt ISR()
{
    if (PIR1bits.TMR2IF==1)
    {
        PIR1bits.TMR2IF==0;     //clear interrupt flag

        TestPin=1;              //toggle pin
        k=0;
        k=0;
        k=0;
        k=0;
        k=0;
        TestPin=0;
    }
}

Equipo utilizado:
 - PIC16F684 con PICkit 3
 - MPLAB X IDE v3.00, compilador XC8
 - Laptop Dell Inspiron 6400, Linux Mint 17 Xfce

    
pregunta Daniel Charles

1 respuesta

5

Tienes un error en el ISR. Cuando creas que el indicador de interrupción está desactivado, en realidad se compara con cero. En consecuencia, el ISR se llama de nuevo inmediatamente después de la finalización. Cambia la línea a

PIR1bits.TMR2IF=0;     //clear interrupt flag

Todo debería estar bien después de eso.

    
respondido por el Oleg Mazurov

Lea otras preguntas en las etiquetas