Interrupción UART no obtiene más de una Char - PIC32MX110F106B

4

Realmente estoy luchando con una comunicación UART con mi PIC32MX110F016 . Es la primera vez que intento implementar una comunicación UART con la familia PIC32MX, pero me resulta difícil y no sé por qué no funciona correctamente. Así que decidí publicar todo mi código de forma tutorial (paso a paso) para obtener ayuda de ustedes. Espero que ayude en el futuro a otras personas que enfrentan el mismo problema.

En primer lugar, importé las bibliotecas y declaré estas configuraciones de microcontroladores:

#pragma config   FNOSC       = FRCPLL
#pragma config   FPLLIDIV    = DIV_2
#pragma config   FPLLMUL     = MUL_20
#pragma config   FPLLODIV    = DIV_2
#pragma config   FPBDIV      = DIV_1
#pragma config   ICESEL      = ICS_PGx2
#pragma config   WDTPS       = PS16384

#define GetSystemClock()        (40000000ul)
#define GetPeripheralClock()    (GetSystemClock())
#define BaudRate   115200

Luego implementé mi función uartconfig ():

void uartconfig(void){
PPSUnLock;                        // Allow PIN Mapping for BLE
  PPSOutput(1, RPA0, U1TX);     // MAP Tx to RA0 set to digital out
  PPSInput (3, U1RX, RPA2);     // MAP Rx to RA2 set to digital in
  PPSOutput(4, RPA3, U1RTS);
  PPSInput (2, U1CTS,RPA1);
PPSLock;                         // Prevent Accidental Mapping

#define UART1TX TRISAbits.TRISA0
#define UART1RX TRISAbits.TRISA2

#define CMD TRISBbits.TRISB5

UART1TX = 0;//output
UART1RX = 1;//input

DDPCONbits.JTAGEN = 0;

UARTConfigure(UART1, UART_ENABLE_PINS_CTS_RTS);
UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
UARTSetDataRate(UART1, GetPeripheralClock(), BaudRate);
UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

INTEnable(INT_SOURCE_UART_RX(UART1), INT_ENABLED);
INTSetVectorPriority(INT_VECTOR_UART(UART1), INT_PRIORITY_LEVEL_2);
INTSetVectorSubPriority(INT_VECTOR_UART(UART1), INT_SUB_PRIORITY_LEVEL_0);

// configure for multi-vectored mode
INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
INTEnableInterrupts();
}

Luego decidí crear una función command_print para enviar datos a través de UART:

void command_print(char *buffer){ 
while(*buffer != (char)0)
{
  while(!UARTTransmitterIsReady(UART1));
  UARTSendDataByte(UART1, *buffer++);
}
UARTSendDataByte(UART1, '\r');
while(!UARTTransmissionHasCompleted(UART1));
}

Decidí crear una estructura para crear un búfer para el pin TX / RX (a partir de ahora solo estoy usando inputBuffer ):

typedef volatile struct UARTBuffer {
char outputBuffer[ UART_INPUT_BUFFER_SIZE ];
char inputBuffer[ UART_OUTPUT_BUFFER_SIZE ];
unsigned short int inputReaderPos;
unsigned short int inputWriterPos;
unsigned short int outputReaderPos;
unsigned short int outputWriterPos;
} UARTBuffer;

UARTBuffer UARTBuffer1;

En mi rutina de servicio de interrupción ISR decidí ignorar la parte U1TX y borrar la marca siempre. Para el U1RX he definido como:

void __ISR(_UART_1_VECTOR, ipl2)UART1HANDLER(void){
char c;
if ( INTGetFlag(INT_U1TX) )
 {
    INTClearFlag(INT_SOURCE_UART_TX(UART1));
}

if ( INTGetFlag(INT_U1RX) )
 {

if( (U1STAbits.OERR == 1) || (U1STAbits.PERR == 1) || (U1STAbits.FERR == 1) ){
    // Ignore
    U1STAbits.OERR = 0;//clears if the Receive buffer has overflowed
    U1STAbits.PERR = 0;//parity error
    U1STAbits.FERR = 0;//framing error
    U1RXREG;
}
else {
    // Check if the buffer is all readed. If so, clear the buffer;
    if( UARTBuffer1.inputWriterPos == UARTBuffer1.inputReaderPos ) {
        UARTBuffer1.inputWriterPos = 0;
        UARTBuffer1.inputReaderPos = 0;
    }
    if (UARTBuffer1.inputWriterPos >= UART_INPUT_BUFFER_SIZE){
        // Buffer overflow
        UARTBuffer1.inputWriterPos = 0;
        UARTBuffer1.inputReaderPos = 0;
    }
    c = U1RXREG;
    UARTBuffer1.inputBuffer[ UARTBuffer1.inputWriterPos++ ] = c;
}
INTClearFlag(INT_SOURCE_UART_RX(UART1));
}
}

Finalmente, mi main(void) se define como:

int32_t main(void) {
__asm__("EI");
UARTBuffer1.inputWriterPos = 0;
SYSTEMConfig(GetSystemClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);

INTEnableSystemMultiVectoredInt(); //enable interrupts

uartconfig();

command_print("SF,1");
while (1);
}

En realidad, mi PIC se está ejecutando normalmente y se está activando mi interrupción. Lo que no puedo entender es la razón por la que mi código nunca obtiene más de un carácter en la parte RXReg (a saber, U1RXREG ) dentro del ISR. Estoy limpiando la bandera al final del ISR y creo que todo está bien configurado. Déjame saber qué debo hacer para obtener mi marco correctamente y no solo el primer carácter. Sé que el UART está bien diseñado y si intento enviar otro comando que no sea "SF,1" , el registro de RX me da un carácter diferente.

EDITAR: No estoy logrando lo que quiero. Estoy perdiendo caracteres en la interrupción, así que conecto el CTS + RTS pero desafortunadamente no estoy obteniendo mejores resultados. ¿Hay alguien disponible para ayudarme con la configuración CTS + RTS para la familia PIC32mx? Sé que tengo que cruzar el CTS con el RTS y el RTS con el CTS del microcontrolador al "otro" componente. Mi problema está más relacionado con las funciones / configuraciones que tengo que hacer.

    
pregunta scuba

1 respuesta

2

A una velocidad en baudios de 115200, sin paridad y 1 inicio & bit de parada (un total de 10 bits), toma 86 microsegundos para que los datos lleguen a su búfer RX desde el otro extremo.

Mirando tu ISR, veo que estás procesando muchas instrucciones en tu ISR.

El escenario que podría estar sucediendo es este: llega tu primer personaje (es decir, "A"),

Se activa la interrupción,

no se ha producido ningún error (desbordamiento, paridad, etc.),

ahora también llegan los demás caracteres ("OK \ r \ n"),

se establece el indicador de desbordamiento,

borras la interrupción de RX (pero no ingresas de nuevo ISR porque no se recibirán más caracteres).

Soluciones de depuración: 1. Utilice el método de control de flujo (ACK para cada byte)

  1. Verifique el tamaño del Rx FIFO de su unidad de control de velocidad (si tiene 16 bytes, entonces no necesita control de flujo. Si no tiene FIFO, necesita control de flujo)

3.Evita las llamadas a funciones en el ISR.

4.Puede habilitar la interrupción para errores de desbordamiento, de manera que no tenga que escribir explícitamente una rutina para la interrupción. Si se produce un error de desbordamiento, simplemente verifique el estado de la bandera de Interrupción y borre la bandera y descarte los datos de Rx. Esto le ayudará a reducir el procesamiento de dichos errores en el ISR, ya que pueden verificarse en el bucle principal. Simplemente copie los datos recibidos en un búfer e incremente un conteo. This podría ayudar.

  1. Reduzca su velocidad en baudios y verifique con su mismo código
respondido por el Akshay Immanuel D

Lea otras preguntas en las etiquetas