When we study microcontrollers, the first thing we may encounter is lighting up (GPIO), and then comes the serial port (UART).
The serial port is a commonly used communication interface and is a necessary knowledge to master in embedded systems. However, I have found that many friends only know how to use the serial port to output or print some data, but do not know how to use the serial port for data transmission and communication.
Here I will share with you the serial communication protocol, custom communication protocol, and the principles of implementation.
What is a Communication Protocol?
A communication protocol is not difficult to understand; it is a protocol that must be followed for communication between two (or more) devices.
The explanation from Baidu Baike:
A communication protocol refers to the rules and agreements that both parties must follow to complete communication or service. Multiple data communication systems connected through communication channels and devices in different geographical locations must have a common language to work together to achieve information exchange and resource sharing. What to communicate, how to communicate, and when to communicate must follow some mutually acceptable rules. This rule is the communication protocol.
Many readers must have purchased some modules based on serial communication. Many of the modules on the market use custom communication protocols, some of which are relatively simple, while others are a bit more complex.
Here is a very simple example of a serial communication protocol: for instance, transmitting only a temperature value, which consists of only three bytes:
Doesn’t this seem very simple? It is also a type of communication protocol.
However, this communication protocol is relatively simple in application (between two devices), and it has many drawbacks.
Problems with Simple Communication Protocols
The aforementioned three-byte communication protocol is understood by everyone. Although it can communicate and transmit data, it has a series of problems.
For example: How do you determine who to transmit to when multiple devices are connected on a single bus (like RS-485)? (No device information)
Additionally: In an interference environment, can you ensure the correctness of the transmitted data? (No verification information)
Furthermore: If I want to transmit multiple data of uncertain length, what should I do? (No length information).
Friends who have done custom communication will understand this series of problems.
Therefore, more ‘protocol information’ must be agreed upon in communication protocols to ensure the integrity of communication.
Common Contents of Communication Protocols
Serial-based communication protocols usually cannot be too complex due to serial communication speed, anti-interference capability, and other factors. Compared to TCP/IP communication protocols, it is a lightweight communication protocol.
Thus, in serial communication, besides some common communication protocols (like Modbus, MAVLink), engineers often customize communication protocols according to their project needs.
Below, I will briefly describe some key points of common custom communication protocols.
(Note: These are some common protocol contents; the actual protocol contents may vary in different situations)
The frame header is the beginning of a frame of communication data.
Some communication protocols have only one frame header, while others have two, such as: 5A, A5 as frame headers.
The device address or type is usually used between multiple devices to facilitate distinguishing different devices.
This situation requires describing various device type information in the protocol or appendix to facilitate developers in coding and querying.
Of course, some fixed communication between two devices may not have this option.
Commands/instructions are quite common; generally, different operations are distinguished by different commands.
For example: Temperature: 0x01; Humidity: 0x02;
4. Command Type/Function Code
This option further supplements the command. For example: read or write operations.
For example: Read Flash: 0x01; Write Flash: 0x02;
The data length option may be placed before the device address in some protocols, counting command information as part of the ‘length’.
This is mainly to facilitate the protocol (receiving) parsing, to count the length of received data.
For example: Sometimes you need to transmit a valid piece of data, sometimes you need to transmit multiple valid data, or even transmit an array of data. In this case, the transmission of a frame of data is variable-length data, which must have [ data length ] to constrain it.
Some lengths are one byte, with a range of: 0x01 ~ 0xFF, while others may require more to be transmitted at once, using two bytes, with a range of 0x0001 ~ 0xFFFFF.
Of course, some communication lengths are fixed (for example, only transmitting temperature and humidity data), and their protocols may not have this option.
Data does not need further description; it is the actual data you are transmitting, such as temperature: 25℃.
Some protocols may not have a frame tail; this should be an optional part.
The checksum is a relatively important content; generally, more formal communication protocols have this option. The reason is simple: communication is easily affected by interference or other reasons, leading to transmission errors.
If there is a checksum, it can effectively prevent data transmission errors.
There are many ways to calculate the checksum, with checksum and CRC checks being relatively common methods used in custom protocols.
Additionally, some protocols may place the checksum second to last, with the frame tail at the last position.
Code Implementation of Communication Protocol
There are many ways to implement custom communication protocols in code. How to say, ‘All roads lead to Rome’; you just need to write implementation code according to your protocol.
Of course, while implementing, you need to consider the actual situation of your project. For example, if there is a lot of communication data, you may need to use a message queue (FIFO). Additionally, if the protocol is complex, it is best to encapsulate structures, etc.
Below, I will share some code I have used before. It may not describe more details, but some ideas can be referenced.
1. Message Data Sending
(1) Directly Send Each Byte Through the Serial Port
This is something even beginners can understand. Here is an example from a previous DGUS serial screen:
(2) Send via Message Queue
On the basis above, use a buffer to hold the message, then ‘package’ it into the message queue and send it out via the message queue method (FIFO).
(3) Use ‘Structure’ Instead of ‘Array SendBuf’
Structures are more convenient for referencing and managing than arrays; therefore, using structures is a higher-level and more practical method compared to arrays. (Of course, if there are many members, using temporary variables can lead to excessive stack usage.)
For example:
(4) More Other Methods
There are many ways to send data via serial port, such as using DMA instead of the message queue method.
2. Message Data Receiving
Serial message reception is usually done through serial interrupt reception, although there are rare cases where polling is used to receive data.
(1) Regular Interrupt Reception
Still using the DGUS serial screen as an example, here is a simple and common interrupt reception method:
(2) Add Timeout Detection
Receiving data may result in half-received data, and if the interrupt is interrupted for some reason, timeout detection is also very necessary.
For example: Use an extra MCU timer to handle a timeout count. When receiving data, start timing; if no next data is received within 1ms, discard this packet (the previously received).
Similar to sending, there are many ways to implement receiving, such as using structures. However, all methods need to be coded according to your actual needs.
All the contents of the custom protocol are for reference only, and the actual number of bytes used depends on your actual needs.
Custom communication protocols based on serial ports vary greatly, depending on factors such as MCU processing capability, number of devices, communication content, etc.
Some may only require a very simple communication protocol to meet the requirements, while others may need a more complex protocol to satisfy.
Finally, two points to emphasize:
First, the examples above are not complete codes (some details are not described), mainly to provide everyone with learning about this programming idea or implementation method.
Second, a good communication protocol code must have certain fault tolerance handling, such as: send completion detection, receive timeout detection, data error detection, etc. Therefore, the above code is not complete.
Copyright belongs to the original author. If there is any infringement, please contact for deletion.
Japan’s Operating System Almost Dominated the World…
Understanding the Difference Between hex, bin, and axf Files in One Article
No Foreign Authorization Required! Fully Autonomous Design of Domestic CPU Milestone is Here~
→Follow to Avoid Getting Lost←