2
votes

I'm writing code to configure the serial port on a pic32 family device. The initialization appears to work for the most part, but I get garbage data in place of the first 6 characters that I write. I noticed, however, that if I add an arbitrarily long wait at the end of the initialization function, this goes away. Is there some register flag that I need to be waiting on at the end of my initialization? My initialization code is below. If it helps, I am basing this initialization off of the UART section in the pic32 reference manual. I added the code below for my transmission function as well. My expected output string is "Hello from the bootloader code.\r\n" but the actual bytes I get are:

00000000  00 00 aa b1 b1 bd 81 66  72 6f 6d 20 74 68 65 20  |.......from the |
00000010  62 6f 6f 74 6c 6f 61 64  65 72 20 63 6f 64 65 2e  |bootloader code.|
00000020  0d 0a


void initializeUART2()
{
    uint32 counter;
    initialized = TRUE;
    U2MODE = 0;
    U2STA = 0;
    U2BRG = 0;

    IEC1bits.U2TXIE = 0;
    IEC1bits.U2RXIE = 0;
    IEC1bits.U2EIE = 0;

    //disable UART transmission before config
    U2STA &= ~UART_TRANSMIT_ENABLED_STATUS_FLAG;

    //disable UART before config
    U2MODE &= ~UART_ENABLED_MODE_FLAG;

    RS232_RS485_TRIS=0; //set to output
    RS232_RS485=0; //select RS-232 mode on MAX3161

    //set baudrate BAUDRATE = CLOCK_FREQUENCY/(16*(U2BRG + 1))
    //solve for U2BRG value
    U2BRG = (UINT16)(((PERIPHERAL_CLOCK_FREQUENCY/UART2_BAUDRATE)/16)-1);

    //set mode to 8 bit no parity
    U2MODE &= ~UART_PARITY_DATA_MODE_BITS;

    //set number of stop bits to 1
    U2MODE &= ~UART_EXTRA_STOP_MODE_BIT_FLAG;

    //enable the UART port
    U2MODE |= UART_ENABLED_MODE_FLAG;

    //enable serial transmission
    U2STA |= UART_TRANSMIT_ENABLED_STATUS_FLAG;

    //without this loop, I get garbage in first 6 bytes of my first message
    counter = 1000;
    while(counter--);
}

void putUART2(uint32 value)
{
    if(!initialized)
    {
        initializeUART2();
    }

    //make sure value is in range of writable values
    value &= UINT32_MASK(8);

    //clear transmit interrupt flag
    IFS1bits.U2TXIF = 0;

    //wait for the transmit buffer to be empty
    while((U2STA & UART_TRANSMIT_STATUS_FLAG) == 0);

    //set the data byte to be written in the write register
    //also starts transmission
    U2TXREG = value;

    //wait for the transmit buffer to be empty
    //both of these waits are necessary to avoid missing bytes
    while((U2STA & UART_TRANSMIT_STATUS_FLAG) == 0);
}
2
The fact that a spin-loop is all you need to stabilize your data should immediate be the red-flag that some kind of rampup or pull up-pull down settling is going on.RufusVS

2 Answers

4
votes

The MAX3161 needs at least 100 ns to stabilize after switching modes to RS232.

Also, these lines:

RS232_RS485_TRIS=0; //set to output
RS232_RS485=0; //select RS-232 mode on MAX3161

should be reversed; set the output, then the direction register to avoid glitches.

2
votes

Suspect the MAX3161 chip, which has charge pumps, needs the additional time to reach stable operating voltages.

It may be only for a bit time or 2, but if a message is sent too early, the serial output is messed until a quiet time occurs.

Lesser candidate: problem is an interaction between this and the unposted send routine.

Note: It's amazing how seeing using info like the unposted "garbage data" may help. Also knowing what the "good" first 6 bytes or so is useful.


[Edit] @Doug Currie is on the right track.

When RS232_RS485_TRIS1 is changed to output, a delay time as he suggest is needed before data is sent. This applies here as well as other place in code.

Further, before RS232_RS485_TRIS1 is changed to input, code needs to insure all the data is completely transmitted. This may be a 10/baud after the the PIC declares the xmit buffer empty. Or check the proper xmit status bit before turning the bus around. (Shift Register empty - names vary depending on compiler.)