Electronic – PIC32 UART Reception (Rx) Issue

microchipmicrocontrollerpic

I am trying to build a very basic communication between PIC32MX274F256D and a laptop through a 3.3v usb to ttl converter.

The Transmission of data from PIC32 to serial terminal works fine.
The Reception of data from serial terminal on the other hand, does
not work at all. No interrupts are being used.

  • I have enabled both Tx and Rx in U1CON register.
  • The baud-rate is correct (since I receive correct data in terminal at 115200)
  • Connections are correct
  • Data are being sent correctly from the converter to PIC Rx pin (tested with oscilloscope)
  • I have configured the peripheral pin selection rather…correctly

When I connected the ICD3 debugger though, I noticed that inside the UART receive function, U1STAbits.URXDA flag,that triggers when data is available in Receive buffer, is never triggered and the program stays at that "while" checking loop for ever. Why is this happening since data can be seen on the Rx pin of the microcontroller?

I attach the UART receive function and the main.c file in case you notice something that I don't.

uint8_t uart_RcvString( uint8_t * message, uint8_t maxLength){           // the function returns the number of characters that have been read message
                                                                      // is the character by character array that is received from docklight
    uint8_t numBytes = 0;

    while(numBytes < maxLength){                                 // while message not complete,
        while(!U1STAbits.URXDA);                              // and data is available,
            *message = U1RXREG;                                 // read the data from the 8-bit buffer
        if(*message == '\n' || *message == '\r'){
            *message = '\0';
            break;
        }
        message++;
        numBytes++;   
    }
    return numBytes;
}

The following code is the main. c file. The program stacks in k = uart_RcvString(array, 4); command before while loop.

#pragma config AI2C1 = OFF             // Alternate I/O Select for I2C1 (I2C1 uses the ASDA1/ASCL1 pins)
#pragma config AI2C2 = OFF             // Alternate I/O Select for I2C2 (I2C2 uses the ASDA2/ASCL2 pins)
#pragma config PMDL1WAY = ON           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = ON            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
#pragma config FUSBIDIO = OFF          // USB USID Selection (Controlled by the USB Module)

// DEVCFG2
#pragma config FPLLIDIV = DIV_4         // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_24         // PLL Multiplier (24x Multiplier)
#pragma config FPLLICLK = PLL_POSC      // System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config UPLLIDIV = DIV_4         // USB PLL Input Divider (4x Divider)
#pragma config UPLLEN = ON              // USB PLL Enable (USB PLL Enabled)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 2)
#pragma config BOREN = OFF              // Brown-Out Reset (BOR) Enable (Enable BOR)
#pragma config DSBOREN = OFF            // Deep Sleep BOR Enable (Enable ZPBOR during Deep Sleep Mode)
#pragma config DSWDTPS = DSPS32         // Deep Sleep Watchdog Timer Postscaler (1:2^36)
#pragma config DSWDTOSC = SOSC          // Deep Sleep WDT Reference Clock Selection (Select SOSC as DSWDT Reference Clock)
#pragma config DSWDTEN = OFF            // Deep Sleep Watchdog Timer Enable (Disable DSWDT during Deep Sleep Mode)
#pragma config FDSEN = OFF              // Deep Sleep Enable (Disable DSEN bit in DSCON)

// DEVCFG1
#pragma config FNOSC = SPLL             // Oscillator Selection Bits (Primary Osc (HS,EC, XT))
#pragma config FSOSCEN = ON             // Secondary Oscillator Enable (Enabled)
#pragma config IESO = ON                // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = HS             // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS16384          // Watchdog Timer Postscaler (1:16384)
#pragma config WDTSPGM = ON             // Watchdog Timer Stop During Flash Programming (Watchdog Timer stops during Flash programming)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config SMCLR = MCLR_NORM        // Soft Master Clear Enable (MCLR pin generates a normal system Reset)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

/*
 * 
 */
int main(void) {

    //===============================PERIPHERAL PIN SELECT==============================================
    uint32_t dmaVal, irqVal;
    unlock_OSCCON(&irqVal, &dmaVal);
    OSCCONbits.UFRCEN = 0;   /**< Disable Internal RC Oscillator*/
    CFGCONbits.IOLOCK = 0;   /**< Pin Select Unlock bit*/

    // Configure PIC32 pins as outputs/inputs

    SPI_MISO_PIN = INPUT;       /**< Set RC1  pin as input for the MISO2 pin*/  //    TRISCSET = _TRISC_TRISC1_MASK;  
    SPI_MOSI_PIN = OUTPUT;      /**< Set RA1  pin as output for the MOSI2 pin*/ //    TRISACLR = _TRISA_TRISA1_MASK; 
    SPI_SCK_PIN = OUTPUT;       /**< Set RB14 pin as output for the SCK2 pin*/  //    TRISBCLR = _TRISB_TRISB14_MASK; 

    TRISBCLR = _TRISB_TRISB3_MASK;        /**< Set RB3 pin as output for the UART1 Tx pin*/   
    TRISBSET = _TRISB_TRISB2_MASK;        /**< Set RB2 pin as input for the UART1 Rx pin*/   

    FLASH_CS_PIN = OUTPUT;      /**< Set RA7  pin as output for the flash enable pin*/  // TRISACLR = _TRISA_TRISA7_MASK;
    LORA_CS_PIN = OUTPUT;       /**< Set RA10  pin as output for the LoRa enable pin*/  // TRISACLR = _TRISA_TRISA10_MASK;
    CHGR_CEN_PIN = OUTPUT;      /**< Set RC3 pin as output for the charger enable pin*/ // TRISCCLR = _TRISC_TRISC3_MASK;  

    // Select the peripheral pins (PPS) for UART, SPI, I2C protocols
    U1RXRbits.U1RXR = 0x04;  /**< Place Rx of UART1 to pin RB2*/
    RPB3Rbits.RPB3R = 0x01;  /**< Place Tx of UART1 to pin RB3*/

    SDI2Rbits.SDI2R = 0x06;  /**< Place MISO pin of SPI2 to pin RC1*/
    RPA1Rbits.RPA1R = 0x04;  /**< Place MOSI pin of SPI2 to pin RA1*/
    // SCK1 is placed by default to RB15 pin when the SPI module is enabled

    // SDA1 is placed by default to RB9 pin when the I2C1 module is enabled
    // SCL1 is placed by default to RB8 pin when the I2C1 module is enabled

    CNPUAbits.CNPUA1 = 1; //Enable Weak Pull up ON MOSI Line
    CNPUCbits.CNPUC1 = 1; //Enable Weak Pull up ON MISO Line
    CNPUBbits.CNPUB15 = 1; //Enable Weak Pull up ON SCK Line
    CNPDBbits.CNPDB14 = 1; //Enable Weak Pull Down ON ID PIN so it is not floating

    CFGCONbits.IOLOCK = 1;    /**<Pin Select lock bit*/
    lock_OSCCON(irqVal, dmaVal);

    //====================Peripheral setup=======================

    unsigned char k = 0;
    char b = 0;
    char *array = &b;

    LED_PIN = OUTPUT;
    LED_OFF();   

    uart_Setup();
    I2C_Master_Setup();

    uart_SndString("Give password\n");
    k = uart_RcvString(array, 4);

    if(*(array+0) == 'P' && *(array+1) == 'A' && *(array+2) == 'S' && *(array+3) == 'S')
       uart_SndString("Correct password\n");
    else 
       uart_SndString("Wrong password\n");

    while(1){

        LED_ON();
        _CP0_SET_COUNT(0);
        while(_CP0_GET_COUNT()< 23994230);   // 23994230 = 1 sec
        LED_OFF();
        _CP0_SET_COUNT(0);
        while(_CP0_GET_COUNT()< 5000000);   


    }
    return (EXIT_SUCCESS);
}

Thank you for your time.

Best Answer

Problem Solved!

The pins I use for the UART communication are by default analog inputs. I disabled this function and turned the pins to digital doing this:

ANSELBbits.ANSB2 = 0;
ANSELBbits.ANSB3 = 0;

and it worked fine.

The registers for this is in p.154 of the PIC32MX2xx datasheet Table 12-4