PIC16F877A: ¿Cómo mantener el controlador despierto?

1

Estoy utilizando Pic16f877a para una comunicación en serie. Tengo una aplicación para PC que envía datos al microcontrolador. El microcontrolador recibe los datos y los transmite a través de I2C.

Pero, estoy enfrentando un problema. Después de cada transmisión, tengo que reiniciar el microcontrolador para la próxima transmisión. Estoy usando ISR (rutina de servicio de interrupción) para recibir datos en serie. Pero incluso ISR no se ha llamado para los próximos datos disponibles. Y tengo que terminar de reiniciar el dispositivo.

Parte de mi Código de referencia:

int main()
{
    UARTInit();
    idmInitI2C();

    TRISB7 = 0;
    bool toggleBit = false;
    while (1)
    {    
        RB7 = toggleBit;
//        __delay_us(10);

        if ( UART_GetRecvByteStatus() ) {
            UART_SetRecvByteStatus(false);              // Set Received flag False
            receiveDataPkt();                           // Receive Incoming data
        }

        if ( isDataPktReceived ) {
            initIDComm();
            isDataPktReceived = false;
        }

        toggleBit != toggleBit;
    }
    return 0;
}

void receiveDataPkt()
{
    char buffer = NULL;                             // Load character receive to output buffer
    int i = 0, j = 0;
    int buf_count = 0;                              // Count character received
    int dly = 50;                                   // Initialize delay duration local to this section

    initBuffers();

    while ( !TXSTAbits.TRMT );                      // Wait until Transmit shift Register is not Empty, 
                                                // a transmission is in   progress or queued in the transmit buffer

    while ( buf_count != MAX_PKT_SIZE ){

        buffer = UART_Read();                             // Read Data


        if ( buffer == 0x00 ){
             break;
        }

        if ( buf_count < MAX_BUF_SIZE ) {
            data_Pkt_1[ i ] = buffer;               // Store data to Char Array 
            i++;
        } else {
            data_Pkt_2[ j ] = buffer;               // Store data to Char Array
            j++;
        }

        if ( ( data_Pkt_1[ 1 ] == READ ) && ( data_Pkt_1[ 4 ] == ETX ) ){
            break;
        }
        buf_count++;                                // Increase Count
    }

    while (dly){                                    // delay
        dly--;
     }

    if (OERR){
        CREN = 0;
        CREN = 1;
    }
    RCIE = 1;                                       // Enable Receive Interrupt

    isDataPktReceived = true;
    }

 void interrupt ISR(void)
 {
     if (RCIF)
     {
         RCIE = 0;
         if ( OERR ){
            CREN = 0;
            CREN = 1;
         }

        UART_SetRecvByteStatus( true );         // Signal for Received Byte
    } 
}

¿Qué se puede hacer para resolver el problema? Quiero mantenerlo siempre despierto para poder llamar a ISR para cada información entrante.

EDITAR:

función UART_Read () para referencia:

char UART_Read()
{
    int count = 0;
    char data = 0x00;

    while ( !RCIF ){
        if ( count >= 10 ){
            break;
        }
        __delay_ms(10);
        count++;
    }

    if ( RCIF ){
        data = RCREG;
    }

    return data;
}

(También estoy recibiendo un máximo de 133 bytes en una transacción).

    
pregunta skg

1 respuesta

3

Cuando un byte entra en el ISR de recepción, si se establece el indicador de interrupción, lo restablece y luego establece un indicador mediante UART_SetRecvByteStatus (verdadero). El ISR también desactiva la interrupción de recepción. No lee un byte del registro de recepción de UART en este momento. No es bueno.

En main, dentro del bucle while (1), si se establece el indicador RecvByteStatus, lo restablece y llama a receiveDataPkt (). En esa función, dentro del bucle while: while (buf_count! = MAX_PKT_SIZE), haces llamadas repetidas para leer el búfer de UART.

Pero a excepción de la primera vez, realmente no sabes si un personaje está disponible (a menos que UART_Read () bloquee la espera de que el búfer de recepción esté lleno, y lo dudo). Mientras realiza todas estas llamadas a UART_Read (), el ISR no se activa porque la interrupción está desactivada.

Sale de receiveDataPkt () solo si ha recibido uno de los dos caracteres especiales. Si faltan, seguirá recibiendo caracteres hasta que los buffers estén llenos.

La forma en que esto debería funcionar es si debe dejar la interrupción habilitada, y debe colocar los caracteres en un búfer circular dentro del ISR, y luego retirarlos de la función receiveDataPkt (). Esto implica el uso de dos punteros, uno para realizar un seguimiento del siguiente byte para el ISR y otro para extraer los bytes del búfer. Si no está familiarizado con los buffers circulares, búsquelo .

    
respondido por el tcrosley

Lea otras preguntas en las etiquetas