Electronic – Use UART PIC24FJ64GB002

cpicuart

I am trying to setup a PIC24FJ64GB002 for UART communication in MBLAB using XC16. I am using the USB CDC demo to communicate with a device, and I am trying to relay that information to an arduino using the PIC. I am confused as to what frequency the cpu is running at. I am using an external 8 MHZ crystal, with several bits set in the demo. Bits relating to the oscillator are set here.

#include <p24FJ64GB002.h>
#include "system.h"
#include "usb.h"

/** CONFIGURATION Bits **********************************************/
_CONFIG1(
    WDTPS_PS1 &
    FWPSA_PR32 &
    WINDIS_OFF &
    FWDTEN_OFF &
    ICS_PGx1 &
    GWRP_OFF &
    GCP_OFF &
    JTAGEN_OFF
)

_CONFIG2(
    POSCMOD_HS &
    I2C1SEL_PRI &
    IOL1WAY_OFF &
    OSCIOFNC_ON &
    FCKSM_CSDCMD &
    FNOSC_PRIPLL &
    PLL96MHZ_ON &
    PLLDIV_DIV2 &
    IESO_OFF
)

_CONFIG3(
    WPFP_WPFP0 &
    SOSCSEL_SOSC &
    WUTSEL_LEG &
    WPDIS_WPDIS &
    WPCFG_WPCFGDIS &
    WPEND_WPENDMEM
)

_CONFIG4(
    DSWDTPS_DSWDTPS3 &
    DSWDTOSC_LPRC &
    RTCOSC_SOSC &
    DSBOREN_OFF &
    DSWDTEN_OFF
)

/*********************************************************************
* Function: void SYSTEM_Initialize( SYSTEM_STATE state )
*
* Overview: Initializes the system.
*
* PreCondition: None
*
* Input:  SYSTEM_STATE - the state to initialize the system into
*
* Output: None
*
********************************************************************/
void SYSTEM_Initialize( SYSTEM_STATE state )
{
    //On the PIC24FJ64GB004 Family of USB microcontrollers, the PLL will not power up and be enabled
    //by default, even if a PLL enabled oscillator configuration is selected (such as HS+PLL).
    //This allows the device to power up at a lower initial operating frequency, which can be
    //advantageous when powered from a source which is not gauranteed to be adequate for 32MHz
    //operation.  On these devices, user firmware needs to manually set the CLKDIV<PLLEN> bit to
    //power up the PLL.
    {
        unsigned int pll_startup_counter = 600;
        CLKDIVbits.PLLEN = 1;
        while(pll_startup_counter--);
    }

    switch(state)
    {
        case SYSTEM_STATE_USB_HOST:
            PRINT_SetConfiguration(PRINT_CONFIGURATION_LCD);
            break;

        case SYSTEM_STATE_USB_HOST_CDC_BASIC:
            BUTTON_Enable(BUTTON_USB_HOST_CDC_BASIC);
            PRINT_SetConfiguration(PRINT_CONFIGURATION_LCD);
            break;
    }
}

I then use this function to initialize the UART

void UART_INIT()
{
   AD1PCFGL = 0xFFFF;
   __builtin_write_OSCCONL(OSCCON & 0xbf);
   TRISBbits.TRISB15 = 0;
   __builtin_write_OSCCONL(OSCCON | 0x40);
   RPOR7bits.RP15R = 3;
   U1BRG = 103; //set baud speed
   U1MODE   =   0x8000;  //turn on module
   U1STA    =   0x8400;  //set interrupts
   IEC0bits.U1TXIE = 0;
   IFS0bits.U1RXIF = 0;
   IFS0bits.U1TXIF = 0;
}

And this function to transmit a byte

void send(char c)
{
   while(U1STAbits.UTXBF == 1);
   U1TXREG = c;
}

I am trying to figure out what value FCY should be defined to be. I assumed that it would be 16 MHZ, (96MHz / 3) / 2 but the code did not work at that setting. Could there be another problem in the code?

I am making all pins digital and setting the UART pin as an input with this code

__builtin_write_OSCCONL(OSCCON & 0xbf);
AD1PCFGL = 0xFFFF;
TRISBbits.TRISB15 = 0;
UART_INIT(9600);
__builtin_write_OSCCONL(OSCCON | 0x40);

Finally, I use the functions like this

UART_INIT(9600); 

while(1) 
{ 
send('H'); 
send('e'); 
send('l'); 
send('l'); 
send('o'); 
send(' '); 
send('W'); 
send('o'); 
send('r'); 
send('l'); 
send('d'); 
send('\n'); 
} 

Best Answer

A diagram would help convey what you're doing. I think this is what you have implemented:

"a device" (USB device) <-> USB <-> PIC24FJ64BG002 (USB host) <-> UART <-> Arduino

Let's take a look at the clock options for this part:

enter image description here

Let's also look more closely at the USB-specific clock stuff:

enter image description here

CONFIG2 contains your oscillator-related stuff:

_CONFIG2(
POSCMOD_HS &                      
I2C1SEL_PRI &
IOL1WAY_OFF &
OSCIOFNC_ON &
FCKSM_CSDCMD &
FNOSC_PRIPLL &
PLL96MHZ_ON &
PLLDIV_DIV2 &
IESO_OFF
)

Recapping what we know:

  • Your source crystal is 8 MHz (input from POSC)
  • POSCMOD is set to HS Oscillator Mode
  • FNOSC is set to Primary Oscillator + PLL
  • PLLDIV is set to divide-by-2

Also, from the datasheet:

  • The default setting for CPDIV is 0x00, which is divide-by-1 (32 MHz)

So, what's our conclusion? I would say that unless there's other code messing with the bits somewhere, the situation is as is shown in figure 8.2 - HSPLL is running at 32 MHz (96 MHz USB PLL output, divided by three, then divided by one).

And, because we know that

\$ F_{CY} = \dfrac {F_{OSC}}{2} \$

the answer should be 16 MHz.

Now, to your baud rate formula:

baud = (FCY/(16*baud))-1;

(It's bad practice to have the same variable name on both sides of the equation: the left side should be renamed to BRG or something more like what it is - it's the baud rate generator value, not the baud rate itself.)

If you look up the PIC24 Family Reference Manual for UART, you'll find the values pre-computed for you:

enter image description here enter image description here

By default, BRGH is zero so unless code is messing with it, your baud rate generator should be set to 103 decimal. (Your formula is for BRGH - 0 and with a 16 MHz clock rate agrees with this table.)

I would dare a guess and say that your UART issues, if they persist, aren't clock related...