This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

HowTo use UARTE 250000 8N2 plus TxBreak for DMX512 protocol

I'd like to use a nRF52840's UARTE0 as interface for a DMX512 controler.
For that I'd need to set the interface at 250000 baud with 8N2. But I can't see how to configure 2 stop bits via nrf_uarte_configure(). This function allows to control HWFC and parity but not the number of stop bits, why?
What can I use instead?

In addition the DMX512 protocol would require a break (~100µs LOW, ~12µs HIGH) as lead-in for the following data train (up to 513 bytes).

  • Hi,

    nRF52840 doesn't support two stop bits by hardware. You can ensure two stop bits by using an UART without EasyDMA, sending each new character at timer interrupt. Two stop bits correspond to 44 usec that is 11 bits (1 start + 8 data + 2 stop).

    In addition the DMX512 protocol would require a break (~100µs LOW, ~12µs HIGH) as lead-in for the following data train (up to 513 bytes).

    Just disable UART temporary and send it to TX line as usual GPIO pin.

  • Thanks for the reply.

    In my topic title and text I do refer to UARTE/UARTE0 (using EasyDMA) and the docs do suggest HW support for 2 stop bits here

    Hence I was surprised not to find that the function - apparently targeting the EasyDMA enabled UARTEx interfaces (going by the name nrf_uarte_config() - note the E) - would not allow for that bit to be controled.

    Thanks for the tip about disabling the interface temporarily.

    This works (code written in C++ based Particle.io Wiring dialect)

    uint8_t * const pBase    = (uint8_t *)0x40002000;       // UARTE0 (UARTE1 .. 0x40028000) (doc. 6.34.9)
    uint32_t* const pStartTX = (uint32_t*)&pBase[0x008];    // TASKS_STARTTX write 1 to initiate
    uint32_t* const pStopTX  = (uint32_t*)&pBase[0x00C];    // TASKS_STARTTX write 1 to initiate
    uint32_t* const pEnable  = (uint32_t*)&pBase[0x500];    // ENABLE register (doc. 6.34.9.6 Enable .. 8, Disable .. 0) 
    uint32_t* const pConfig  = (uint32_t*)&pBase[0x56C];    // CONFIG register (doc. 6.34.9.18)
    
    void breakTx(uint32_t duration = 100) {
      *pEnable  = 0;
      pinResetFast(TX);
      delayMicroseconds(duration);
      *pEnable  = 8;                                        // enabling takes ~14µs which should work as DMX512 ABM (~12µs)
    }
    

  • I suspect the low level driver was originally made for the nRF52832-hardware, and have since not been updated with the new features of nRF52840 SPIM peripheral. My suggestion is to manually set this register by NRF_UARTE0->CONFIG |= 0x10 or simliar after config the UARTE0 peripheral through the driver.

  • Thanks, that's what I've done after going down that rabbit hole and it works ;-)

    Are there any chances these extra features will be finding their way into the "SDK" anytime (soon)?

  • It seems to be supported in latest nrfx driver on github (likely not made it into the nRF5 SDK yet):

    https://github.com/NordicSemiconductor/nrfx/blob/master/hal/nrf_uarte.h#L146 

Related