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 while(1) { // 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”.
Example
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.
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.
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:
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:
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:
Best of luck!
Ted
Thanks a lot that solved my problem. Thanks
Great! Thanks for letting me know.
Ted
Pingback: Stepper Motor Control | Cormac McConigley