Any example or demo to implement Rs485 on lpc55s69?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Any example or demo to implement Rs485 on lpc55s69?

Jump to solution
2,095 Views
manasvb
Contributor III

Am not sure how to use RTS and CTS both in hardware and software and need help regarding the same.

When I do this 

usart_config_t config;
USART_GetDefaultConfig(&config);
config.enableTx = true;
config.enableRx = true;
 
this is just normal UART implemenentation
 
For RS485 I added this 
config.loopback = true;
config.enableHardwareFlowControl = true;
 
This doesnt work though

Then I referred UM
manasvb_0-1690887042264.png

 

This too doesnt clearly state the implentation.

Any help or support is appreciated

Thanks

 

 
Labels (1)
0 Kudos
Reply
1 Solution
2,085 Views
ErichStyger
Senior Contributor V

You might have a look at one of my projects posted here:

https://mcuoneclipse.com/2022/12/31/controlling-an-ev-charger-with-modbus-rtu/

 

I'm using that both for LPC854 and LPC55S69. Check the McuUART485.c, which has a setting

McuUart485_CONFIG_USE_HW_OE_RTS

which defines if you want to use normal GPIO for the RE signal or the hardware RTS.

I only noticed that on LPC using a GPIO is faster:

ErichStyger_1-1690911981472.png

 

than using the hardware RTS pin, maybe there is a delay I missed to configure in hardware.

ErichStyger_0-1690911955130.png

Anyway, both works fine.

The 'magic' trick is to configure the UART using the following flags (they are not accessible through the SDK, so I do it directly:

 

#if McuUart485_CONFIG_USE_HW_OE_RTS
  #if McuLib_CONFIG_CPU_IS_KINETIS /* Kinetis K22FN512 */
  McuUart485_CONFIG_UART_DEVICE->MODEM |= UART_MODEM_TXRTSPOL(1); /* TXRTSPOL: 1: transmitter RTS polarity is active high */
  McuUart485_CONFIG_UART_DEVICE->MODEM |= UART_MODEM_TXRTSE(1);   /* TXRTSE: Transmitter request-to-send enable, 1: RTS asserted before start bit is transmitted and deasserted after stop bit */
  #elif McuLib_CONFIG_CPU_IS_LPC /* LPC845 or LPC55S69 */
  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 */
  #endif
#endif

 

I hope this helps, otherwise I would write up a quick article on my blog (if time permits).

You can find the McuLib here: https://github.com/ErichStyger/McuOnEclipseLibrary/tree/master/lib

Erich

 

View solution in original post

0 Kudos
Reply
18 Replies
1,956 Views
manasvb
Contributor III

I flashed ur project on my board

I used "rs send hi", (dont know why it didnt show up on the serial monitor)

manasvb_0-1691147046729.png

 

On the RS485 recv side it shows this

manasvb_1-1691147211185.png

 

To answer your above question -> without the transceiver, that is using normal uart my flexcom 2 worked, and for pull-up thing, I had used the same transiever for lpc2148 and it worked without the need for pullup

0 Kudos
Reply
1,952 Views
ErichStyger
Senior Contributor V

The reason why you don't see the text in the console view is because it does not implement 'local echo'. This could be configured in other terminals or in the McuShell itself.

0 Kudos
Reply
1,907 Views
manasvb
Contributor III
That fine, but can you explain the random/garbage values
0 Kudos
Reply
1,901 Views
ErichStyger
Senior Contributor V

possible reasons:

  • floating pins
  • incorrect bus termination
  • incorrect baud
  • hardware FIFO issues
0 Kudos
Reply
1,897 Views
manasvb
Contributor III
I checked using the mutlimeter, my RTS pin does go to voltage high during Tx
0 Kudos
Reply
1,892 Views
ErichStyger
Senior Contributor V

A multi-meter does not show you much, especially it won't show glitches or fast changes. You need to check it with an oscilloscope or or with a logic analyzer (best one which can show analog signals too). See the screenshot in my blog as an example.

0 Kudos
Reply
1,875 Views
manasvb
Contributor III

I noticed a strange thing

Firstly, this is my code for rs485

manasvb_1-1691474736529.png

 

manasvb_0-1691474695864.png

 

This is what i got on serial monitor

manasvb_2-1691474761226.png

 

 

The very first time `RS485_Transmit()` is called it shows output correctly, after that its just random characters

(PS: RS485_Transmit() is in while loop with delay of 1sec between two consecutive function calls)

0 Kudos
Reply
1,869 Views
ErichStyger
Senior Contributor V

a) have a look at the signals with your oscilloscope

b) just for making things simpler: for sending you don't need the interrupt, so for testing I would disable/not using it.

0 Kudos
Reply
1,833 Views
manasvb
Contributor III
Hey
Looks like the issue was loose connection

Am using max485 transceiver and if connection is even offset then garbage values are seen.

I am able to get data on DSO as well, ie RTS goes high till Tx sends one block of data, and stays low till next Tx block

Thanks a lot for helping
0 Kudos
Reply
1,979 Views
manasvb
Contributor III

Hey @ErichStyger 

Thank you for dedicating your time in writing the above blog. Help a lot

Please check my pin config in the attached image.

Also I have included the 3 lines of code for RTS.

But again, the problem am facing is garbage value displayed on serial terminal.

(PS: baudrate and other serial settings are not the issue, as the same worked when i used normal uart instead of rs-485)

 

0 Kudos
Reply
1,970 Views
ErichStyger
Senior Contributor V

Maybe your RS-485 transceiver requires a pull-up? Have you checked the signals without the transceiver?

Your muxing looks ok.

Other than that: can you try my code with the EVK using that different FLEXCOM?

0 Kudos
Reply
1,927 Views
ErichStyger
Senior Contributor V

Just in case, this is the usual circuit I'm using:

bus termination.png

0 Kudos
Reply
2,030 Views
manasvb
Contributor III

I got the point now

Am using flexcomm2 which means, this is my rs485_init pins

 

void Init_RS485_Pins() {

  // FC2 -> P1_24
  const uint32_t Rs485_Rx =
      (IOCON_PIO_FUNC1 | IOCON_PIO_MODE_INACT | IOCON_PIO_SLEW_STANDARD |
       IOCON_PIO_INV_DI | IOCON_PIO_DIGITAL_EN | IOCON_PIO_OPENDRAIN_DI);

  IOCON_PinMuxSet(IOCON, 1U, 24U, Rs485_Rx);

  // FC2 -> P1_25
  const uint32_t Rs485_Tx =
      (IOCON_PIO_FUNC1 | IOCON_PIO_MODE_INACT | IOCON_PIO_SLEW_STANDARD |
       IOCON_PIO_INV_DI | IOCON_PIO_DIGITAL_EN | IOCON_PIO_OPENDRAIN_DI);

  IOCON_PinMuxSet(IOCON, 1U, 25U, Rs485_Tx);

  // FC2 -> P1_27
  const uint32_t Rs485_RTS =
      (IOCON_PIO_FUNC1 | IOCON_PIO_MODE_INACT | IOCON_PIO_SLEW_STANDARD |
       IOCON_PIO_INV_DI | IOCON_PIO_DIGITAL_EN | IOCON_PIO_OPENDRAIN_DI);

  IOCON_PinMuxSet(IOCON, 1U, 27U, Rs485_RTS);
}
 
 
and your piece of code I put the same way, something like this 
 
void RS485_Init() {
  usart_config_t config;

  /*
   * config.baudRate_Bps = 115200U;
   * config.parityMode = kUSART_ParityDisabled;
   * config.stopBitCount = kUSART_OneStopBit;
   * config.loopback = false;
   * config.enableTxFifo = false;
   * config.enableRxFifo = false;
   */
  USART_GetDefaultConfig(&config);
  config.baudRate_Bps = RS485_BAUD_RATE;
  config.enableTx = true;
  config.enableRx = true;

  /* attach main clock divide to FLEXCOMM2*/
  CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2);
  USART_Init(RS485, &config, RS485_CLK_FREQ);

  RS485->CFG |= USART_CFG_OESEL(1); /* if enabled, use RTS signal for RS-485 transceiver */
  RS485->CFG |= USART_CFG_OEPOL(1); /* 1: the output enable signal is high active */
  RS485->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 */

  USART_EnableInterrupts(RS485, kUSART_RxLevelInterruptEnable);
  EnableIRQ(FLEXCOMM2_IRQn);
}
 
first i call Init_RS485_Pins() and then RS485_Init()
 
I have written a normal transmit code which runs in a task with period 1 sec, and in the recv interrupt it just loopbacks whatever it recvs.
 
When I keep P1_27(RTS pin) floating I get Tx properly, but Rx loopback doesnt work(please tell me why even Tx should work in this case?)
 
Then when I mux P1_27 with Re and De of my max-485, I get garbage values for Tx and loopback works too, but obviously thats garbage too
 
Please help on this
 
Another thing, in ur reply you stated that
 With writing the CFG register I configure the UART to change the RE pin accordingly, to enable 'Tx' mode, otherwise being always in Rx mode.
Does including those 3 lines in init function do the Tx and Rx mode?
 
0 Kudos
Reply
1,991 Views
ErichStyger
Senior Contributor V

Just in case: I have described my setup here: https://mcuoneclipse.com/2023/08/03/rs-485-with-nxp-lpc55s69/

 

0 Kudos
Reply
2,004 Views
ErichStyger
Senior Contributor V

The three lines configure the RTS pin to go high during sending, and pulling it low (listening mode) otherwise. That's all what it does.

0 Kudos
Reply
2,066 Views
manasvb
Contributor III

@ErichStyger Thanks for the info

 

But I cannot see where you have enabled the hardware flow control

For lpc55s69 there is dedicated rts pin for every uart, and also in config structure there is this member 

enableHardwareFlowControl.
 
I cannot find out where you have used/init it.
0 Kudos
Reply
2,058 Views
ErichStyger
Senior Contributor V

Hi @manasvb ,

the 'magic sauce' is with that code piece I shared, plus muxing the RTS pin:

ErichStyger_0-1690953972069.png

With RS-485, I cannot use 'full' handshaking, as it would require the CTS pin too. But all what I need is the RTS which is connected to both the RE pins of the receiver. With writing the CFG register I configure the UART to change the RE pin accordingly, to enable 'Tx' mode, otherwise being always in Rx mode.

If you want to try it out: I stripped down our university research project and published an example on GitHub you can see it in action:

Examples/MCUXpresso/LPC55S69-EVK/LPC55S69_RS-485

I hope this helps,

Erich

0 Kudos
Reply
2,086 Views
ErichStyger
Senior Contributor V

You might have a look at one of my projects posted here:

https://mcuoneclipse.com/2022/12/31/controlling-an-ev-charger-with-modbus-rtu/

 

I'm using that both for LPC854 and LPC55S69. Check the McuUART485.c, which has a setting

McuUart485_CONFIG_USE_HW_OE_RTS

which defines if you want to use normal GPIO for the RE signal or the hardware RTS.

I only noticed that on LPC using a GPIO is faster:

ErichStyger_1-1690911981472.png

 

than using the hardware RTS pin, maybe there is a delay I missed to configure in hardware.

ErichStyger_0-1690911955130.png

Anyway, both works fine.

The 'magic' trick is to configure the UART using the following flags (they are not accessible through the SDK, so I do it directly:

 

#if McuUart485_CONFIG_USE_HW_OE_RTS
  #if McuLib_CONFIG_CPU_IS_KINETIS /* Kinetis K22FN512 */
  McuUart485_CONFIG_UART_DEVICE->MODEM |= UART_MODEM_TXRTSPOL(1); /* TXRTSPOL: 1: transmitter RTS polarity is active high */
  McuUart485_CONFIG_UART_DEVICE->MODEM |= UART_MODEM_TXRTSE(1);   /* TXRTSE: Transmitter request-to-send enable, 1: RTS asserted before start bit is transmitted and deasserted after stop bit */
  #elif McuLib_CONFIG_CPU_IS_LPC /* LPC845 or LPC55S69 */
  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 */
  #endif
#endif

 

I hope this helps, otherwise I would write up a quick article on my blog (if time permits).

You can find the McuLib here: https://github.com/ErichStyger/McuOnEclipseLibrary/tree/master/lib

Erich

 

0 Kudos
Reply