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