2020-02-14 04:42 AM
I am using Nucleo-f413zh board. now i want to check whether the modbus rtu will work over it or not. i already have my modbus library but how to start it m not getting. so plzz tell me the basic idea how should I start it from cubemx and thn do coding in MDK ARM.if u have any code plzz share with me so that i can configure that my modbus library is compatible to it or not.
2020-02-14 10:03 AM
For RTU you have some strict requirements on inter-character and inter-frame gap times, since the inter-frame gap is used to mark the end/start of a message.
Ideally you can use DMA transfer to transmit. This will ensure your inter-character gap is at a minimum, no overhead lost to interrupt latency on character interrupts. A TX DMA sends the entire message at once, so all you need to worry about is the line turnaround if you are using a half duplex serial bus, like RS-485. You do have to be careful about sending back-to-back message, like a broadcast followed by a node specific message, to make sure the delay between the end of one message (i.e. last bit shifted out, the TC interrupt on the UART) and the start of the next message is longer than the inter-frame gap for RTU. Make sure you do not use TX buffer empty or DMA complete as the end of TX message event. You have to account for the extra shift out time from the UART, that's why the TC interrupt is there.
Receiving RTU is a bit more complicated. You have to detect the end of a message by the longer gap between incoming bytes. Some STM32s have an RTO, receive time out, which can be used to detect the inter-frame gap. Be careful about using the IDLE UART interrupt since on many STM32s it's only one data byte long, too short to distinguish between inter-character and inter-message gaps. Gap times vary in a non-linear way depending on baud rate so be aware of that also.
I set up a DMA transfer for the TX message, since the exact length is known. After the line turnaround (I use RS-485) I start the DMA transfer, UART TX IRQs disabled. At the end of DMA interrupt I enable the UART TC interrupt to capture the actual, last bit shifted out end of transmission, at which point the line is turned back to receive.
What I've used for RX is a character interrupt for the first byte, then start a DMA for the rest of the message, and terminating the DMA at the RTO timeout, or a hardware timer on older STM32s. ST has an application note on how to configure a timer to terminate RX DMA on a UART for the STM32F1 series, but that requires hardware changes. At the RTO interrupt I stop the DMA and signal a message has arrived. Ideally you'll use a dual "ping-pong" buffering scheme to immediately start another receive while processing the current message.
And being Modbus, you do have to watch out for big/little endian conversions for 16 and 32 bit integers.
Jack Peacock
2020-02-16 06:51 AM
2020-04-15 07:30 AM
I published a book which discusses this very topic on Amazon: https://www.amazon.com/dp/B086PNZF4W
"Tutorial on Modbus RTU Slave Design: How to Design Modbus Slave Device Firmware in C"