0
\$\begingroup\$

I want to continuously transmit the data on the UART2 of my dsPIC33EP512MU810

. UART2 Tx pin i am configuring it to Pin 51 of the controller which is RP99.

Now the UART output is being converted to RS485 using ST4485EB on board IC. 3 number pin of ST4485EB IC is connected with controller's 55 number pin which is RA2. I am making RA2 pin high to activate the IC.

My board also has a on board crstal TXC 4.00 MFC which is a 4 MHZ crystal.

Trying to configure the UART with baudrate of 38400 8 data bits, 1 stop bit, none parity and none flow control. Using the following code but not getting the desired result. Please help me out with this.

/******************************************************************************/
/* Files to Include                                                           */
/******************************************************************************/

/* Device header file */
#if defined(__XC16__)
    #include <xc.h>
#elif defined(__C30__)
    #if defined(__dsPIC33E__)
        #include <p33Exxxx.h>
    #elif defined(__dsPIC33F__)
        #include <p33Fxxxx.h>
    #endif
#endif
#define FP 40000000
#define BAUDRATE 9600
#define BRGVAL ((FP/BAUDRATE)/16)-1
unsigned int i;
#define DELAY_105uS asm volatile ("REPEAT, #4201"); Nop(); // 105uS delay

#include <stdint.h>        /* Includes uint16_t definition                    */
#include <stdbool.h>       /* Includes true/false definition                  */

unsigned int i;
#define DELAY_105uS asm volatile ("REPEAT, #4201"); Nop(); // 105uS delay

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <xc.h>
#include <float.h>
#include <libpic30.h>
#include <p33Exxxx.h>
#include "system.h"        /* System funct/params, like osc/peripheral config */
#include "user.h"          /* User funct/params, such as InitApp              */

/******************************************************************************/
/* Global Variable Declaration                                                */
/******************************************************************************/

/* i.e. uint16_t <variable_name>; */

/******************************************************************************/
/* Main Program                                                               */
/******************************************************************************/
int16_t main(void)
{

    TRISAbits.TRISA2=0;
    PORTAbits.RA2 = 1;

    RPOR8bits.RP99R = 3; // Assign U2TX peripheral to pin RP84
    RPINR19bits.U2RXR = 19; // Assign pin RPI16 to U2RX peripheral  

    U2MODEbits.STSEL = 0; // 1-Stop bit
    U2MODEbits.PDSEL = 0; // No Parity, 8-Data bits
    U2MODEbits.ABAUD = 0; // Auto-Baud disabled
    U2MODEbits.BRGH = 0; // Standard-Speed mode
    U2BRG = BRGVAL; // Baud Rate setting for 9600
    U2STAbits.UTXISEL0 = 0; // Interrupt after one TX character is transmitted
    U2STAbits.UTXISEL1 = 0;
    IEC1bits.U2TXIE = 1; // Enable UART TX interrupt
    U2MODEbits.UARTEN = 1; // Enable UART
    U2STAbits.UTXEN = 1; // Enable UART TX
    /* Wait at least 105 microseconds (1/9600) before sending first char */
    DELAY_105uS
    U2TXREG = 'a'; // Transmit one character
    while(1)
    {
    }
}

void __attribute__((__interrupt__)) _U2TXInterrupt(void)
{
IFS1bits.U2TXIF = 0; // Clear TX Interrupt flag
U2TXREG = 'a'; // Transmit one character//comment this once testing is done and UART is working.
}

I can see the data on the PC terminal but its not 'a'. Tried different baud rate but none of them is giving me the result 'a' which I am sending.

\$\endgroup\$
3
  • \$\begingroup\$ Your code appears to be configuring the port for 9600 baud, not 38400. \$\endgroup\$
    – Dave Tweed
    Mar 24, 2018 at 13:14
  • \$\begingroup\$ Sorry for got to change the code. I was testing it on various baudrate just to do some troubleshooting this doesnt work with 9600 either. \$\endgroup\$
    – spp
    Mar 26, 2018 at 5:13
  • \$\begingroup\$ screen shot what is happening on the terminal , and in binary if you can \$\endgroup\$
    – ElectronS
    Mar 28, 2018 at 21:43

3 Answers 3

3
+50
\$\begingroup\$

This is most likely a baud rate/clock error. Try capturing the TX line on a scope and measure the baud rate you actually see, compared to what you've programmed. From that you should be able to tell that you're off by a specific ratio, and with any luck that will make it easier to track down the bug.

Since you've tried various baud rates and none look right, you may be unintentionally creating a "non-standard" baud rate. You're using FP = 40000000 (40MHz). Can you confirm the chip is running at 40MHz? I don't see your PLL settings, so I can't say for sure.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You are spot on. While using the scope realized the actual baudrate was 37037 when I configure it for the 38400 and around 8351 for 9600 baud rate. I back calculated the Fp from the results and it found chip is running somewhere at 19MHz. \$\endgroup\$
    – spp
    Mar 29, 2018 at 6:58
  • 1
    \$\begingroup\$ Maybe post your PLL setup code, and we'll be able to get to the bottom of this? \$\endgroup\$
    – Selvek
    Mar 31, 2018 at 5:10
0
\$\begingroup\$

I see that you copied most of the code from the User Manual.

Imgur

It defines FP as 4Mhz and it appears in the calculations of BRGVAL as "4,000,000" whereas yours is 40MHz, "40,000,000".

[Reason of comma usage was to make reading easier, do not c/p them.]

\$\endgroup\$
-1
\$\begingroup\$

You are sending UART data without any idle time. This can cause the receiver to "lock" onto a wrong bit as start bit (any "zero" data bit could be misinterpreted as start bit).

Try sending 0x00 or 0xFF once in a while - these values allow the receiver to re-sync to the sender.

Alternatively you can introduce some idle time (more than 8 bits) - this would also allow correct syncing.

\$\endgroup\$
8
  • \$\begingroup\$ how to put idle time here? \$\endgroup\$
    – spp
    Mar 24, 2018 at 10:41
  • \$\begingroup\$ No idea, I don't use PIC µC. \$\endgroup\$
    – Turbo J
    Mar 24, 2018 at 11:08
  • \$\begingroup\$ You could just use a delay similar to DELAY_105uS... but I doubt it will solve your problem. \$\endgroup\$
    – Selvek
    Mar 28, 2018 at 1:25
  • 1
    \$\begingroup\$ A UART won't 'lock onto' the next 0 as a START bit in a stream and stay there. For each byte rx, it's looking for a 1->0 pattern (STOP->START) followed by 8 bits then a 1 (STOP). No STOP bit means dump Rx byte (framing error) and take next 0 as a START. Again, that must meet framing (...10dddddddd10dddddddd1...). In UART comms, filler bytes/gaps aren't a must for UARTs to correctly sync'. It may waste some bytes while doing so but will correctly sync' to a stream. Downvoting as incorrect, I'm afraid. Try drawing it out on paper, it may surprise you that it's simpler than you've guessed here. \$\endgroup\$
    – TonyM
    Mar 29, 2018 at 8:41
  • \$\begingroup\$ The sequence of 'aaa' is 0011000011001100001100110000110011000011 in 8n1 binary, which could errorously lock on the "longer" runs of zeros. Both start and stop bits would be valid (0 and 1 respectively). The receiver would see a char value of 25decimal. \$\endgroup\$
    – Turbo J
    Mar 29, 2018 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.