Leyendo el código infrarrojo XC8

1

SOLUCIONADO: cambié el receptor de infrarrojos y todo funcionó correctamente, estoy usando el TSOP4838.

EDITAR: He modificado el código, he estado probando el programa más a fondo y he encontrado algo extraño. Estoy usando un receptor de código infrarrojo como este:

CuandoelPORTBestávinculadoaGND,elmicrocontroladorcomienzaaenviarcadasegundoelmensaje"while", pero cuando lo vinculo al VOUT el microcontrolador deja de enviarlo (cuando no debería detenerse) y parpadea el led Cuando presiono algún botón en el control remoto infrarrojo. Realmente no tengo idea de lo que está pasando aquí, espero que alguien pueda ayudarme con esto.

Estoy creando un programa para leer un código de un transmisor de infrarrojos remoto. Lo he probado en Proteus y parece que funciona, pero no lo hace físicamente. El uso de mi microcontrolador (PIC18F2520) parece no entrar en la interrupción.

Te muestro el siguiente código:

#include <xc.h>

#define _XTAL_FREQ 4433619

char infrared_code[6];
unsigned char UART1Config = 0, baud;
char MensajeTx[] = "Probando ";
int counter = 0;


void main(void) {

//Infrared entry.
TRISBbits.RB0 = 1;

TRISBbits.RB1 = 1;
TRISBbits.RB2 = 1;
TRISBbits.RB3 = 1;
TRISBbits.RB4 = 1;
TRISBbits.RB5 = 1;
TRISBbits.RB6 = 1;
TRISBbits.RB7 = 1;


//State LED
TRISCbits.RC2 = 0;

UART1Config = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE &              USART_EIGHT_BIT & USART_BRGH_HIGH;
baud = 28;
OpenUSART(UART1Config,baud);

ADCON1 |= 0b1111;
EnablePullups();

RCIF = 0; //reset RX pin flag
RCIE = 1; //Enable RX interrupt
IPEN = 0;

INTCONbits.RBIE = 1; //Enable Interrupt per change on PORTB
INTCONbits.PEIE = 1; // Enable Peripherial Interrupt
INTCONbits.GIE = 1; // Enable Global Interrupt

INTEDG0 = 1;

ei();       //remember the master switch for interrupt?

while(1){
    for(int i=0; i<10; i++)
        __delay_ms(100);

    putsUSART("While: /n");
}
}

void interrupt low_priority myIsr(void){

//If is interrupted by change on portB
if (INTCONbits.RBIF){

    __delay_ms(14);
    __delay_us(224);

    for(int i=0;i<6;i++)
    {
        if(PORTBbits.RB0)
        {
            infrared_code[i] = 1;
        }
        else{
            infrared_code[i] = 0;
        }
        __delay_ms(1);
        __delay_us(778);
    }

    while(BusyUSART());
    putsUSART("Interrupcion: ");

    //for(int i=0;i<6;i++)
    //{
        //WriteUSART(infrared_code[i]);
     //   putsUSART(infrared_code[i]);
   // }
    putsUSART(infrared_code);
    putsUSART("/n");

    if(counter == 0)
    {
        PORTCbits.RC2 = 1;
        counter = 1;
    }
    else if(counter == 1)
    {
        PORTCbits.RC2 = 0;
        counter = 0;
    }
    INTCONbits.GIE = 1;
    INTCONbits.RBIF = 0;

    if (PORTB) {
        asm("nop");
    }

    for(int i=0;i<20;i++)
       __delay_ms(100);

}

}

Realmente estoy trabajando en ello, pero no encuentro la causa, agradecería que me ayudaras.

Por cierto, cuando lo he probado en Proteus, no sé por qué, pero para poder leer algunos cambios en PORTB0 tengo que conectarlos todos (de PORTB0 a PORTB7 ) incluso cuando acabo de especificar PORTB0 como entrada digital.

Saludos!

    
pregunta Manuel Joaquín

1 respuesta

2

No estoy seguro de poder responder completamente a tu pregunta, pero es posible que pueda darte un par de cosas para verificar.

En primer lugar, no tengo fluidez con el compilador XC8 por lo que puede haber alguna automatización de la que no tenga conocimiento aquí, pero observo que no restablece explícitamente el bit GIE en ninguna parte de su ISR. El bit GIE se borra cuando se genera una interrupción, deshabilitando otras interrupciones, y usted debe asegurarse de que se reinicie al final de su ISR. A menos que sepa que el compilador XC8 está haciendo esto automáticamente por usted (?), Debe indicarlo en el código.

En segundo lugar, me doy cuenta de que su esquema muestra un LED receptor, pero no hay demodulación ni filtrado de ningún tipo. ¿Está utilizando un módulo de recepción IR "adecuado" (por ejemplo, STOP2236) o es simplemente un diodo IR? Si es lo último, necesita demodular el portador de 36 kHz y filtrar cualquier ruido.

En tercer lugar, ¿puedo asumir que no ha habilitado la prioridad de interrupción para este dispositivo? Si ha habilitado la prioridad de interrupción, debe asegurarse de configurar la fuente de interrupción en la prioridad correcta (baja o alta) para que ingrese el ISR correcto.

En cuarto lugar, observo que al comienzo de su ISR tiene un retraso de 14.224 ms. ¿Para qué es esto? Me parece que esta demora de 14 ms lo obligaría a perder la mayoría de las transmisiones RC5. En realidad, solo hice un cálculo y me di cuenta de que caería al final de los bits de la dirección. Tal vez haya hecho esto a propósito para decodificar solo la parte de comando de la transmisión?

Y una nota final; El protocolo RC5 utiliza codificación Manchester, cuyo propósito es eliminar la necesidad de confiar en una velocidad de reloj precisa. De hecho, puede pensarse como un reloj automático porque los "1" y "0" están definidos por transiciones de alta-baja o baja-alta, no por un punto de muestreo conocido en los datos. Definitivamente, es posible crear un decodificador que funcione con su método (muestrear un punto conocido en el flujo de datos), pero de esta manera ha descuidado una ventaja importante de la decodificación RC5. No necesita confiar en el muestreo de los datos en puntos conocidos.
También se debe tener en cuenta que, dado que el RC5 está diseñado para ser de reloj automático en primer lugar, es poco probable que los diseñadores de transmisores RC5 hayan prestado mucha atención a la velocidad de transmisión y que no pueda confiar en el período de tiempo de 1,778mS .

    
respondido por el Brian J Hoskins

Lea otras preguntas en las etiquetas