Thursday, August 13, 2009

UART Example for DSPIC33 (DSPIC33FJ128GP802)

#include <p33FJ128GP802.h>

_FOSC(OSCIOFNC_ON & FCKSM_CSDCMD & POSCMD_NONE);	//Oscillator Configuration (clock switching: disabled;
							// failsafe clock monitor: disabled; OSC2 pin function: digital IO;
							// primary oscillator mode: disabled)
_FOSCSEL(FNOSC_FRCPLL);					//Oscillator Selection PLL
//_FOSCSEL(FNOSC_FRC);					//Oscillator Selection no PLL
_FWDT(FWDTEN_OFF);					//Turn off WatchDog Timer
_FGS(GCP_OFF);						//Turn off code protect
_FPOR(FPWRT_PWR1);					//Turn off power up timer

void InitUART1() {
	// This is an EXAMPLE, so brutal typing goes into explaining all bit sets

	// The HPC16 board has a DB9 connector wired to UART2, so we will
	// be configuring this port only

	// configure U2MODE
	U1MODEbits.UARTEN = 0;	// Bit15 TX, RX DISABLED, ENABLE at end of func
	//U2MODEbits.notimplemented;	// Bit14
	U1MODEbits.USIDL = 0;	// Bit13 Continue in Idle
	U1MODEbits.IREN = 0;	// Bit12 No IR translation
	U1MODEbits.RTSMD = 0;	// Bit11 Simplex Mode
	//U2MODEbits.notimplemented;	// Bit10
	U1MODEbits.UEN = 0;		// Bits8,9 TX,RX enabled, CTS,RTS not
	U1MODEbits.WAKE = 0;	// Bit7 No Wake up (since we don't sleep here)
	U1MODEbits.LPBACK = 0;	// Bit6 No Loop Back
	U1MODEbits.ABAUD = 0;	// Bit5 No Autobaud (would require sending '55')
	U1MODEbits.URXINV = 0;	// Bit4 IdleState = 1  (for dsPIC)
	U1MODEbits.BRGH = 0;	// Bit3 16 clocks per bit period
	U1MODEbits.PDSEL = 0;	// Bits1,2 8bit, No Parity
	U1MODEbits.STSEL = 0;	// Bit0 One Stop Bit
	
	// Load a value into Baud Rate Generator.  Example is for 9600.
	// See section 19.3.1 of datasheet.
	//  U1BRG = (Fcy / (16 * BaudRate)) - 1
	//  U1BRG = (36850000 / (16 * 9600)) - 1
	//  U1BRG = 238.908854 //Round to 239
	
	U1BRG = 239;

	// Load all values in for U1STA SFR
	U1STAbits.UTXISEL1 = 0;	//Bit15 Int when Char is transferred (1/2 config!)
	U1STAbits.UTXINV = 0;	//Bit14 N/A, IRDA config
	U1STAbits.UTXISEL0 = 0;	//Bit13 Other half of Bit15
	//U2STAbits.notimplemented = 0;	//Bit12
	U1STAbits.UTXBRK = 0;	//Bit11 Disabled
	U1STAbits.UTXEN = 0;	//Bit10 TX pins controlled by periph
	U1STAbits.UTXBF = 0;	//Bit9 *Read Only Bit*
	U1STAbits.TRMT = 0;	//Bit8 *Read Only bit*
	U1STAbits.URXISEL = 0;	//Bits6,7 Int. on character recieved
	U1STAbits.ADDEN = 0;	//Bit5 Address Detect Disabled
	U1STAbits.RIDLE = 0;	//Bit4 *Read Only Bit*
	U1STAbits.PERR = 0;		//Bit3 *Read Only Bit*
	U1STAbits.FERR = 0;		//Bit2 *Read Only Bit*
	U1STAbits.OERR = 0;		//Bit1 *Read Only Bit*
	U1STAbits.URXDA = 0;	//Bit0 *Read Only Bit*


	U1MODEbits.UARTEN = 1;	// And turn the peripheral on

	U1STAbits.UTXEN = 1;
	// I think I have the thing working now.
}

int main() {
	ADPCFG = 0xFFFF;				//make ADC pins all digital	
	
	//PLL setup:
	CLKDIVbits.PLLPRE = 0;          // N1=2: PLL VCO Output Divider Select bits; 0 -> /2 (default)
	PLLFBDbits.PLLDIV = 42 - 2;     // M=40: PLL Feedback Divisor bits; 42 - 2 = 40 -> 40 x multiplier
					// (divisor is 2 more than the value)
	CLKDIVbits.PLLPOST = 0;         // N2=2: PLL Phase Detector Input Divider bits; 0 -> /2
	
	//40 x: 73.700000 MHz = 36.850000 MIPS
	//42 x: 77.385 MHz = 38.6925 MIPS
	//43 x: 79.2275 MHz = 39.61375 MIPS
	
	while(OSCCONbits.LOCK != 1);	// Wait for PLL to lock
	RCONbits.SWDTEN = 0;      // Disable Watch Dog Timer
	
	TRISA = 0b00000000;
	TRISB = 0b00000000;
	
	
	asm volatile ("mov #OSCCONL, w1  \n"
				  "mov #0x46, w2     \n"
				  "mov #0x57, w3     \n"
				  "mov.b w2, [w1]    \n"
				  "mov.b w3, [w1]    \n"
				  "bclr OSCCON, #6");
				  

	RPINR18bits.U1RXR = 7;
	RPOR3bits.RP6R = 0b00011;
	
	asm volatile ("mov #OSCCONL, w1  \n"
				  "mov #0x46, w2     \n"
				  "mov #0x57, w3     \n"
				  "mov.b w2, [w1]    \n"
				  "mov.b w3, [w1]    \n"
				  "bset OSCCON, #6");
	

	InitUART1();
	
	while(1) {

		U1TXREG = 'H';
	}
		
	return 0;
}

6 comments:

  1. Dude! you totally saved my day!!!

    Keep up the good work!!! TY A LOT!!!
    I´ve been trying this all day, with no results, until i found your page :D

    PS: sorry about my english

    ReplyDelete
  2. could you explain what this program do, please, I´m a beginner in pic33
    thanks

    ReplyDelete
  3. Thanks for the code, helped a lot,
    i think there is a small bug though, U1BRG = 239; should be U1BRG = 23.9 or rounded U1BRG = 24.

    Best

    ReplyDelete
  4. Hallo, thanks really much for your code! it was helpful to me.
    Only one thing, using it with a dsPIC33FJ64MC802, found out that :
    PLLFBDbits.PLLDIV = 42 - 2; // M=40: PLL Feedback Divisor bits; 42 - 2 = 40 -> 40 x multiplier
    // (divisor is 2 more than the value)
    wasn't correct.
    correct value is 38, that is 40 (the multiplier we want) -2 (not + 2).

    Than your code is to put the character 'H' into the register. can you suggest the best and more simple way to write sequently more characters?

    Thanks, D.

    ReplyDelete
  5. thank you your code really help me.....

    ReplyDelete
  6. It just work good, thank you for your kind post. I am working whit dspic33 series and fits fine for my project.
    I just have a doubt is why I can not use other ports to make the Uart work on them? I have tried configuring others and no way to make them transmit or receive....
    but your information help me a lot.
    Thanks

    ReplyDelete