Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: Using processor-managed transmitterEnable pin for RS485, on Teensy 3.2

  1. #1

    Using processor-managed transmitterEnable pin for RS485, on Teensy 3.2

    Hi,

    Teensyduino supports the transmitterEnable(pin) on all UARTs for use in applications where you need to signal that Transmission is ongoing. A typical case are RS485 chips but also applies to tri-state buffers.

    Teensyduino implements this in software so you can use any pin as TxEnable.

    There have been some recent reports in the forum of people having issues with the timing of TxEnable and subsequent communication problems (myself included).
    See here https://forum.pjrc.com/threads/57067...e-pin?p=215480 and here https://forum.pjrc.com/threads/56281...tween-2-teensy

    From my thorough investigation so far, one of the solutions is to have Teensy processor manage the Tx Enable pin natively in Hardware. This is something the processor can do with proper UART configuration, which I'll describe below.
    This seems to work correctly and overcome the problems described when using the software implemented transmitterEnable.

    The processor manages TxEnable by configuring the UARTx_MODEM register with the TXRTSE flag. This modifies the RTS pin to work as a TX Enable.

    There is one constraint to using hardware-managed TXEnable:
    you are limited on the pins that can be used for this (which are the UART hardware RTS pins)
    • For Serial 1: can be pins 6 or pin 19 (there may be another pin according to the datasheet but not sure)
    • For Serial2: pin 22 only
    • For Serial 3: pin 2 only

    The pin you choose for TxEnable is the pin that you need to connect to the DE/RE pin of your chip (if RS485) or equivalent, to perform the indication of Active Transmission.

    NOTE: Even though we are re-purposing the UART hardware RTS pin, RTS flow control can still be used because, once again, RTS support is implemented by Teensyduino in software (bit banged), so you can assign the RTS function to any other pin. This means that if you need traditional RTS functionality it is still available, even if using this TxEnable approach.

    Therefore, here is how to enable processor(hardware)-managed TxEnable for RS485 and other transceivers in Teensy 3.2(for other models, refer to the datasheet)

    For Serial1:

    Code:
    Serial1.begin(....)
    
    /* Activation of TxEnable*/
    
    // uncomment ONE of the lines below depending on which pin you want to use for TxEnable on Serial 1 (6 or 19)
    //CORE_PIN6_CONFIG = PORT_PCR_MUX(3);
    //CORE_PIN19_CONFIG = PORT_PCR_MUX(3);
    UART0_MODEM |= (UART_MODEM_TXRTSE | UART_MODEM_TXRTSPOL);
    
    // DON'T issue the Serial1.transmitterEnable(x) instruction as that would turn on the software managed TxEnable and duplicate the functionality (causing malfunction probably)
    
    
    // now use the UART normally.
    // no need to wait for Serial1.flush(). everything is managed by the processor and library
    Serial1.write('a');
    Serial1.write('b');
    ...
    For Serial2:

    Code:
    Serial2.begin(....)
    
    /* Activation of TxEnable*/
    
    // Serial 2 can only use pin 22 for hardware managed TXEnable
    CORE_PIN22_CONFIG = PORT_PCR_MUX(3);
    UART1_MODEM |= (UART_MODEM_TXRTSE | UART_MODEM_TXRTSPOL);
    
    // DON'T issue the Serial2.transmitterEnable(x) instruction as that would turn on the software managed TxEnable and duplicate the functionality (causing malfunction probably)
    
    // now use the UART normally.
    // no need to wait for Serial2.flush(). everything is managed by the processor and library
    Serial2.write('a');
    Serial2.write('b');
    ...
    For Serial3:

    Code:
    Serial3.begin(....)
    
    /* Activation of TxEnable*/
    
    // uncomment ONE of the lines below depending on which pin you want to use for TxEnable on Serial 1 (6 or 19)
    CORE_PIN2_CONFIG = PORT_PCR_MUX(3);
    UART2_MODEM |= (UART_MODEM_TXRTSE | UART_MODEM_TXRTSPOL);
    
    // DON'T issue the Serial3.transmitterEnable(x) instruction as that would turn on the software managed TxEnable and duplicate the functionality (causing malfunction probably)
    
    
    // now use the UART normally.
    // no need to wait for Serial3.flush(). everything is managed by the processor and library
    Serial3.write('a');
    Serial3.write('b');
    ...
    That's it.

    Best Regards
    Pedro

  2. #2
    Hi

    Just a quick update on the instructions above:

    The instructions UARTx_MODEM |= should always be placed AFTER the Serialx.begin().

    If you place them before Serialx.begin, Teensy appears to crash / lock up. I'm unsure as to why this happens (couldn't find anything about this in the documentation), but I'd presume it to be related to UART not being initialized.

    Interestingly, you can issue Serial.end() normally (no need to revert UARTx_MODEM) and Serial.begin() again without any problems. This is probably because Serial.end() does not really undo all that Serial.begin() does; it just stops scanning for characters and disables all interrupts, but keeps clock configuration etc.


    ---

    Further to this, I noticed I have a typo in my previous post regarding the code for Serial3 above. The typo in the Comment. The code itself is correct.
    Nevertheless please see below the updated code block with the corrected commented (correction signaled in Green)

    Code:
    Serial3.begin(....)
    
    /* Activation of TxEnable*/
    
    // Serial 3 can only use pin 2 for hardware managed TXEnable
    CORE_PIN2_CONFIG = PORT_PCR_MUX(3);
    UART2_MODEM |= (UART_MODEM_TXRTSE | UART_MODEM_TXRTSPOL);
    
    // DON'T issue the Serial3.transmitterEnable(x) instruction as that would turn on the software managed TxEnable and duplicate the functionality (causing malfunction probably)
    
    
    // now use the UART normally.
    // no need to wait for Serial3.flush(). everything is managed by the processor and library
    Serial3.write('a');
    Serial3.write('b');

  3. #3
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,413
    The processors are setup such that you must enable access to a subsystem before you use (or even touch) them, or it will fault.

    That is why the first thing that the function serial2_begin does is:
    Code:
    	SIM_SCGC4 |= SIM_SCGC4_UART1;	// turn on clock, TODO: use bitband
    Again each Serial port has it's own clock enable and they may be in different registers... that is they are not all in SIM_SCGC4...

  4. #4
    Hi Kurt

    That makes sense. Wasn't aware of that and thank you for clarifying it!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •