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 en forma de tutorial (paso a paso) para obtener ayuda de ustedes. Espero que ayude en el futuro a otras personas que enfrentan el mismo problema.
Entonces, en primer lugar, importé las bibliotecas y declaré las configuraciones de este microcontrolador:
#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();
}
Entonces he decidido crear una command_print
función 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 U1TX
parte y borrar la bandera siempre. Para el U1RX
definí el 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 ejecuta normalmente y se activa mi interrupción. Lo que no puedo entender es la razón por la cual mi código nunca obtiene más de un carácter en la RXReg
Parte (es decir, U1RXREG
) dentro de la ISR. Estoy limpiando la bandera al final de la 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 "SF,1"
el registro 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 obtengo 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.
A una velocidad de transmisión de 115200, sin paridad y con 1 bit de inicio y parada (un total de 10 bits), los datos tardan 86 microsegundos en llegar a su búfer RX desde el otro extremo.
Mirando su ISR, veo que está procesando muchas instrucciones en su ISR.
El escenario que podría estar sucediendo es este: llega tu primer personaje (es decir, "A"),
Se activa la interrupción,
no ha ocurrido ningún error (desbordamiento, paridad, etc.),
ahora tambien llegan el resto de personajes("OK\r\n"),
se establece el indicador de desbordamiento,
borra la interrupción de RX (pero no ingresa ISR nuevamente 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)
3. Evite las llamadas a funciones en el ISR.
4. Puede habilitar la interrupción para errores de desbordamiento de modo que no tenga que escribir explícitamente una rutina para la interrupción. Si se produce un error de desbordamiento, simplemente verifique el estado del indicador de interrupción y borre el indicador y deseche los datos Rx. Esto lo ayudará a reducir el procesamiento de tales errores en el ISR, ya que se pueden verificar en el bucle principal. Simplemente copie los datos recibidos en un búfer e incremente un conteo. Esto podría ayudar.
Pez globo
escafandra autónoma
brahans
escafandra autónoma
justamente
escafandra autónoma
U1RXREG
.pjc50
escafandra autónoma