Search code examples
uartmplabbaud-ratepic32

PIC32MX795F512H UART communication to RS232


I am currently working for the first time with a PIC microcontroller. In the code I specified exactly which PIC, compiler, etc I am using. Maybe this is of help.

I am trying to set up UART communication on the PIC32 and send a hex code like 0x41 for example to a terminal on my computer through RS232. To convert the signal from the PIC UART to RS232 levels I am using a MAX232EPE.

At the moment I am running into the problem that when I send 0x41 for example from the PIC32 to the terminal or vice versa, the received data doesn't match. I think this being caused by a mistake in my baud rate settings, but I am not sure. Could someone please look over my code and see if someone can see a problem? Did I forget to define something? Did I define something wrong? Did I mis calculate the baud rate?

P.S. I know the data being received doesn't match the data send because i checked in the "watches" in debug mode in mplab and when I echo the data send from the terminal to the PIC32 back to the terminal it doesn't match either.

The Delay and interrupt code can be ignored, they are working as expected, so I really believe the problem has to do with the initial setting of the PIC/buad rate.

I hope this is clear enough, any help is very much appreciated

Thanks,

See code below

/*
The configuration below and in void UART1_Init should set up the UART correctly.
I want to achieve a buadrate of 9600. My external Crystal is 8MHz. So:
FPLLIDIV=2, FPLLMUL=20, FPLLODIV=1, FPBDIV=2, FNOSC=PRIPLL, BRGH = 0, and U1BRG = 259.
This should give me the desired baudrate of 9600.
- ((8MHz / 2) * 20)/2) = 40MHz PBclk.
- U1BRG = (PBclk/(16*Buad rate))-1 so 259
- 16*Buad rate because BRGH = 0

PIC32MX795F512H
MPLAB X IDE V3.26
XC32 Compiler
PICKit3
*/

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <plib.h>

// Give useful names to pins
#define LED1_TRIS   TRISDbits.TRISD6
#define LED1        LATDbits.LATD6
#define UART1TX_TRIS    TRISDbits.TRISD3
#define UART1RX_TRIS    TRISDbits.TRISD2

#define FOSC 8000000                // Crystal frequency = 8 MHz
#define SYS_FREQ (80000000UL)       // SYSCLK is 80 MHz
#define GetSystemClock()       (FOSC) // For delay

#pragma config FPLLIDIV=DIV_2       // PLL Input Divider Value (Divide by 2)
#pragma config FPLLMUL=MUL_20       // Phase-Locked Loop (PPL) muiltiplier, multiplier of 20
#pragma config FPLLODIV=DIV_1       // Postscaler for PLL, output divided by 1
#pragma config FPBDIV=DIV_2         // 2 = PBCLK is SYSCLK divided by 2 (80MHz/2 = 40MHz)
#pragma config FWDTEN=OFF           // Watch Dog Timer (WDT) is not enabled. It can be enabled by software
#pragma config CP=OFF               // Code-Protect, 1 = OFF/Disabled
#pragma config BWP=OFF              // Boot Flash Write-protect, 1 = OFF/Disabled
#pragma config POSCMOD=XT           // Primary oscillator configuration, HS = HS Oscillator mode selection
#pragma config FNOSC=PRIPLL         // Oscillator selection, PRIPLL = Primary Oscillator with PLL module
#pragma config OSCIOFNC=OFF         // CLKO output disabled
#pragma config FSOSCEN=OFF          // Disable secondary Oscillator

int UART_RX_Count;                  // Counter variable for the UART1 receiver interrupt
int UART_TX_Count;                  // Counter varible for the UART1 transmitted interrupt  
unsigned char RD_SER_NUM;           // Variable to store command to read serial number
unsigned char UART_RX_OUTPUT;       // Variable to store the UART output
unsigned char i;

void UART1_Init(void){
// UART1 initialization
    U1MODEbits.ON = 1;          // UART1 is enabled
    U1MODEbits.SIDL = 0;        // Continue operation in idle mode
    U1MODEbits.IREN = 0;        // Disable IrDA (IrDA Encoder and Decoder Enable bit)
    U1MODEbits.RTSMD = 1;       // !U1RTS! pin is in Simplex mode, 0 = !U1RTS! pin is in Flow Control mode
    U1MODEbits.UEN = 0;         // UxTX and UxRX pins are enabled and used; UxCTS and UxRTS/UxBCLK pins are controlled by corresponding bits in the PORTx register
    U1MODEbits.WAKE = 1;        // Enable Wake-up on Start bit Detect During Sleep Mode bit
    U1MODEbits.LPBACK = 0;      // UARTx Loopback Mode Select bit, 0 = disabled, loopback = UxTX output is internally connected to the UxRX input
    U1MODEbits.PDSEL = 2;       // Parity and Data Selection bits, 10 = 8-bit data, odd parity
    U1MODEbits.STSEL = 0;       // Stop Selection bit, 0 = 1 stop bit
    U1MODEbits.BRGH = 0;        // High Baud Rate Enable bit, 0 = Standard Speed mode 16x baud clock enabled
    U1MODEbits.RXINV = 1;       // Receive Polarity Inversion bit, 1 = UxRX Idle state is 0

    U1STAbits.URXEN = 1;        // 1 = UART1 receiver is enabled. U1RX pin is controlled by UARTx (if ON = 1)
    U1STAbits.UTXEN = 1;        // 1 = UART1 transmitter is enabled. U1TX pin is controlled by UARTx (if ON = 1)
    U1STAbits.UTXINV = 1;       // Transmit Polarity Inversion bit, 1 = UxTX Idle state is 0
    U1STAbits.ADM_EN = 0;       // 0 = Automatic Address Detect mode is disabled
    U1BRG = 259;                // Baud Rate Divisor bits (0-15 bits), set baud rate, 9600 @ 40 MHz PBclk

    __builtin_disable_interrupts();     // Tell CPU to stop paying attention to interrupts
    INTCONbits.MVEC = 1;                // Multi Vector interrupts
    U1STAbits.URXISEL = 0;              // 0x = Interrupt flag bit is set when a character is received
    U1STAbits.UTXISEL = 1;              // 01 = Interrupt flag bit is set when all characters have been transmitted
    IPC6bits.U1IP = 5;                  // Set UART1 priority 5 of 7
    IPC6bits.U1IS = 0;                  // Set UART1 sub priority to 0
    IFS0bits.U1RXIF = 0;                // Clear UART1 RX interrupt flag
    IFS0bits.U1TXIF = 0;                // Clear UART1 TX interrupt flag
    IEC0bits.U1RXIE = 1;                // Enable UART1 RX ISR
    __builtin_enable_interrupts();      // Tell CPU to start paying attention to interrupts again

    UART_RX_Count = 0;                  // Set initial UART1 received interrupts count to 0
    UART_TX_Count = 0;                  // Set initial UART1 transmit interrupts count to 0
}

void __ISR(_UART_1_VECTOR, IPL5SRS) UART1_INT(void){
    if(INTGetFlag(INT_U1RX)){           // Check if UART1 RX interrupt was triggered
        LED1 = ~LED1;                   // Toggle LED1
        UART_RX_Count++;                // Add 1 to UART1 RX interrupt occurrence counter
//        UART_RX_OUTPUT = U1RXREG;       // Read UART1 RX buffer/register
        U1TXREG = U1RXREG;      // Transmit the received data back
//        U1STAbits.OERR = 0;             // Clear UART1 buffer overflow
        IFS0bits.U1RXIF = 0;            // Clear UART1 RX interrupt flag
    }else{
        if(INTGetFlag(INT_U1TX)){       // Check if UART1 TX interrupt was triggered
            UART_TX_Count++;            // Add 1 to UART1 TX interrupt occurrence counter
            IEC0bits.U1TXIE = 0;        // Disable UART1 TX ISR
            IFS0bits.U1TXIF = 0;        // Clear UART1 TX interrupt flag
        }
}
}

  // DelayMs creates a delay of given milliseconds using the Core Timer
  void DelayMs(WORD delay){
     unsigned int int_status;
     while( delay-- ){
         int_status = INTDisableInterrupts();
         OpenCoreTimer(GetSystemClock() / 200);
         INTRestoreInterrupts(int_status);
         mCTClearIntFlag();
         while( !mCTGetIntFlag() );
     }
     mCTClearIntFlag();
 }

int main(){
    UART1_Init();               // Call the initializations function of UART1
    LED1_TRIS = 0;              // Set the LED1 as an output
    UART1TX_TRIS = 0;           // Set UART1 TX pin as output
    UART1RX_TRIS = 1;           // Set UART1 RX pin as input
    LED1 = 0;                   // Turn off LED1

    while(1){
//        DelayMs(1000);
//        IEC0bits.U1TXIE = 1;            // Enable UART1 TX ISR
//       U1TXREG = 0x41;           // Send command to U1TXREG
    }
return 0;
}

Solution

  • As You are using PIC32MX795F512H, You can use the MPLAB Harmony framework tool for creating your project. So that you need not to play on bit level and stuck in minor error or most probabaly typo error. Its convinient to generate drivers and all framework properly.

    Thanks and regards Ravi