I am newly working on Stm32CubeIde and I am trying to understand how it works. I would like to transmit data to a specific address using the UART port and I don't know how to do it. So far I have been able to transmit using these three methods:
using the poll —> HAL_UART_Transmit
using the interrupt —> HAL_UART_Transmit_IT
using DMA —> HAL_UART_Transmit_DMA
but none of them in their implementation refer to transmitting to a specific address.
Can someone help me ?
The UART hardware will transmit a series of high a low voltages onto the wire. RS232 and RS422 are full duplex so there is only a single receiver. RS485 is half duplex so there can be multiple receivers listening to the same data. How that data is framed including which receiver the data is for depends on the higher level protocol like Modbus
Related
IMPORTANT NOTE: I'm aware that UDP is an unreliable protocol. But, as I'm not the manufacturer of the device that delivers the data, I can only try to minimize the impact. Hence, please don't post any more statements about UDP being unreliable. I need suggestions to reduce the loss to a minimum instead.
I've implemented an application C++ which needs to receive a large amount of UDP packets in short time and needs to work under Windows (Winsock). The program works, but seems to drop packets, if the Datarate (or Packet Rate) per UDP stream reaches a certain level... Note, that I cannot change the camera interface to use TCP.
Details: It's a client for Gigabit-Ethernet cameras, which send their images to the computer using UDP packets. The data rate per camera is often close to the capacity of the network interface (~120 Megabytes per second), which means even with 8KB-Jumbo Frames the packet rate is at 10'000 to 15'000 per camera. Currently we have connected 4 cameras to one computer... and this means up to 60'000 packets per second.
The software handles all cameras at the same time and the stream receiver for each camera is implemented as a separate thread and has it's own receiving UDP socket.
At a certain frame rate the software seems miss a few UDP frames (even the network capacity is used only by ~60-70%) every few minutes.
Hardware Details
Cameras are from foreign manufacturers! They send UDP streams to a configurable UDP endpoint via ethernet. No TCP-support...
Cameras are connected via their own dedicated network interface (1GBit/s)
Direct connection, no switch used (!)
Cables are CAT6e or CAT7
Implementation Details
So far I set the SO_RCVBUF to a large value:
int32_t rbufsize = 4100 * 3100 * 2; // two 12 MP images
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rbufsize, sizeof(rbufsize)) == -1) {
perror("SO_RCVBUF");
throw runtime_error("Could not set socket option SO_RCVBUF.");
}
The error is not thrown. Hence, I assume the value was accepted.
I also set the priority of the main process to HIGH-PRIORITY_CLASS by using the following code:
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
However, I didn't find any possibility to change the thread priorities. The threads are created after the process priority is set...
The receiver threads use blocking IO to receive one packet at a time (with a 1000 ms timeout to allow the thread to react to a global shutdown signal). If a packet is received, it's stored in a buffer and the loop immediately continues to receive any further packets.
Questions
Is there any other way how I can reduce the probability of a packet loss? Any possibility to maybe receive all packets that are stored in the sockets buffer with one call? (I don't need any information about the sender side; just the contained payload)
Maybe, you can also suggest some registry/network card settings to check...
To increase the UDP Rx performance for GigE cameras on Widnows you may want to look into writing a custom filter driver (NDIS). This allows you to intercept the messages in the kernel, stop them from reaching userspace, pack them into some buffer and then send to userspace via a custom ioctl to your application. I have done this, it took about a week of work to get done. There is a sample available from Microsoft which I used as base for it.
It is also possible to use an existing generic driver, such as pcap, which I also tried and that took about half a week. This is not as good because pcap cannot determine when the frames end so packet grouping will be sub optimal.
I would suggest first digging deep in the network stack settings and making sure that the PC is not starved for resources. Look at guides for tuning e.g. Intel network cards for this type of load, that could potentially have a larger impact than a custom driver.
(I know this is an older thread and you have probably solved your problem. But things like this is good to document for future adventurers..)
IOCP and WSARecv in overlapped mode, you can setup around ~60k WSARecv
on the thread that handles the GetQueuedCompletionStatus process the data and also do a WSARecv in that thread to comnpensate for the one being used when receiving the data
please note that your udp packet size should stay below the MTU above it will cause drops depending on all the network hardware between the camera and the software
write some UDP testers that mimuc the camera to test the network just to be sure that the hardware will support the load.
https://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancediomethod5e.html
I am trying to understand how to use the Windows API to communicate with RS232/RS422.
I need to interface to some hardware where I don't really have control of the communication protocol, so I am forced to work with this.
I need to set the TX + (pin 3) to high (~5 volts), and the TX - (pin 7) to low (~0 Volts).
I know there is
SetCommBreak
But that puts both pins (3,7) to ~5 volts. I need only pin 3 to be 5 volts, and pin 7 to be ~ 0 volts. Is there a doable way to do this? I would love if I could just control these lines like wire, but is there a way to manipulate the baud rate and transmit data to achieve this? Or any sort of solution?
You can not manipulate the RX and TX pins arbitrarily and without limitations *without writing your own RS485/RS422 protocol is hardcoded on the chip. The reason why you are limited in manipulating the pins when the windows serial driver is loaded ( automatically ) is that the specification of a serial port ( what RS485 / RS 422 is ) requires a specific data structure, i.e. start bits, stop bits, signals like RTS ( ready-to-send ) , ... this required data structure is implemented in the windows serial driver and you can not overwrite it. You can custom your data in a way that the required pin states are produced but your data will always be enveloped in the structure that is required by the serial protocol ( start / stop bits, ... ), cf this graphic from https://en.wikipedia.org/wiki/RS-485
in windows you initialize a serial port in a DCB structure ( https://learn.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_dcb )
within this serial port structures the several protocols that run on RS485 / RS422 are defined like MODBus, ...
you can think of a RS-485/RS-422 serial port as a 'smart file'. 'smart' because of the multiple slaves / addresses that can be accessed. if you write a correct address to the file / serial bus you get an answer, i.e. if you write a 23 what means "Slave 23, send me your register values !"
This overlying protocol is what has to be implemented in software. For this you do not need to manipulate single pins except possibly the control lines like RTS, ... and actually you can not do this without writing your own driver.
An example how to implement MODBus protocol is in http://libmodbus.org/documentation/
The following citation shows that the protocols that run over RS-485 are written over the serial port layer :
You cannot easily craft MODBUS messages "by hand", as you would have
done with ASCII protocols used on RS232: each MODBUS message ends with
a checksum code, computed from the full content of the message. To
exchange MODBUS messages, you must therefore use:
either a specific program provided by the device vendor, with a compatible interface;
or a simple RS485 interface with a programming library which encodes
and decodes MODBUS messages;
or a smart RS485 interface able to
encode and decode by itself the MODBUS messages, such as the Yocto-RS485.
source : http://www.yoctopuce.com/EN/article/a-quick-tutorial-on-rs485-and-modbus
https://social.msdn.microsoft.com/Forums/vstudio/en-US/1751dafb-2fd5-48b8-8c16-08dd95d7db6d/writing-a-string-to-an-rs485-port-vs-2010-c?forum=vcgeneral
As a homework assignment, I wrote UDP server-client application that tries to correct errors in the UDP communication using checksums and through confirming correctly received packets.
The problem is that on localhost, all packets are received without a problem. I tried some packet tampering programs, but they all require communication through network interface.
How to simulate UDP packet loss on localhost loopback address?
UDP is easy to deal with--just write a bit of code in the sender or receiver which drops a certain percentage of the messages, and perhaps occasionally reorders some too.
If you can't modify the actual sender or receiver, it is easy enough to write a third program which simply sits in the middle, forwarding packets with some drops and reordering.
If you're using Linux, you can probably set up iptables to drop packets for you: http://code.nomad-labs.com/2010/03/11/simulating-dropped-packets-aka-crappy-internets-with-iptables/ - this seems like it might work even on loopback ports.
I am writing a data display program where I receive the data through a serial port. The listener is written by others and it is quite complex. Now I need to transfer the received data to another program/pc. So I am thinking of the standard tcp communication from Qt.
Is there any class that come along with the tcp classes that does job like checksum?
If I am transmitting an array of 10 doubles each time but at high frequency. How could I write a client that received all the data correctly without writing those complex algorithms to check the validity of received data bytes?
TCP/IP includes these checks as part of the protocol itself. This includes guarantees for data integrity, as well as the correct re-assembly of data (i.e it will definitely be in the same order). You mentioned that TCP chops the datastream into packets; this is true, but it will re-assemble the packets in the correct order on the receiving end, or request a re-transmission if it needs to do so. All of this is taken care of by the Qt networking classes.
I know that serial ports work by sending a single stream of bits in serial. I can write programs to send and receive data from that one pin.
However, there are a lot more other pins on the serial port connection that normal aren't used but from documentation all seem to have some sort of function for signalling as opposed to data transfer.
Is it possible in any way to cause the other pins that are not used for direct data transfer to be controlled individually? If so, how would i go about doing that?
EDIT: more information
I am working with a modern CPU running windows 7 64-bit on an intel core i7 870 processor. I'm using serial to usb ports because its imposable for me to do anything directly with a usb port and my computer does not come with serial ports and also for some inexplicable reason i have a bunch of these usb to serial port adapters lying around.
My goal is to control mutipul stepper motors (200 steps per rotation, 4 phase motors). My simple circuitry accepts single high pulses and interprets it as a command to cause the motor to rotate one step. The circuit itself will handle the power supply and phase switching. I wish to use the data transfer pin to send the rotation signals (we can control position and velocity by altering the number of high pulses and frequency of high pulses through the pin, however there is no real pulse width modulation).
I have many motors to control but they do not need to be controlled simultaneously. I hope to use the rest of the pins and run them through a simple combination logic circuit to identify which motor is being moved and which direction it is to move in. This is part of the power switching circuitry.
The data transfer pin will operate normally at some low end frequency. However, i want to control the other pins to allow me to give a solid on or off signal (they wont be flipping very quickly, only changes when i switch to controlling another motor).
Based of the suggestion of Hans Passant , I'd like to suggest that you use an Arduino instead of an USB-to-serial converter. The "Duemilanove" is an Arduino-based board that provides 6 PWM outputs (as well as 8 other digitial I/Os and 6 analog). Some more specialized boards might be even cheaper (Arduino Pro Mini, $15 in volume, some soldering required).
Using the handshaking pins to send data can work very well, though probably not on a multitasking OS, it's just very processor intensive (because the port needs to be polled constantly) and requires some custom cables. In fact, back in the day, this is exactly how Laplink got such high transfer rates over serial connections (and why to get those rates you needed a special 'Laplink' cable). And you need both sides of hte link to be aware of what's going on and be able to deal with the custom communications. Laplink would send a packet of data over both the normal UART pins while trying to send data from the other end of the packet over the handshaking pins. If the correct cable wasn't used (or there was some other problem with sending over the handshaking pins) there was no problem - all the data would just get send normally.
Embedded developers might know this as 'bit banging' - often on small embedded systems there's no dedicated UART circuitry - to get serial communications to work they have to toggle a general I/O pin with the correct timing. The same can be done on a UART's handshaking pins. But like I said, it can be detrimental to the system if other work needs to be done.
You can use DTR and RTS only, but that is four possible states. You do need to be careful that the device on the other end uses TTL levels. At he end of this link Serial there are tips on hardware if you need it.
What kind of data rate are you thinking of when you say high frequency? What kind of serial port do you have? With the old 9 pin connectors on the back of the computer the best you can do is around 115Kbps. With a USB adapter I have done test where I could push close to 1Mbps through the port.
Here's an article from Microsoft that goes into great detail on how to work with serial ports:
http://msdn.microsoft.com/en-us/library/ms810467.aspx
It mentions EscapeCommFunction for directly controlling the DTR line.
Before you check out this information, I'm joining in with the others that say a serial port is inappropriate for your application.
I´ve been trying to find an answer to your question for 3 hours, seems like there is no "simple way" to get a simple boolean signal from a computer...
But, there is always a way, and jet, as simple (maybe even stupid) as this may sound, have you considered using the audio jack connector as an output?, It is stereo so you would have 2 outputs available,the programming would is not that difficult. and you don#t need to buy expensive shit to make it work.
If you also need an input, just disassemble a mouse... and bridge the sensors to the servos, probably the most cheap and easiest way of doing it...
Another way would be using the leds for the Num-lock, caps-lock and the dspl-lock on the keyboard, these can be activated using software, and you just need to take a cheap external keyboard, and use the connectors for these 3 leds.
you are describing maybe a parallel port - where you can set bit patterns all at once - then toggle the xmit line to send it all...
Lets take a look from the "bottom up" point of view:
The serial port pins
Pins on the serial port may be connected to a "controller" or directly connected to the processor. In order for the processor to have access (control) the pins, there must be an electrical connection from the pins to the processor. If not, the processor nor the program can control the pins.
Using a serial controller
A controller, such as a USART, would be connected between the serial port and the processor. The controller may function as to convert 8 parallel data bits into serial bitstream. In the big picture, the controller must provide access to the port pins in order for them to be controlled. If it doesn't, the pins can't be accessed. The controller must be connected to the processor in order to control the pins if a controller is connected.
The Processor and the Serial port
Assuming that the pins you want to control are connected to the processor, the processor must be able to access them. Sometimes they are mapped as physical addresses (such as with an ARM processor), or they may be connected to a port (such as the intel 8086). A program would access the pins via a pointer or using a i/o instruction. In some processor, the i/o ports must be enabled and initialized before they can be used.
Support from the OS
Here's a big ticket item: If your platform has an Operating System, the Operating System must provide services to access the pins of the serial port. The services could be a driver or an API function call. If the OS doesn't provide services, you can't access the serial port pins.
Permission from the OS
Assuming the OS has support for the serial port, your program must now have permission to access the port. In some operating systems, permission may only be granted to root or drivers and not users. If your account does not have permission to access the pins, you are not going to read them.
Support from the Programming Language
Lastly, the programming language must have support for the port. If the language doesn't provide support for the port you may have to change languages, or even program in assembly.
Accessing the "unused" pins of a serial port require extensive research into the platform. Not all platforms have serial ports. Serial port access is platform dependent and may change across different platforms.
Ask another, more detailed question and you will get more detailed answers. Please provide the kind of platform and OS that you are using.