• AVR Freaks

Hot![SOLVED] UART transmission send 0xFF instead of last byte

Author
Watchinofoye
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2020/02/06 03:23:22
  • Location: 0
  • Status: offline
2020/02/13 09:53:49 (permalink)
0

[SOLVED] UART transmission send 0xFF instead of last byte

Hello.
 
I'm working on a PIC18F97J60 with the old compiler C18 and MPLAB v8.92 (legacy code, not mine, and porting it to xc8 compiler is absolutely not a priority for the company...) and I encounter a problem with the UART transmission.
The part of program I focus on have to send a Modbus frame via RS485. The program uses EUSART1 for it.
 
One part of the program writes the frame to send in a global buffer and enables the transmission via the register TXEN :

 
for(loc_u8_ind = 0; loc_u8_ind < prm_u8_length; loc_u8_ind++)
{
    u8_rs485_buffer[loc_u8_ind] = prm_ptr_frame[loc_u8_ind];
}
serial.u8_rs485_length = prm_u8_length;
serial.u8_rs485_ptr = 0;
 
 
 
LATJbits.LATJ4 = 1;
TXSTA1bits.TXEN = 1;
 

 
The other part is the interrupt routine. When the flag TX1IF is set, the interrupt routine is in charge to set the parity bit (no parity in my case), and fill the UART register byte after byte via TXREG1. When it's done, TXEN is reset and CREN is set to enable the reception :
 

 
if(PIR1bits.TX1IF == 1)
 
{
    if(serial.u8_rs485_ptr < serial.u8_rs485_length)
 
    {
 
        // Check the parity, 0 in our case [...]
 
        serial.u8_parity = 0;

        TXSTAbits.TX9D = (serial.u8_parity);
        TXREG1 = u8_rs485_buffer[serial.u8_rs485_ptr];
 
        serial.u8_rs485_ptr++;
 
       
 
        if(serial.u8_rs485_ptr >= MODBUS_BUFFER_SIZE)
            serial.u8_rs485_ptr = 0;
 
    }
    else
    {
         serial.u8_rs485_ptr = 0;
         TXSTA1bits.TXEN = 0;
 
         LATJbits.LATJ4 = 1;
         RCSTA1bits.CREN = 1;
    }
    PIR1bits.TX1IF = 0;
 }
 

 
I've checked the registers and all seems correct (EUSART in Asynchronous mode, no parity bit, 8 bit of data, and every byte is written in the TXREG1). But, when I check the frame with a logic analyzer, the last byte is interpreted as a 0xFF. I tried to add and remove bytes and, every time, the last byte is interpreted as 0xFF instead of its correct value. Same thing with the device supposed to communicate with the PIC : the last byte is 0xFF.
 
What do you think it can be ? I suspect there is something more to do for sending the last byte. Can you help me, please ?
 
Best regards.
post edited by Watchinofoye - 2020/02/19 07:58:10
#1

14 Replies Related Threads

    Jerry Messina
    Super Member
    • Total Posts : 465
    • Reward points : 0
    • Joined: 2003/11/07 12:35:12
    • Status: offline
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 13:35:13 (permalink)
    +4 (4)
    A few things...

    You can remove this...
        PIR1bits.TX1IF = 0;
    TXIF cannot be cleared in software... it's controlled by the hardware.

    Now, when you load the TXREG with your last byte, the TXREG gets transferred into the TSR (transmit shift reg) and it will set TXIF again. You'll get another interrupt telling you the TXREG is empty, but your last byte will still be in the TSR being shifted out.
    Your code goes through the 'else' clause of your 'if(serial.u8_rs485_ptr < serial.u8_rs485_length)' where you disable the transmitter (TXEN=0), but since your data is still being shifted out, you get 'FF'

    For the last byte you can't disable the transmitter until the TRMT flag is set, and you have to poll for that outside the TXIF isr.



    #2
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11673
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 13:50:24 (permalink)
    +1 (1)
    LATJbits.LATJ4 = 1;


    Did you  mean to set one of these to 0?
     
    you can't disable the transmitter until the TRMT flag is set

     
    TRMT goes high at the beginning of the stop bit, so it may not be safe to use it directly.
    #3
    ric
    Super Member
    • Total Posts : 26083
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 14:19:02 (permalink)
    +3 (3)
    jtemples
    LATJbits.LATJ4 = 1;


    Did you  mean to set one of these to 0?

    Good catch!
     

    you can't disable the transmitter until the TRMT flag is set

     
    TRMT goes high at the beginning of the stop bit, so it may not be safe to use it directly.



    I agree in principal, but I suspect the OP would get away with it, as plainly their bus is defaulting to the "high" state, as the other end is receiving 0xFF.
    However, that might be a side effect of the direction line not being controlled correctly, as your first point shows.
    To be really safe, you need a one bit time delay after TRMT goes true.
    The baud rate in use has not been mentioned. If it is 9600 baud, then 0.1ms is fine.
    My code usually has a 1ms timer interrupt running, so I just get it to do the swap on the NEXT service after TRMT goes true, which guarantees at least 1ms delay.
     
    I don't see ANY reason to turn TXEN off. Just leave it on. If you need to stop TXIF causing interrupts, clear TXIE.
     
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #4
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11673
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 15:29:30 (permalink)
    +1 (1)
    I don't see ANY reason to turn TXEN off.

     
    I can't think of an application where TXEN = 0 would be useful.
    #5
    ric
    Super Member
    • Total Posts : 26083
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 15:34:11 (permalink)
    +1 (1)
    Would only be if you needed manual control of the TX pin, or wanted to let it float.
    If you ARE going to turn TXEN off, be aware that the TX pin will revert to the level set by the matching LATx register.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #6
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11673
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 15:40:06 (permalink)
    0
    But I don't think TXEN lets you control the pin.  It's one side of an AND gate going into the TSR.  As far as I can tell, it just kills the baud clock and halts the current transmit mid-bit.
    #7
    ric
    Super Member
    • Total Posts : 26083
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 15:50:27 (permalink)
    0
    I must admit, I got that from some older PIC16F datasheets.
    As you say, the PIC18F datasheet doesn't say anything about TXEN controlling the pin.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #8
    jtemples
    عُضْوٌ جَدِيد
    • Total Posts : 11673
    • Reward points : 0
    • Joined: 2004/02/13 12:31:19
    • Location: Southern California
    • Status: offline
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 16:12:17 (permalink)
    +2 (2)
    I see the same TXEN implementation in a 16F877A.  But there was also this:
     
    The transmission can also be started by first loading the TXREG
    register and then setting bit TXEN. This is advantageous when slow
    baud rates are selected since the BRG is kept in Reset when bits TXEN,
    CREN and SREN are clear. Setting enable bit TXEN will start the BRG,
    creating a shift clock immediately.

    #9
    ric
    Super Member
    • Total Posts : 26083
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 16:30:55 (permalink)
    +3 (3)
    It also mentions:

    Clearing enable bit TXEN during a transmission will
    cause the transmission to be aborted and will reset the
    transmitter. As a result, the RC6/TX/CK pin will revert
    to high-impedance.

     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #10
    Aussie Susan
    Super Member
    • Total Posts : 3685
    • Reward points : 0
    • Joined: 2008/08/18 22:20:40
    • Location: Melbourne, Australia
    • Status: offline
    Re: UART transmission send 0xFF instead of last byte 2020/02/13 18:34:45 (permalink)
    +3 (3)
    The only reason I can thing of for playing with the TXEN bit is so that the Tx ISR can handle all of the sending - remembering that setting the TXEN bit will trigger the ISR.
    However the OP seems to forget that the TX ISR is called when the TX *buffer* can receive a new character, not then the last character has been fully sent. The result is, as pointed out above, they are turning off the TX side of the UART way too early.
    Susan 
    #11
    Watchinofoye
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2020/02/06 03:23:22
    • Location: 0
    • Status: offline
    Re: UART transmission send 0xFF instead of last byte 2020/02/14 02:21:30 (permalink)
    0
    First of all, I precise it again : it's not my code. It's a legacy code, written 12 years ago by another developer who left since.
     
    Jerry MessinaYou can remove this...
       PIR1bits.TX1IF = 0;
    TXIF cannot be cleared in software... it's controlled by the hardware.

    OK, I'll change that. Is it just a useless instruction or can it have side effects ? In the last case, it could be a valuable argument for a rewrite of the code.
     
    jtemples
    LATJbits.LATJ4 = 1;
    Did you mean to set one of these to 0?

    ricHowever, that might be a side effect of the direction line not being controlled correctly, as your first point shows.

    Oops, sorry. That's a re-transcription error. It really equals 0 in the code.
     
    Jerry MessinaYour code goes through the 'else' clause of your 'if(serial.u8_rs485_ptr < serial.u8_rs485_length)' where you disable the transmitter (TXEN=0), but since your data is still being shifted out, you get 'FF'

    That's what I thought. It really seemed like it's trying to send something but it's suddenly aborted.
     
    ricI don't see ANY reason to turn TXEN off. Just leave it on. If you need to stop TXIF causing interrupts, clear TXIE.

    As the code is written, if I leave it on, the interrupt will try to send a byte just after it received one. Also, the frame buffer, and the index and length variables are common between reception and transmission.
     
    ricTo be really safe, you need a one bit time delay after TRMT goes true.
    The baud rate in use has not been mentioned. If it is 9600 baud, then 0.1ms is fine.
    My code usually has a 1ms timer interrupt running, so I just get it to do the swap on the NEXT service after TRMT goes true, which guarantees at least 1ms delay.

    The baud rate is 19200. I just (re)tried to set a delay just before setting TXEN to 0, with Delay1KTCYx. And it works ! The frame is finally complete !
    Thank you very much !
    #12
    ric
    Super Member
    • Total Posts : 26083
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: UART transmission send 0xFF instead of last byte 2020/02/14 05:54:06 (permalink)
    +2 (2)
    Watchinofoye
    Jerry MessinaYou can remove this...
     PIR1bits.TX1IF = 0;
    TXIF cannot be cleared in software... it's controlled by the hardware.

    OK, I'll change that. Is it just a useless instruction or can it have side effects ? In the last case, it could be a valuable argument for a rewrite of the code.

    No, it won't have extra side effects, it's just pointless, as that is a read-only flag.
     

    ric
    I don't see ANY reason to turn TXEN off. Just leave it on. If you need to stop TXIF causing interrupts, clear TXIE.

    As the code is written, if I leave it on, the interrupt will try to send a byte just after it received one. Also, the frame buffer, and the index and length variables are common between reception and transmission.

    Not if you clear TXIE instead of TXEN, as I mentioned.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #13
    Watchinofoye
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2020/02/06 03:23:22
    • Location: 0
    • Status: offline
    Re: UART transmission send 0xFF instead of last byte 2020/02/19 03:49:31 (permalink)
    0
    I really would rather do that.
    But it would be necessary to massively rewrite the code just to change little things like that (this code is so [EFF!]ed up...). And, like I said, it's not a priority for the company. sad: sad
     
    So, for the moment, the "solution" is to set a one millisecond delay before resetting TXEN. And I've noted all the remarks in my knowledge base, in case of a code rewriting initiative is taken.
     
    Thanks you again for your help, all.
     
    Do I have to set a flag to "Resolved" or something ?
    #14
    ric
    Super Member
    • Total Posts : 26083
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: UART transmission send 0xFF instead of last byte 2020/02/19 06:06:17 (permalink)
    +2 (2)
    Best you can do is edit the first post in this thread, and add "[SOLVED]" to the subject.
    Please do NOT delete the existing subject.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #15
    Jump to:
    © 2020 APG vNext Commercial Version 4.5