Interrupción UART PIC No se dispara

2

Tengo el PIC16F628A que intento leer desde UART. Sin interrupciones, lee bien los primeros 3 bytes pero golpea un OERR. Para combatir esto, pensé que una interrupción sería buena y cargaría todos los bytes recibidos en una variable de búfer que podría leerse más tarde (búfer de anillo de tipo de matriz). Pero la interrupción no se está activando y me he quedado sin ideas.

CMCON = 0x07;           //16F627/8 spcial function reg (RAx is port)
CCP1CON = 0b00000000;   //Capt/Comp/PWM off

OPTION_REG = 0b00000000;

T1CON = 0;
INTCON = 0;
PIR1 = 0;
GIE = 0;

PIE1 = 0;

BRGH = 1;   /* high baud rate */
SPBRG = 19200;  /* set the baud rate */

SYNC = 0; //Async
TXEN = 0; //Disable transmit
TXIE = 0; //Disable transmit interrupt
RCIE = 1; //Enable Receive interrupt
SPEN = 1; //Enable serial pins
CREN = 1; //Enable continuous receive
SREN = 0;
TX9  = ninebits?1:0;    /* 8- or 9-bit transmission */
RX9  = ninebits?1:0;    /* 8- or 9-bit reception */

PEIE = 1; //Enable external interrupt
GIE = 1; //Enable global interrupt

He simplificado mi interrupción para encender una luz:

extern interrupt isr(void)
{
    RB5 = 1;
}

Pero no se está disparando. El proyecto es leer un escáner de código de barras en serie y procesar el código de barras. ¿Alguien puede ofrecer alguna ayuda?

EDIT

Ok, ya que parece que no entiendes. Voy a publicar las rutinas reales:

void initialize()
{
    CMCON = 0x07;           //16F627/8 spcial function reg (RAx is port)
    CCP1CON = 0b00000000;   //Capt/Comp/PWM off

    OPTION_REG = 0b00000000;

    T1CON = 0;
    INTCON = 0;
    PIR1 = 0;
    GIE = 0;
    PEIE = 0;
    PIE1 = 0;

    sci_Init(BAUDRATE ,SCI_EIGHT);// Baud set and Bit set

    TMR0 = 1000;
    T0IE = 0;
    PEIE = 1; //Enable external interrupt
    GIE = 1; //Enable global interrupt

    //Set inputs to input
    SetButtons();

    //Set relays to output
    SetRelays();

    TRISB5 = 0;

    LEDStatus = 0;
}

unsigned char sci_Init(unsigned long int baud, unsigned char ninebits)
{
    int X;
    unsigned long tmp;

    /* calculate and set baud rate register */
    /* for asynchronous mode */
    tmp = 16UL * baud;
    X = (int)(FOSC/tmp) - 1;
    if((X>255) || (X<0))
    {
        tmp = 64UL * baud;
        X = (int)(FOSC/tmp) - 1;
        if((X>255) || (X<0))
        {
            return 1;   /* panic - baud rate unobtainable */
        }
        else
            BRGH = 0;   /* low baud rate */
    }
    else
        BRGH = 1;   /* high baud rate */
    SPBRG = X;  /* set the baud rate */

    SYNC = 0; //Async
    TXEN = 0; //Disable transmit
    TXIE = 0; //Disable transmit interrupt
    RCIE = 1; //Enable Receive interrupt
    SPEN = 1; //Enable serial pins
    CREN = 1; //Enable continuous receive
    SREN = 0;
    TX9  = ninebits?1:0;    /* 8- or 9-bit transmission */
    RX9  = ninebits?1:0;    /* 8- or 9-bit reception */

    rxBuffIndex = 0;
    rxBuffRead = 0;

    return 1;
}

void sci_LoadBuffer(void)
{
    rxBuffer[rxBuffIndex] = RCREG;

    rxBuffIndex = ++rxBuffIndex % MAXBUFFER;
}

unsigned char sci_ReadBuffer()
{
    unsigned char byte;

    do
    {
        byte = rxBuffer[rxBuffRead];
    }while( byte == 0 ); //Block until valid data

    rxBuffer[rxBuffRead] = 0;
    rxBuffRead = (++rxBuffRead) % MAXBUFFER;

    return byte;
}

void interrupt isr(void)
{
    if(RCIF) sci_LoadBuffer();
    LEDStatus = 1;
}

Sé que no es TODO, pero debería ser suficiente para diagnosticar por qué no se activan las interrupciones. ¡ESO ES TODO LO QUE NECESITO! Activando las interrupciones.

Estoy usando MPLab con Hi-Tech C Compiler. El cual, a partir del manual, guarda automáticamente el estado y lo restaura al ingresar / salir de la interrupción.

    
pregunta Teagan

4 respuestas

2

TRISB1 debe configurarse en 1 para configurar RB1 (RX) como entrada. No estoy seguro de cuál es el valor predeterminado, por lo que puede estar bien.

Debe borrar el indicador de interrupción de recepción (RCIF) leyendo el registro de recepción (RCREG). Además, dado que el registro de recepción tiene un doble búfer, es posible que deba leerlo más de una vez.

Por lo tanto, su rutina de interrupción debe verse más como esto:

extern interrupt isr(void)
{
    while (RCIF)
    {
        char ch;

        RB5 = 1;
        ch = RCREG;    // normally would go into an array and increment a counter
    }
}

No sé si ese es su único problema, ya que indica que no está ingresando a la rutina de interrupción. Pero lo anterior es la forma correcta de leer los caracteres fuera del búfer de recepción.

======================================

EDITAR:

No sé si esto ayudará o no, pero en esta publicación , antes de habilitar las interrupciones , el código borra primero el FIFO. (Su código también borra la marca RCIF, pero dado que está solo en su chip, no es necesario).

ch = RCREG;    // clear FIFO  
ch = RCREG;
ch = RCREG;

// then enable interruupts ...
    
respondido por el tcrosley
1

Ok, dos cosas.

Primero, dentro de su rutina de interrupción, por lo general tiene que borrar el indicador IF RCIF para permitir que la interrupción vuelva a dispararse.

No es la razón por la que la interrupción no se dispara en absoluto.

El problema con su código es que está definiendo una función como una interrupción (lo cual está bien), lo que hace que el compilador empuje las cosas a la pila automáticamente y las saque después de que termine la rutina. También termina la función con un comando de "retorno de interrupción" en lugar de un simple comando de "retorno".

Lo que no hace es vincular la función al vector de interrupción. Por lo general, solo hay una pequeña cantidad de espacio alrededor del área del vector de interrupción, por lo que es normal colocar un goto en la dirección del vector de interrupción que llama al nombre de su rutina de interrupción.

Dependiendo de tu compilador, hay varias formas de hacerlo. Le sugiero que lea el manual de su compilador sobre los vectores de interrupción y el código de muestra correspondiente.

    
respondido por el Majenko
1

No leí todo tu largo post, pero me he dado cuenta de esto en el skimming:

extern interrupt isr(void)
{
    RB5 = 1;
}

Esto es definitivamente incorrecto. No sé cuál es la condición de interrupción, pero no la está eliminando. El procesador se bloqueará en la primera interrupción porque volverá a ingresar a la rutina de interrupción inmediatamente después de que se complete porque la condición de interrupción aún está activa.

    
respondido por el Olin Lathrop
0

¿Ha intentado mirar la señal RS-232 en un alcance para ver si la velocidad en baudios es correcta? Intente transmitir algunos caracteres desde el PIC para asegurarse de que el UART tenga la configuración de velocidad en baudios correcta.

    
respondido por el mjh2007

Lea otras preguntas en las etiquetas