A dsPIC program to display bytes received via serial link

I wrote the following short program for the dsPIC30F4011 microcontroller to record a sequence of bytes received via serial link (UART 2) and then print the byte values and the corresponding text string via UART 1. I was using this to verify that another program I had written (SerialSend) was working correctly. SerialSend is a command line application for Windows which is used to transmit arbitrary sequences of bytes via a serial port.

// dsPIC30F4011 program to record bytes received via UART 2
// and then print the byte values and text string via UART 1
// Written by Ted Burke - last updated 16-4-2013

#include <xc.h>
#include <stdio.h>
// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, i.e. 30 MIPS
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

// Function prototype for Timer 1 interrupt service routine
void __attribute__((__interrupt__, __auto_psv__)) _T1Interrupt(void);

int n = 0;
unsigned char buf[100];

int main(void)
	// Setup UART 1
	U1BRG = 48;            // 38400 baud @ 30 MIPS
	U1MODEbits.UARTEN = 1; // Enable UART
	// Setup UART 2
	U2BRG = 48;            // 38400 baud @ 30 MIPS
	U2MODEbits.UARTEN = 1; // Enable UART

	// Configure Timer 1
	// TMR1 is set to zero whenever a byte is received
	// or whenever the buffer is empty. Whenever TMR1
	// reaches PR1, the Timer 1 ISR prints whatever
	// bytes are in the buffer. This creates a timeout,
	// such that when bytes are received, they are stored
	// in the buffer, but when no bytes are received for
	// 100ms, the buffer data is printed.
	PR1 = 46875;          // Set the Timer 1 period to 100ms
	TMR1 = 0;             // Reset Timer 1 counter
	IEC0bits.T1IE = 1;    // Enable Timer 1 interrupt
	T1CONbits.TCKPS = 2;  // Prescaler (0=1:1, 1=1:8, 2=1:64, 3=1:256)
	T1CONbits.TON = 1;    // Turn on Timer 1

	_TRISD0 = 0; // Make RD0 a digital output

		// Don't let TMR1 increase unless bytes are in buffer
		if (n == 0) TMR1 = 0;

		// Check if any characters were received via UART
		if (U2STAbits.URXDA == 1)
			// Store received byte and increment byte counter
			buf[n++] = U2RXREG;
			TMR1 = 0;

	return 0;

// Timer 1 interrupt service routine prints the buffer contents.
// This runs when there are bytes stored in the buffer, but none
// have been received for 100ms.
void __attribute__((__interrupt__, __auto_psv__)) _T1Interrupt(void)
	int m;

	// Clear Timer 1 interrupt flag
	IFS0bits.T1IF = 0;

	// Print bytes as numbers in hex format
	for (m=0 ; m<n ; ++m) printf("%02x ", buf[m]);

	// Print the same bytes again as a text string
	buf[n] = '\0';
	printf("\n%s\n", buf);

	// Reset the buffer byte count
	n = 0;

I compiled the program above with Microchip’s XC16 C compiler using the following simple build script.

xc16-gcc main.c -mcpu=30F4011 -Wl,--script=p30F4011.gld
if errorlevel 0 xc16-bin2hex a.out

To use the build script, just create a new folder, save the C program above in the folder as “main.c”, save the build script above as “build.bat” in the same folder, and then open a command window and type “build.bat”.


The following screenshot shows SerialSend running twice in a command window. The serial device used (COM22) is a USB-to-serial converter which is connected to the Tx and Rx pins of UART 2 on the dsPIC.

SerialSend running twice in a console window

The following screenshot shows the UART tool window in the PICkit 2 software application. The PICkit 2 hardware is connected to the Tx and Rx pins of UART 1. The byte sequences sent in the previous screenshot have been received by the dsPIC on UART 2 and, after a 100ms timeout, printed out via UART 1 and displayed in the UART tool.

Screenshot of the PICkit 2 UART tool showing byte values printed by the dsPIC via UART 1

This entry was posted in Uncategorized. Bookmark the permalink.

5 Responses to A dsPIC program to display bytes received via serial link

  1. Shyamal says:

    Hi, recently I wrote a program for UART2 which is identical to the program written for UART1. Program written for UART1 works but that for UART2 doesn’t. I tried to pinpoint the problem but in vain. I think there is some problem with this particular chip though I don’t have an extra chip to confirm my doubt.

    Can you please check it on your chip?

    The code which I am using is as follows:

    /* UART program 
    Note: Fosc = 20MHz   */
    // FOSC
    #pragma config FPR = HS                 // Primary Oscillator Mode (HS)
    #pragma config FOS = PRI                // Oscillator Source (Primary Oscillator)
    #pragma config FCKSMEN = CSW_FSCM_OFF   // Clock Switching and Monitor (Sw Disabled, Mon Disabled)
    // FWDT
    #pragma config FWPSB = WDTPSB_16        // WDT Prescaler B (1:16)
    #pragma config FWPSA = WDTPSA_512       // WDT Prescaler A (1:512)
    #pragma config WDT = WDT_OFF            // Watchdog Timer (Disabled)
    // FBORPOR
    #pragma config FPWRT = PWRT_OFF         // POR Timer Value (Timer Disabled)
    #pragma config BODENV = BORV27          // Brown Out Voltage (2.7V)
    #pragma config BOREN = PBOR_ON          // PBOR Enable (Enabled)
    #pragma config LPOL = PWMxL_ACT_HI      // Low-side PWM Output Polarity (Active High)
    #pragma config HPOL = PWMxH_ACT_HI      // High-side PWM Output Polarity (Active High)
    #pragma config PWMPIN = RST_IOPIN       // PWM Output Pin Reset (Control with PORT/TRIS regs)
    #pragma config MCLRE = MCLR_DIS         // Master Clear Enable (Disabled)
    // FGS
    #pragma config GWRP = GWRP_OFF          // General Code Segment Write Protect (Disabled)
    #pragma config GCP = CODE_PROT_OFF      // General Segment Code Protection (Disabled)
    // FICD
    #pragma config ICS = ICS_PGD            // Comm Channel Select (Use PGC/EMUC and PGD/EMUD)
     void serial_init();
    int main()
    //OSCCON: Oscillator Control Register
    OSCCONbits.COSC = 0b11;		//11 = Primary oscillator ,oscillator status bit
    OSCCONbits.POST = 0b00;		//00 = Oscillator postscaler does not alter clock
    OSCCONbits.OSWEN = 0; 	//Does not initiate clock switch
    OSCCONbits.LPOSCEN = 0;		//0 = LP oscillator is disabled
    printf("\nHello world ");
    return 0;
    void serial_init()
    	U2MODEbits.UARTEN = 1; //Enables UART
    	U2MODEbits.USIDL = 0;
    	//0 = Continue operation in Idle mode
    	U2MODEbits.PDSEL = 0b00;
    	//00 = 8-bit data, no parity
    	U2MODEbits.STSEL = 0;
    	//0 = 1 Stop bit
    	U2STAbits.UTXISEL = 1;
    	//1 = Interrupt when a character is transferred to the Transmit Shift register and as result, the transmit buffer becomes empty
    	U2STAbits.UTXBRK = 0;
    	//0 = UxTX pin operates normally
    	U2STAbits.UTXEN = 1;
    	//1 = UART transmitter enabled, UxTX pin controlled by UART (if UARTEN = 1)
    	U2STAbits.URXISEL = 0b00;
    	//0x =Interrupt flag bit is set when a character is received
    	U2BRG = 32;  //	UXBRG = [Fcy/(16* Baudrate)] - 1 , where Fcy = Fosc/4 
    	// 9600 Baudrate
    • batchloaf says:

      Hi Shyamal,

      I think the problem here is that you’re using the printf function which uses UART1 by default. This also applies to other stdio.h functions. You can change the default UART by setting the value of the global variable __C30_UART.

      For example, try putting this line at the start of your main function:

      __C30_UART = 2;

      From that point on, printf and other stdio.h functions will use UART 2 by default. Hopefully that will solve your problem.

      By the way, I’m not sure which header file __C30_UART is defined in. You may also need this at the top of your program:

      #include <libpic30.h>

      Best of luck!

  2. shyamal says:

    Thanks a lot that solved my problem. Thanks

  3. Pingback: Stepper Motor Control | Cormac McConigley

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s