I need to send data over ModBus-RTU (basically RS485) from an nRF52840. For this, I use uarte. The transceiver's transmit enable input is controlled through a GPIO pin, which in turn is controlled from the PPI (NRF_UARTE_EVENT_TXSTARTED and NRF_UARTE_EVENT_TXSTOP events). When I check on the scope, I see a varying time between the enable pin being raised and the start of the actual transfer. For example: in the below capture, the delay between TXD (in blue) and the enable pin (in red) is 23.67 usec, This delay varies from 0 up to one bittime (I've seen a 103 usec delay when transmitting on 9600 bps).
Can I remove these delays or otherwise at least stabilize them so that they always are the same?
This is my code for initialization:
void rs485_init ( void ) { uint32_t task_addr; uint32_t event_address; static bool _init_done = false; nrfx_uarte_config_t uarte_config = NRFX_UARTE_DEFAULT_CONFIG; uarte_config.pseltxd = MODBUS_TX_PIN; uarte_config.pselrxd = MODBUS_RX_PIN; uarte_config.hwfc = NRF_UARTE_HWFC_DISABLED; nrfx_gpiote_out_config_t nrfx_gpiote_out_config = NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE(0); uarte_config.baudrate = NRF_UARTE_BAUDRATE_9600; uarte_config.parity = NRF_UARTE_PARITY_INCLUDED; if (_init_done) nrfx_uarte_uninit(&uarte); APP_ERROR_CHECK(nrfx_uarte_init( &uarte, &uarte_config, uarte_event_handler)); // Init in non-blocking mode if ( !nrfx_gpiote_is_init() ) { nrfx_gpiote_init(); } else { nrfx_gpiote_out_uninit( MODBUS_RTS_PIN ); } // Initialize the RTS pin as output, to be driven from UART TX via PPI APP_ERROR_CHECK(nrfx_gpiote_out_init( MODBUS_RTS_PIN, &nrfx_gpiote_out_config )); nrfx_gpiote_out_task_enable( MODBUS_RTS_PIN ); // Setup PPI to set enable on start of transmission APP_ERROR_CHECK( nrfx_ppi_channel_alloc( &_ppi_channel_start ) ); event_address = nrfx_uarte_event_address_get( &uarte, NRF_UARTE_EVENT_TXSTARTED ); task_addr = nrfx_gpiote_out_task_addr_get( MODBUS_RTS_PIN ); APP_ERROR_CHECK( nrfx_ppi_channel_assign( _ppi_channel_start, event_address, task_addr ) ); nrfx_ppi_channel_enable( _ppi_channel_start ); // Setup PPI to clear enable on end of transmission APP_ERROR_CHECK( nrfx_ppi_channel_alloc( &_ppi_channel_stop ) ); event_address = nrfx_uarte_event_address_get( &uarte, NRF_UARTE_EVENT_TXSTOPPED ); task_addr = nrfx_gpiote_out_task_addr_get( MODBUS_RTS_PIN ); APP_ERROR_CHECK( nrfx_ppi_channel_assign( _ppi_channel_stop, event_address, task_addr ) ); nrfx_ppi_channel_enable( _ppi_channel_stop ); // Receiver initialization removed for brevity _init_done = true; NRF_LOG_INFO( "RS485 initialized" ); }