2015/02/19 21:58:02
Greetings People,
I am new to PIC family. Previously i was working on 89S8253 processors. I have a new requirement where i need to interface PIC24FJ64GB002/4 to my 89S8253 where my controller(89S8253) will send data to PIC controller on Uart Port. Once PIC receives the data i need to store that data on USB Flash drive. I have come to know that PIC controller can work as usb host and it can also received data on its UART port. My question can i program PIC controller to accept data on UART port and then save that data on USB Flash Drive ? I don't know much about oscillator configuration for PIC controller. Any documents or links might be helpful for me.
Please give some advice.
2015/02/20 09:35:45
The PIC 24F processors are fairly complex and can be confusing at first. I suggest the PIC24F Family Reference Manual (microchip website under "other resources", it has many different sections for each part of the pic). Also the data sheet for the specific processor is a good source. USB operation in the PIC is not a simple task however there is a great deal of code and literature on this forum and also the microchip website on this topic.
Receiving data on the USART and writing to a Flash Drive are certainly in the capability of the processors but will not be a trivial development project, at least n my opinion, especially as a first introduction to these parts.
2015/02/20 10:24:41
...Any documents or links...

The Microchip Libraries for Applications has a demonstration project for a USB - Host - MSD Data Logger.  This uses the USB host stack and the FILEIO stack to talk to a USB Mass Storage Device.  That project just uses a PIC internal timer to cause it to write data to the device periodically.
There are MPLABX project configurations for various devices, including the PIC24FJ64GB004 PIM, which might show you what is involved.
Now, compared to USB and File I/O, the USART part of your application is kind of trivial from a technical point of view, but if you have never programmed a PIC24, the USART I/O might be a good place to start.
But here's my main suggestion:
Try a few simple projects first to make sure the device is operating under your control. (Blink an LED with a delay loop; blink an LED with a timer interrupt; do simple serial data transfers from the PIC UART to your workstation; etc.)
Read the data sheet to see how to set up the clock on the PIC24 in such a way that you can eventually use it for your USB application.
Then get on to the "good stuff" with USB and File I/O.
2015/02/23 21:58:09
Thanks Dave. 
After your suggestion i have decided to start on with a code for UART reception and transmission. I have one question regarding using Tx and Rx pins. How can i map these two pins in my code ? Any suggestions or any links would be of great help. I do have the sample pdf from Microchip describing UART Tx (with interrupt) and Rx (with pooling), but can't see any definitions on using the pins. The code is pretty simple and well explained. I am talking about PIC24FJ64gb002 28 pin DIP package. I would like to use 5v pins. Can i use Pin number 14 i.e. RB5 for Tx/Rx purpose ?
2015/02/24 12:34:29
Read the Data Sheet section about PPS (Peripheral Pin Select) (Section 10.4 of the current Data Sheet for your chip).
Table 10-2 shows what registers are used for the various input pin functions.  In a given register, put the number of an RPn pin in the bit positions for that function.
Table 10-3 shows what function numbers to assign to registers for PPS pins used as outputs.  In a given register (for the particular RPn pin), put the function number shown in that table.
Look at the rest of that section to see the register designations for the given RPn Input and Output stuff.
Here is code used in my PIC24FJ32GB002 project (same assignments work for '64GB002):
I used RP8 for the Uart1 Receive pin and RP7 for Uart1 Transmit.  After reading the section in the Data Sheet you should be able to change the assignments to suit your requirements.
    // For PIC24FJ34GB002/PIC24FJ64GB002
    // Configure Input Functions (Table 10-2)
    // Assign U1RX To Pin RP8 (Pin 17 on the DIP-28)
    RPINR18bits.U1RXR = 8;

    // Configure Output Functions (Table 10-3)
    // Assign U1TX (Function 3) to Pin RP7 (Pin 16 on the DIP-28)
    RPOR3bits.RP7R = 3;

Now, some would recommend using assignments with macros defined in <PPS.H>, and I think that's probably a Good Idea in the long run, but I think it's important to be able to use explicit register assignments, at least for the first time, so that you can really understand the mechanism.  (You have to look at the data sheet anyhow to understand what pins are programmable.)
1.  For input functions, there is a register for that function and you put the programmable pin (RPn) number in that register.  Use any RPn that is defined for the device.  Some devices have RPIn pins defined.  These can only be used for inputs.
2.  For output functions, there is a function number that you put into the appropriate register for that output pin.  Use any RPn that is defined for the device.
  For an input, you assign a PPS pin to a register defined for a specific function.
  For an output, you assign a function number to a register defined for a specific PPS pin.
For your question abour RB5:
Pin 14 (RB5) does not have an RPn designation (so it is not a PPS pin), therefore it can not be used for any of the programmable I/O functions.

2015/02/25 02:36:48
Hey dave,
After reading your reply i have written small UART code.

#include <stdio.h>
#include <stdlib.h>
#include <p24Fxxxx.h>
#include <PPS.h>
#define FP 4000000
#define BAUDRATE 9600
#define BRGVAL ((FP/BAUDRATE)/16)-1
#define Delay_105uS asm volatile ("REPEAT, #4201"); Nop(); //105uS Delay Proc
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void)
IFS0bits.U1RXIF = 0; // Clear Uart1 Rx flag.
U1TXREG = U1RXREG; // Send received char to Tx Buff for Transmission.
void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt(void)
IFS0bits.U1TXIF = 0; // Clear Uart1 Tx flag.
void initUART()
U1MODEbits.STSEL = 0 ; // 1 - Stop bit.
U1MODEbits.USIDL = 0; // Continue operation at Idle state.
U1MODEbits.PDSEL = 0 ; // No Parity. 8-bit Data
U1MODEbits.ABAUD = 0 ; // Auto Baudrate Disabled.
U1MODEbits.BRGH = 0 ; // Standard speed mode.
U1MODEbits.UARTEN = 1 ; // Enable Uart.
U1BRG = BRGVAL ; // Baud Rate setting for 9600.
U1STAbits.UTXISEL0 = 0 ; // Interrupt when transmit buffer becomes empty.
U1STAbits.UTXISEL1 = 1 ;
U1STAbits.URXISEL0 = 1 ; // Interrupt when receive buffer has one
U1STAbits.URXISEL1 = 0 ; // or more than one char.
U1STAbits.UTXEN = 1; // Enable Uart Tx.

// U1STAbits.URXISEL = 0b00; // interrupt flag bit is set when RXBUF is filled whith 1 character
IEC0bits.U1TXIE = 1 ; // Enable uart transmit interrupt.
IEC0bits.U1RXIE = 1 ; // Enable uart receive interrupt.
IFS0bits.U1RXIF = 0; // clear interrupt flag of Rx
IFS0bits.U1TXIF = 0; // clear interrupt flag of Tx
__builtin_write_OSCCONL(OSCCON & 0xbf) ; // Unlock register for pin mapping.
RPINR18bits.U1RXR = 9; // Assign RP9 for Uart 1 Rx.
RPOR3bits.RP7R = 3; // Assign RP7 for Uart 1 Tx.
__builtin_write_OSCCONL(OSCCON | 0x40); // Lock register after mapping.
int main(void) {

Correct me if i am wrong. One major problem is i have not added configuration in the start because i actually don't know what to configure and how to configure. In this I have take FP as 4 MHz so do i need to use external 4MHz crystal or my code will be using internal 4MHz crystal frequency.
2015/02/25 20:16:09
Aussie Susan
That coding style suggests that you are using the C30 compiler. I would get rid of the "stdio" and "stdlib" include statements as they are almost never used (certainly the stdio one) for embedded systems - perhaps for old-style (printing to the console while the program executes) debugging but I've not seen them used for 'production' code.
Normally there are a number of "configuration" macro calls at the start of the code file that holds the 'main' function that are used to set the "power on" configuration of the device. You can alter some of these later on (for example, you may want to start with the FRC oscillator and later switch to an external crystal or to some other configuration that is not available immediately on power up).
The data sheet will tell you the various "config" settings and options - look for a section named "Special Features" or similar. The MPLABx IDE also has a window that lists the config settings  for the processor you are using and has a function that lets you cut-paste the settings into your code. I must admit that I have never used this as I generally work from the devices data sheets directly.
The data sheet will tell you the default (power on) register settings and you should look at the "Oscillator" section in the data sheet at eh OSCCON register. Your device look like it powers up in the FRCDIV mode (the fast RC oscillator with the post-scalar used). The FRC is 8MHz and the default FRC postscalar is 'divide by 2' so you should be running with a 4MHZ clock as you say. The FRC is an "RC" oscillator, not an "internal crystal" and Table 29-19 in the data sheet shows that it typically is +/-0.25%.
My general "style" is to do the following at the start of the "main" function:
- configure the oscillator(s)
- set the PPS (if necessary)
- disable the analog functions on the pins unless I actually want them
- set the I/O configurations
- initialise each peripheral (typically calling an "init" function within the source file for the function)
- go into the "while" loop and get on with the job
2015/02/25 20:55:54
Thanks Susan.
I will try to follow your guidance and will come up if i get stuck up some where else. Thanks again to all for helping me.
2015/02/26 01:59:14
I have re-written the code as per Susan's advice.

#include <p24FJ64GB002.h>
void IOInit()

// Disable analog function of all pins.

// Unlock register for pin mapping.
__builtin_write_OSCCONL(OSCCON & 0xbf) ;
// Assign RP9 for Uart 1 Rx.
RPINR18bits.U1RXR = 9;
// Assign RP7 for Uart 1 Tx.
RPOR3bits.RP7R = 3;
// Lock register after mapping.
__builtin_write_OSCCONL(OSCCON | 0x40);
void UARTInit()
// Value for 9600 baud rate.
U1BRG = 25;
U1MODEbits.UARTEN = 1; // UART1 is Enabled
U1MODEbits.USIDL = 0; // Continue operation at Idlestate
U1MODEbits.IREN = 0; // IrDA En/Decoder is disabled
U1MODEbits.RTSMD = 1; // flow control mode
U1MODEbits.UEN0=0; // Uart1 Tx and Rx pins are enabled and used.
U1MODEbits.WAKE = 0; // Wake-up disabled
U1MODEbits.LPBACK = 0; // Loop-back is disabled
U1MODEbits.ABAUD = 0; // auto baud is disabled
U1MODEbits.RXINV = 0; // No RX inversion
U1MODEbits.BRGH = 0; // low boud rate
U1MODEbits.PDSEL = 0b00; // 8bit no parity
U1MODEbits.STSEL = 0; // one stop bit

U1STAbits.UTXISEL1 = 0; // Tx interrupt mode selection
U1STAbits.URXISEL0 = 1; // Interrupt when a last character is shifted out of Transmit Shift Register. All Tx operations are complete.
U1STA &= 0xDFFF; // clear TXINV by bit masking
U1STAbits.UTXBRK = 0; // sync break tx is disabled
U1STAbits.UTXEN = 1; //transmit is enabled
U1STAbits.URXISEL = 0b00; // interrupt flag bit is set when RXBUF is filled whith 1 character
U1STAbits.ADDEN = 0; // address detect mode is disabled
IFS0bits.U1RXIF = 0; // clear interrupt flag of rx
IFS0bits.U1TXIF = 0; // clear interrupt flag of Tx
IEC0bits.U1TXIE = 1 ; // Enable uart transmit interrupt.
IEC0bits.U1RXIE = 1 ; // Enable uart receive interrupt.
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void)
IFS0bits.U1RXIF = 0; // Clear Uart1 Rx flag.
U1TXREG = U1RXREG; // Send received char to Tx Buff for Transmission.
void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt(void)
IFS0bits.U1TXIF = 0; // Clear Uart1 Tx flag.
int main()


return 0;

Am i going wrong at any place ? According to YTS tutorial on Bluetooth dongle and PIC24FJ64GB002 ,i will be interfacing Max232 on 5v tolerance pin for now. If my code works then next step is to create a file in usb flash drive and write csv data into that file. The current code will echo what ever i send to PIC on its RX pin. As show in the attached image do i need to connect external crystal on pin 9 and 10 ?

Attached Image(s)

2015/02/26 19:58:33
Aussie Susan


 As show in the attached image do i need to connect external crystal on pin 9 and 10 ?

I have edited the above so that the question and the related code are together
In CONFIG2, you have told the chip to use the primary oscillator (FNOSC_PRI) and that it is to expect a crystal in the 12MHz to 24MHz range (POSCMOD_HS). Therefore the answer to your question is "yes". ALso don;t forget the capacitors as well as the crystal.
However, that will give you a system clock frequency of whatever the crystal frequency is.
If we go by your comment - that you are wanting to use the RC oscillator, then set PNOSC_FRC and the POSCMOD to disabled (I don't remember the code by heart - or simply leave this out and it will default to disabled). That wil give you an 8MHz system clock.
Personally I would not bother with unlocking and re-locking the PPS lock capability. The default is for the PPS registers to be available and you can end up in more trouble than you can imagine if you get this wrong.
....i will be interfacing Max232 on 5v tolerance pin for now.

Remember that a 5V tolerant pin means that you can drive it to 5V without damaging the pin BUT *NOT* that it will drive 5V as an output pin. The full name is "5.5V tolerant input pin".
Some devices (and I don't think this is one) will allow you to also use an open collector output pin that can be driven to about 5V - you need to be sure of the device capabilities before you  try this sort of thing.
*In theory*, a "logical high" signal on a 3.3V device should be just high enough for a 5V device to detect it as "high". However you should never rely on this and certainly I would not recommend this for any production quality systems as it makes them very vulnerable to noise on the signal lines
The safest way is to use a level shifter.
I see that you have declared both an Rx and a Tx ISR. This is OK for practice, but for what you want to do I would suggest that you only use the Rx ISR and do not enable the Tx side interrupt.
Better still for now, I would simply test the URXDA bit within the main loop and then transferring the received value to the transmit buffer when it is set. Interrupts can complicate things as you get started.
© 2021 APG vNext Commercial Version 4.5

Use My Existing Forum Account