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.