0
votes

I seem to have issue to receive correct bytes from a PC to a PIC18F27J53. The PIC UART is set standard, asynchronous, 8bits, 9600, No parity. The PC is a win 10, I have made a simple UART program, and sending a few ints, all separated by commas, like the following. "123,24,65,98,12,45,564,987,321,0,5.9,87,65,789,123,6554,213,8754\n"

I have tried different ways,

  1. Tried to send each char one by one, however the PIC seems to get stuck midway or early in the transfer and the RX flag doesn't go high anymore.
  2. I have tried to send each int followed by "\n" and my PIC to parse each chars and cut the read after a "\n" is found. This seems better, I can get more data in, but the final received data is corrupted: some ints are wrong etc.

It clearly show this is a sync issue, it looks like the PC is too fast for the PIC? If so, I am looking at having a synchronous uart, however according to the web, this seems to be far from the chosen method, which makes me thing I must have another issue to resolve, in asynchronous mode?

My question, what is the most popular robust way to do that PIC to PC UART full duplex communication?

Here are my PIC receive APIs, fairly standard and simple (I think).

void int_receive_data(void)
{
    char input_element[10] = { 0 };
    char full_rx[128] = { 0 };

    for (int i = 0; i < 22; i++) {
        p18f47j53_uart2_read_text(input_element, sizeof(input_element));
        strncat(full_rx, input_element, strlen(input_element));
        strncat(full_rx, ",", 1);
    }
}
void p18f47j53_uart2_read_text(char *output, uint8_t max_length)
{
    uint8_t c;
    char buffer[64] = { 0 };

    for (uint8_t i = 0; i < max_length; i++) {
        c = p18f47j53_uart2_receive_u8();
        buffer[i] = c;

        if ((c == 10) || (c == '\n')) {
            buffer[i] = 0;
            memcpy(output, buffer, i);
            i = max_length;
        }
    }
}

uint8_t p18f47j53_uart2_receive_u8(void)
{
    // wait for the flag
    while (!PIR3bits.RC2IF);

    // reset receiver if over run error
    if (RCSTA2bits.OERR) {
        RCSTA2bits.CREN = 0;
        RCSTA2bits.CREN = 1;
        return PIC_RC_FAIL;
    }

    // reset if frame error
    if (RCSTA2bits.FERR) {
        RCSTA2bits.SPEN = 0;
        RCSTA2bits.SPEN = 1;
        return PIC_RC_FAIL;
    }

    return RCREG2;
}

On the PC C# side, my sending looks like this

        string[] full_separated = full_tx.Split(',');

        foreach (string s in full_separated)
            my_port.WriteLine(s);

The PIC is running from its internal clock 8MHz. I never tried the synchronous way as it seems more complicated and 99 percent of the web result will show asynchronous way, which makes me think I better debug what I am doing.

Any idea? advice? Thanks

1

1 Answers

0
votes

Well not really a solution, but an alternative. You should break the frame in small chunks. And if possible the receiver to ack with a char to notify the transmitter to go ahead with another chunk.

Reason I am saying that, I have a mikroE dev board with a similar PIC, and while running an "out of the box" example, and sending "111,222,333,444,555,666,777,888,999" It looks like the "999" is creating issues, too much byte, maybe buffer issue, maybe the not perfect baud rate mismatch builds up after a few bytes?

Repeat the sending every 50ms, 500ms or 1000ms doesn't make it better. Changing the baud rate neither. Only removing ",999" and it seems to work all right.

Without the ",999" I am guessing it is still on the "edge of working", so maybe just remove "666,777,888,999" and the communication should feel more comfortable.

More code, more traffic, but at least it works..