Quantcast
Channel: Question and Answer » uart
Viewing all articles
Browse latest Browse all 57

UART Interrupt does not get more than one Char – PIC32MX110F106B

$
0
0

I am really struggling with an UART communication with my PIC32MX110F016. It is the first time I am trying to implement an UART communication with PIC32MX family but I find it difficult and I don’t know why it’s not working properly. So I decided to post all my code in a tutorial way (step-by-step) in order to get some help from you guys. I hope it helps in the future for other people who face the same problem.

So firstly I imported the libraries and declared this microcontoller configs:

#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

Then I implemented my uartconfig() function:

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();
}

Then I have decided to create a command_print function to send data through UART:

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

I have decided to create a struct in order to create a buffer for the TX/RX pin (from now I am just using the 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;

In my interrupt service routine ISR I decided to ignore the U1TX part and clear the flag always. For the U1RX I defined the as:

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));
}
}

Finally my main(void) is defined as:

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);
}

Actually my PIC is running normally and my interrupt is being triggered. What I can not understand is the reason why my code never get more than one character in the RXReg Part (namely U1RXREG) inside the ISR. I am clearing the flag by the end of the ISR and I think everything is well configured. Let me know what should I do to get my frame properly and not only the first character.
I know the UART is well designed and if I will try to send another command than "SF,1" the RX register gives me a different char.

EDIT: I am not achieving what I want. I am losing characters in the interrupt so I connect the CTS + RTS but unfortunately I am not getting better results. Is anybody available to help me with the CTS + RTS configuration for the PIC32mx family? I know I have to cross the CTS with the RTS and the RTS with the CTS from the microcontroller to the “other” component. My problem is more related with the functions/configs do I have to do.


Viewing all articles
Browse latest Browse all 57

Trending Articles