PIC18F4550 y Sparkfun RFID Starter Kit con módulo RFID ID-12LA, problema de lectura de TAG

0

Recientemente compré un kit de inicio RFID SparkFun con módulo RFID ID-12LA. Similar a la que se encuentra en el siguiente enlace: enlace . Lo probé utilizando la interfaz USB, lo conecté a Putty y funcionó muy bien. También intenté conectarlo a Arduino como se presenta en el sitio web, y todo está funcionando correctamente. ¡También intenté no usar la biblioteca de software de serie del arduino y también funcionó perfectamente! Cuando empecé a probarlo con PIC18F4550, no funcionó como debería. Primero conecté su impresora TX a RX en el microcontrolador PIC. Y conectó un LCD basado en caracteres al microcontrolador. Enciendo el PIC, el lector RFID y la LCD a través de un regulador de voltaje lineal de 5 V 7805. Tenga en cuenta que el lector con el USB a la placa de interfaz en serie está configurado en modo ASCII. El siguiente es el código que estoy usando:

#include <p18F4550.h>
#include <delays.h>

// CONFIG1H
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator 
                                // (HS))
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (Fail-
                                // Safe Clock Monitor enabled)
#pragma config IESO = ON        // Internal/External Oscillator Switchover 
                                // bit (Oscillator Switchover mode enabled)

// CONFIG2L
#pragma config PWRT = ON        // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOR = ON         // Brown-out Reset Enable bits (Brown-out 
                                // Reset enabled in hardware only (SBOREN is 
                                // disabled))
#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum 
                                // setting 2.05V)

// CONFIG2H
#pragma config WDT = OFF        // Watchdog Timer Enable bit 
                                // (WDT disabled (control is placed on the 
                                // SWDTEN bit))

// CONFIG4L
#pragma config STVREN = OFF     // Stack Full/Underflow Reset Enable bit 
                                // (Stack full/underflow will not cause 
                                // Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit 
                                // (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit 
                                // (Instruction set extension and Indexed 
                                // Addressing mode disabled (Legacy mode))

#define LCD_RS LATBbits.LATB0   
#define LCD_EN LATBbits.LATB1   
#define LCD_DATA LATD

#define UART_RECEIVE_FLAG PIR1bits.RCIF

void initialize_LCD();
void latch_LCD();
void print_char_LCD(unsigned char c);
void print_HEX_BYTE_LCD(unsigned char byte);
void command_LCD(unsigned char c);
void clear_LCD();

void Delay_ms(int ms);

void chk_isr(void); // check interrupt subroutine
void RC_ISR(void);  // interrupt subroutine for receive of UART
void initializeSerial();

void enInterrupts();

volatile unsigned char recv;

#pragma code My_HiPrio_Int=0x0008//high priority interrupt

void My_HiPrio_Int(void) {
    _asm
        GOTO chk_isr
    _endasm
}
#pragma code

#pragma interrupt chk_isr //used for high-priority interrupt only

void chk_isr(void) {
    if (UART_RECEIVE_FLAG == 1)// && status == connection_OK_Status)
        RC_ISR();
}

void main(void) {

    // set LCD pins as output

    TRISBbits.TRISB0 = 0;
    TRISBbits.TRISB1 = 0;
    TRISD = 0x00;

    initialize_LCD();

    initializeSerial();
    enInterrupts();

    clear_LCD();
    Delay_ms(1000);
    while (1) {

    }
    return;
}

void Delay_ms(int ms) {

    int counter = 1;
    for (counter = 1; counter <= ms; ++counter) {
        Delay100TCYx(25);
    }

}

void initializeSerial() {
    TRISCbits.TRISC6 = 0; //TX pin = output
    TRISCbits.TRISC7 = 1; //RX pin = input
    TXSTA = 0x20; //low baud rate, 8-bit
    SPBRG = 15; //9600 baud rate
    RCSTAbits.CREN = 1;
    RCSTAbits.SPEN = 1;
    TXSTAbits.TXEN = 1;
    PIE1bits.RCIE = 1; //enable rcv interrupt
    //PIE1bits.TXIE = 1; //enable TX interrupt
}

void enInterrupts() {
    INTCONbits.PEIE = 1; //enable peripherals interrupt
    INTCONbits.GIE = 1; //enable all interrupts
}

void latch_LCD() {
    LCD_EN = 1;
    Delay_ms(1);
    LCD_EN = 0;
    Delay_ms(1);
}

void initialize_LCD() {
    TRISD = 0;
    TRISBbits.RB3 = 0;
    TRISBbits.RB4 = 0;

    Delay_ms(15);

    LCD_RS = 0;
    LCD_DATA = 0x30;
    latch_LCD();
    Delay_ms(16);

    LCD_RS = 0;
    LCD_DATA = 0x30;
    latch_LCD();
    Delay_ms(16);

    LCD_RS = 0;
    LCD_DATA = 0x30;
    latch_LCD();
    Delay_ms(16);

    LCD_RS = 0;
    LCD_DATA = 0x38;
    latch_LCD();
    Delay_ms(16);

    LCD_RS = 0;
    LCD_DATA = 0x08;
    latch_LCD();
    Delay_ms(16);

    LCD_RS = 0;
    LCD_DATA = 0x01;
    latch_LCD();
    Delay_ms(16);

    LCD_RS = 0;
    LCD_DATA = 0x06;
    latch_LCD();
    Delay_ms(16);

    LCD_RS = 0;
    LCD_DATA = 0x0E;
    latch_LCD();
    Delay_ms(16);
}

void print_char_LCD(unsigned char c) {
    LCD_DATA = c;
    LCD_RS = 1;
    latch_LCD();
    Delay_ms(1);
}

void print_HEX_BYTE_LCD(unsigned char byte){
    unsigned char nibble_MS = (byte >> 4) & 0x0F;
    unsigned char nibble_LS = byte & 0x0F;

    if(nibble_MS <= 9){
        nibble_MS += '0';
    }
    else{
        nibble_MS = nibble_MS - 10 + 'A';
    }
    print_char_LCD(nibble_MS);

    if(nibble_LS <= 9){
        nibble_LS += '0';
    }
    else{
        nibble_LS = nibble_LS - 10 + 'A';
    }
    print_char_LCD(nibble_LS);

    print_char_LCD(' ');
}

void command_LCD(unsigned char c) {
    LCD_DATA = c;
    LCD_RS = 0;
    latch_LCD();
    Delay_ms(1);
}

void clear_LCD() {
    command_LCD(0x01);
}

void RC_ISR() {
    recv = RCREG;
    print_HEX_BYTE_LCD(recv);
    UART_RECEIVE_FLAG = 0;
}

El problema es que cada vez que escaneo una tarjeta (que ya viene preempaquetada con el kit), ¡solo obtendré los primeros 3 bytes de la respuesta impresos en la pantalla! Además, si vuelvo a escanear otra tarjeta o la misma tarjeta, no aparecerá nada en la pantalla LCD hasta que reinicie el microcontrolador. Después de restablecer también, los primeros 3 bytes solo se mostrarán mientras escaneo una tarjeta. Probé un código que cuenta el número de bytes ingresados en serie y era 3, por lo que lo que veo en la pantalla LCD es la única respuesta del lector. ¿Está este problema relacionado con el lector o un problema en el código? Supongo que mis conexiones son perfectas o de lo contrario nunca conseguiré que la pantalla LCD funcione o el lector (es decir, las conexiones son buenas porque recibo una respuesta).

Cualquier ayuda es apreciada. Busqué en Google sin ningún caso similar!

    
pregunta Khaldoun Kassam

1 respuesta

1

Dado que recibe tres bytes correctamente, el mecanismo general está funcionando y el problema está en algún lugar en un nivel superior.

En 9600Baud, la transferencia de un byte dura aproximadamente 1 ms. Su código necesita al menos 6 ms debido a los retrasos para procesar un byte recibido.
Por lo tanto, si su dispositivo RFID envía los datos demasiado rápido, perderá algunos bytes.

El microcontrolador indica bytes perdidos al elevar un indicador de desbordamiento. Que yo sepa, dejará de leer datos hasta que su código borre esta bandera.

En general, una rutina de interrupción debe ser corta, para que esté disponible para la próxima interrupción lo más rápido posible. Debe almacenar en búfer los bytes recibidos en una matriz dentro de la rutina de interrupción, y dejar que la rutina principal los introduzca en la pantalla LCD.

Esto es sencillo cuando su dispositivo envía algún tipo de señal de fin de mensaje como CR LF. En este caso, su rutina de interrupción puede escribir todo el mensaje en un búfer y luego notificar a la rutina principal para escribir los datos en la pantalla LCD.

EDITAR:

La hoja de datos mentiones RCSTA.OERR como indicador de error de saturación. Aunque ya no se menciona en el texto, la hoja de datos dice que se deben verificar los errores en la recepción de un byte y, si hay uno, borrarlo estableciendo RCSTA.CREN (recepción continua habilitada) en 0 (y 1 otra vez).

En cuanto a por qué exactamente tres bytes se reciben correctamente:

Técnicamente, se recibe un byte al insertar los bits en un registro de desplazamiento RSR a la llegada. Una vez que todos los ocho bits están allí, el byte se copia en RCREG , donde espera que su código lo lea.
Si ya hay un byte esperando en RCREG , RSR también espera, pero por supuesto no puede recibir otro byte. Si se recibe un nuevo byte, se abandona, se establece el indicador OERR y el módulo UART deja de funcionar hasta que el código borra el error.
De esta manera, tiene un búfer de dos bytes de largo, que contiene los dos últimos bytes antes de que se produzca el desbordamiento.

Ahora, en su proyecto, el primer byte se recibe en RSR , se copia en RCREG y se lee directamente con el código. El código estará ocupado procesando el byte desde hace años. El segundo byte se recibe y también se copia en RCREG , ya que el primer byte ya fue leído.
El tercer byte también se recibe en RSR , pero no se puede copiar, porque el segundo byte todavía está esperando ... El cuarto byte causa OERR y no se almacena, como otros bytes.

Después de una edad, el código ha terminado de procesarse, lee el segundo byte y comienza a procesarlo. RSR copia el tercer byte en RCREG , donde será procesado por el código una vez más tarde. Pero mientras tanto, no se recibe ningún otro byte.

    
respondido por el sweber

Lea otras preguntas en las etiquetas