Any example or demo to implement Rs485 on lpc55s69?

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

Any example or demo to implement Rs485 on lpc55s69?

跳至解决方案
2,094 次查看
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

 

 
标签 (1)
0 项奖励
回复
1 解答
2,084 次查看
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 项奖励
回复
18 回复数
1,955 次查看
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 项奖励
回复
1,951 次查看
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 项奖励
回复
1,906 次查看
manasvb
Contributor III
That fine, but can you explain the random/garbage values
0 项奖励
回复
1,900 次查看
ErichStyger
Senior Contributor V

possible reasons:

  • floating pins
  • incorrect bus termination
  • incorrect baud
  • hardware FIFO issues
0 项奖励
回复
1,896 次查看
manasvb
Contributor III
I checked using the mutlimeter, my RTS pin does go to voltage high during Tx
0 项奖励
回复
1,891 次查看
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 项奖励
回复
1,874 次查看
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 项奖励
回复
1,868 次查看
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 项奖励
回复
1,832 次查看
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 项奖励
回复
1,978 次查看
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 项奖励
回复
1,969 次查看
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 项奖励
回复
1,926 次查看
ErichStyger
Senior Contributor V

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

bus termination.png

0 项奖励
回复
2,029 次查看
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 项奖励
回复
1,990 次查看
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 项奖励
回复
2,003 次查看
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 项奖励
回复
2,065 次查看
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 项奖励
回复
2,057 次查看
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 项奖励
回复
2,085 次查看
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 项奖励
回复