RS-485 with NXP LPC55S69

I’m using the RS-485 field bus in many of my projects: it is very reliable and robust, and easy to implement. And with ModBus there is standardized protocol used in building automation or industrial control applications. For example I’m using the protocol to communicate between battery systems and an EV Charger.

NXP LPC55S69-EVK with RS-485

In this article I show you with an example, how the NXP LPC55S69 can be used with RS-485.

Outline

In this article, I describe how to use the LPC55S69-EVK for communicating over RS-485 (and ModBus if you like). To get you quickly started, I have put an example project on GitHub.

RS-485 is basically a half-duplex serial protocol (like UART) over two wires, with a differential signalling. With a simple protocol or ModBus, it can address and talk to individual nodes on the bus. Because the signal is differential, it is suitable for longer distances up to about 1000 meter, implementing a wired network with multi-drop capabilities.

Wiring

In most of my RS-485 projects I’m using the TI SN65HVD72 bus transceiver:

RS-485 circuit

The bus is terminated on each end with a 120 Ohm resistor with a jumper. To have defined states (e.g. in case of disconnected wires, I usually add optional jumpers for pull-ups and pull-downs as in the schematic below:

Typical RS-485 circuit, for a device on one end of the bus. The pull-up on A and pull-down on B can be added if needed.

In the picture below I have connected the LPC55S69-EVK with the SN65HVD72 transceiver on the green board, and the RS-485 A/B and ground wire is connected to the Sparkfun RS-485-to-USB-CDC converter board I’m using in other projects too.

Wiring of NXP LPC55S69-EVK with RS-485

Muxing

On the LPC side I’m using the UART with FLEXCOMM1, below is the muxing for the Rx, Tx and RTS lines:

Muxing for FlexComm1

The RTS line is used to toggle the RS458_EN line, which puts the transceiver into Rx or Tx mode. In the driver the RTS can be configured to be automatically set by the UART, or toggled manually as a GPIO pin. The enable (or RE/DE on the transceiver) is HIGH active while sending:

RS-485 signals while sending a “hello”

McuLib

The project uses the McuLib on top of the MCUXpresso SDK. The McuLib is a cross-platform driver and utility collection.

McuLib

The RS-485 driver is inside McuLib\src\McuUART485.c, and configured through McuLib/config/McuUart485config.h

Configuration

The driver is configured through macros which can be overwritten or extended.

Below is the main configuration:

/* ---------------------------------------------------------------------------------------*/
/* McuUart485 */
#define McuUart485_CONFIG_USE_RS_485          (1) /* enable RS-458 driver */
#define McuUart485_CONFIG_USE_MODBUS          (0) /* not using Modbus for now */
#define McuUart485_CONFIG_USE_LOGGER          (1) /* add ability to log data to the console */
#define McuUart485_CONFIG_UART_BAUDRATE       (115200) /* baud rate */
#define McuUart485_CONFIG_USE_HW_OE_RTS       (1)  /* use UART hardware RTS pin */

Which useds the following driver settings to use FlexComm1:

  /* using FlexComm1, on LPC55S69-EVK this is on pin 40 (Rx, FC1_RXD_SDA_MOSI_DATA, PIO1_10) and pin 93 (Rx, FC1_TXD_SCL_MISO_WS, PIO1_11) */
  #include "fsl_usart.h"

  #ifndef McuUart485_CONFIG_UART_PARITY
    #define McuUart485_CONFIG_UART_PARITY                 kUSART_ParityDisabled /* or kUSART_ParityEven or kUSART_ParityOdd */
  #endif

  #define McuUart485_CONFIG_UART_DEVICE                   USART1
  #define McuUart485_CONFIG_UART_SET_UART_CLOCK()         CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1)
  #define McuUart485_CONFIG_UART_WRITE_BLOCKING           USART_WriteBlocking
  #define McuUart485_CONFIG_UART_GET_FLAGS                USART_GetStatusFlags
  #define McuUart485_CONFIG_UART_HW_RX_READY_FLAGS        (kUSART_RxFifoNotEmptyFlag | kUSART_RxError)
  #define McuUart485_CONFIG_UART_READ_BYTE                USART_ReadByte
  #define McuUart485_CONFIG_UART_CONFIG_STRUCT            usart_config_t
  #define McuUart485_CONFIG_UART_GET_DEFAULT_CONFIG       USART_GetDefaultConfig
  #define McuUart485_CONFIG_UART_ENABLE_INTERRUPTS        USART_EnableInterrupts
  #define McuUart485_CONFIG_UART_ENABLE_INTERRUPT_FLAGS   (kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable)
  #define McuUart485_CONFIG_UART_IRQ_NUMBER               FLEXCOMM1_IRQn
  #define McuUart485_CONFIG_UART_INIT                     USART_Init
  #define McuUart485_CONFIG_UART_GET_CLOCK_FREQ_SELECT    kCLOCK_Fro12M
  #define McuUart485_CONFIG_UART_IRQ_HANDLER              FLEXCOMM1_IRQHandler
  #define McuUart485_CONFIG_CLEAR_STATUS_FLAGS            USART_ClearStatusFlags

If McuUart485_CONFIG_USE_HW_OE_RTS is set to zero, it uses a normal GPIO pin to control Rx/Tx on the transceiver:

   /* default: pin 92 on LPC55S69-EVK, routed as FC1_I2C_SCL */
    #ifndef McuUart485_CONFIG_TX_EN_GPIO
      #define McuUart485_CONFIG_TX_EN_GPIO       GPIO
    #endif
    #ifndef McuUart485_CONFIG_TX_EN_PORT
      #define McuUart485_CONFIG_TX_EN_PORT       0
    #endif
    #ifndef McuUart485_CONFIG_TX_EN_PIN
      #define McuUart485_CONFIG_TX_EN_PIN        14U
    #endif

If it is set to 1, then it uses the UART hardware to control the CTS pin. The CTS pin is pulled high for sending data, and pulled LOW to be in listening mode. Because the MCUXpresso SDK does not offer an interface to control the needed bits, it is done directly in the driver:

McuUart485_CONFIG_UART_DEVICE->CFG |= USART_CFG_OESEL(1); /* if enabled, use RTS signal for RS-485 transceiver */
McuUart485_CONFIG_UART_DEVICE->CFG |= USART_CFG_OEPOL(1); /* 1: the output enable signal is high active */
McuUart485_CONFIG_UART_DEVICE->CFG |= USART_CFG_OETA(1); /* output enable turnaround time: if set, the output enable signal remains asserted for 1 char time after the end of the last bit */

Usage

The demo application includes a command-line (shell) interface. Open one terminal to the USB CDC VCOM of the on-board debug interface. The ‘help’ command shows all available commands:

Shell interface

Open another terminal on the other side of the bus (in my case, the Sparkfun RS-485 converter). The Sparkfun converter is used to send and receive data on the bus.

To send text from the LPC55S69, use the ‘rs send’ command, and it should show up on the other (Sparkfun) side:

Sending text to the bus

Text send from to the LPC55S69 is shown in the console:

Receiving text from the bus

With this, we know that the communication is working.

Summary

It should not be hard to use the RS-485 bus and Modbus protocol with LPC55S69: In the software an UART needs to be configured to control the RTS line to drive transceiver RE/DE, an on the hardware side I need a transceiver which is used for the differential signal. I’m using the RS-485 successfully in many projects.

I just have covered sending simple text over the bus, but of course there are more features available. For example with ‘rs sendcmd’ you can send commands to an address on the bus and execute them on the remote node, or one can use the Modbus protocol, see the Modbus folder inside the McuLib. Be free to check the source code and the comments in it to explore more features like this.

With this, I hope you find that article useful for your own RS-485 and Modbus applications.

Happy communicating 🙂

Links

What do you think?

This site uses Akismet to reduce spam. Learn how your comment data is processed.