7. Serial Communication
7.1 Serial Communication Introduction
A serial port is a communication method in which peripherals and processors transmit data bit by bit through data signal lines, ground lines, control lines, and so on. Although the transmission speed is lower than parallel transmission, serial communication can send data on one wire while receiving data on another wire. This communication method uses fewer data lines and can reduce communication costs in long-distance communication. The most important parameters of serial communication are baud rate, data bits, stop bits, and parity bits. These parameters must match between the two communication ports.
7.2 Serial Communication Parameters
Serial communication parameters include baud rate, data bits, parity bits, stop bits, and so on. These parameters describe the basic specifications for data transmission. For example, the baud rate defines the data transmission speed, data bits determine the number of bits contained in each data byte, parity bits are used for error detection, and stop bits indicate the end of data transmission.
- Baud rate: a parameter that measures communication speed. It indicates the number of bits transmitted per second.
- Data bits: a parameter that measures the actual data bits in communication. It indicates the number of data bits contained in one information packet.
- Stop bits: used to indicate the last bit of a single information packet. Typical values are 1, 1.5, and 2 bits. Because data is transmitted on a transmission line and each device has its own clock, synchronization errors may occur during communication. Stop bits not only indicate the end of transmission but also provide an opportunity to correct clock synchronization. More stop bits provide greater tolerance for different clock synchronization, but also reduce data transfer rate.
- Parity bit: a simple error-checking method. For more detailed information, refer to additional serial communication references.
7.3 Serial Port Operating Modes
Serial port operating modes are divided into three types: simplex, full-duplex, and half-duplex.
- Simplex: at any moment in communication, information can only be transmitted from A to B, or from B to A.
- Half-duplex: at any moment in communication, information can be transmitted from A to B or from B to A, but only one direction can transmit at a time.
- Full-duplex: at any moment in communication, signals can be transmitted in both directions, from A to B and from B to A, on the communication line.
7.4 Serial Communication Protocol
A serial communication protocol defines the rules and format for exchanging data through a serial port. Common serial communication protocols include ASCII, Modbus, RS-232, and so on. The protocol specifies the data frame structure, data format, checksum method, and other rules to ensure that the sender and receiver exchange data according to the same rules, enabling correct transmission and parsing. Serial communication transmits data bit by bit. Each character always starts with a start bit and ends with a stop bit. There is no fixed time interval requirement between characters. Each character begins with a start bit, low level, followed by 7 data bits, then one parity bit, and finally the stop bit. After the stop bit, there are idle bits of variable length. Both the stop bit and idle bits are defined as high level.
7.5 Functions and Advantages of Serial Communication
The serial port is one of the most common communication interfaces between computers and external devices. It has important functions and wide applications. In the computer field, the importance of serial ports is reflected in the following aspects:
- Data transmission: the serial port is a commonly used data transmission interface. Through a serial port, a computer can exchange data and communicate with various external devices. Whether the device is a sensor, actuator, display, printer, or another external device, serial communication can transmit and control data.
- Remote control and monitoring: serial communication is widely used in remote control and monitoring. Through a serial port, a computer can remotely control device actions and monitor device status and data in real time. This is important in industrial control, automation systems, remote monitoring, and other scenarios.
- Debugging and troubleshooting: serial communication is an important tool for debugging and troubleshooting. Through a serial port, a computer can communicate with embedded systems, microcontrollers, and so on, monitor and debug programs in real time, output debug information, locate errors, troubleshoot issues, and monitor system status and faults.
- Hardware connection: a serial port can act as a connection bridge between a computer and various external devices. Through a serial port, different external devices such as sensors, actuators, and peripheral devices can be connected and controlled. A serial port can provide stable data transmission and bidirectional communication.
- Communication protocol: a serial communication protocol is the specification and convention for data transmission between a computer and external devices. By defining different protocols, data interaction and communication between different devices can be implemented. Common serial communication protocols include UART, RS-232, and RS-485.
In short, the serial port plays an important role in communication between computers and external devices. It is a key tool for data transmission, remote control and monitoring, debugging and troubleshooting, and it is a bridge for connecting and communicating with external devices.
7.6 Serial Communication Schematic
ESP32S3 has three serial ports: UART0, UART1, and UART2. Serial port 0 on the development board is already used for automatic downloading and debugging, so in practical applications it is not recommended to use serial port 0 to communicate with other devices.
We can use UART1, serial port 1, and UART2, serial port 2, to communicate with external serial devices. Except for serial port 0, serial pins can use any GPIO as communication pins, just like other peripherals.
7.7 Serial Communication Driver Flow
When performing serial communication on ESP32S3, the corresponding serial driver is usually required. ESP32 provides dedicated serial libraries, such as the Serial library in the Arduino environment, to simplify serial communication. The usual serial communication driver flow includes initializing the serial port, setting communication parameters, sending data, and receiving data. The specific flow depends on the serial library used and the specific requirements. Common steps are as follows:
- Initialize the serial port Add a statement similar to the following in the
setup()function to initialize the serial port:
Serial.begin(115200); // Initialize serial port 0 and set the baud rate to 115200Note that in Arduino, ESP32 serial port 0 is Serial, serial port 1 is Serial1, and serial port 2 is Serial2. To modify pins and communication parameters, write:
int RXPIN = 9;
int TXPIN = 10;
// Initialize serial port 1. Baud rate 115200. SERIAL_8N1 = 8 data bits, no parity, 1 stop bit. RX pin is 9, TX pin is 10.
Serial1.begin(115200, SERIAL_8N1, RXPIN, TXPIN);2
3
4
SERIAL_8N1 represents the configuration of data bits, parity bits, and stop bits. Here, 8 means 8 data bits, N means no parity bit, and 1 means 1 stop bit. This parameter specifies the data format for serial communication. Other configurations can also be set, for example:
SERIAL_5N1,SERIAL_6N1,SERIAL_7N1,SERIAL_8N1,SERIAL_5N2,SERIAL_6N2,SERIAL_7N2,SERIAL_8N2, and so on: these parameters configure different combinations of data bits, parity bits, and stop bits.SERIAL_8E1,SERIAL_8E2,SERIAL_8E1,SERIAL_8O2, and so on: these parameters configure 8 data bits, even or odd parity, and 1 or 2 stop bits.SERIAL_8N1,SERIAL_8E1,SERIAL_8O1,SERIAL_8N2,SERIAL_8E2,SERIAL_8O2, and so on: these parameters configure 8 data bits, no parity, even parity, or odd parity, and 1 or 2 stop bits.SERIAL_8N2,SERIAL_8E1_RXINV,SERIAL_8E1_TXINV, and so on: these parameters configure 8 data bits, no or even parity, 2 stop bits, and can also configure receive pin, RXPIN, inversion or transmit pin, TXPIN, inversion.
- Set the serial receive callback function
// Set callback function onReceiveFunction() for serial port 1
Serial1.onReceive(onReceiveFunction);2
Serial1.onReceive() is a callback registration function used to register a callback function for receiving serial data. When data is received through the serial port, the registered callback function is automatically called to process the received data.
📌A callback function is called under specific conditions rather than during the linear loop execution flow of the program. Similar to an interrupt service routine, it can be used to handle asynchronous operations, event triggers, message passing, and other situations.
The following code example shows how to use Serial1.onReceive():
// This function is executed when data is received
void onDataReceived()
{
// Process the received data
while (Serial1.available())
{
char receivedData = Serial1.read(); // Read data from the receive buffer
// Perform data processing operations
}
}
void setup()
{
Serial1.begin(115200); // Initialize serial port 1 with a baud rate of 115200
Serial1.onReceive(onDataReceived); // Register the callback function for receiving data
}
void loop()
{
// Other main loop code
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
In the example above, onDataReceived() is a custom function used to process data received by the serial port. In setup(), calling Serial1.onReceive(onDataReceived) registers onDataReceived() as the callback function for receiving data. When data is received through Serial1, onDataReceived() is automatically called and data processing is performed inside it.
Using Serial1.onReceive() provides an asynchronous way to process serial received data, so you do not need to poll serial availability in the loop() function. This can process serial data more efficiently and make better use of processor resources.
Note that Serial1.onReceive() can only be used for hardware serial ports, such as Serial1, and cannot be used for virtual serial ports, such as SoftwareSerial. In addition, when using Serial1.onReceive(), keep the loop() function executing quickly so it does not block callback execution for serial data reception.
- Send and receive data
Send data:
After initializing the serial port, use Serial1.write() or Serial1.print() to send data to the serial port. Example:
Serial1.write("Hello, world!"); // Serial port 1 sends character data
Serial1.println(123); // Serial port 1 sends numeric data and a newline2
Receive data:
In the program, use Serial1.available() to check whether data is available on the serial port. If data is available, use Serial1.read() to read data from the serial receive buffer. Example:
// If serial port 1 has data
if (Serial1.available())
{
// Read data from the serial port 1 receive buffer
char receivedData = Serial1.read();
// Send data through serial port 0
Serial.print("Received data: ");
// Print the received data through serial port 0
Serial.println(receivedData);
}2
3
4
5
6
7
8
9
10
7.8 Hardware Connection and Preparation
This example uses the common CH340 module to connect the development board to a computer and test serial communication.
CH340 is a USB-to-serial chip commonly used for USB-to-serial functions in microcontrollers, MCU boards, and Arduino, and it can also be used for USB data transmission and reception. When using a CH340 module, the corresponding driver must be installed so the computer can recognize the serial output of the CH340 chip. On Windows, the driver is usually installed automatically. On Mac and Linux, the corresponding driver support must be downloaded and installed before use.
File Download
Download it from the Development Tools section in the Baidu Netdisk link in the Download Center.
CH340 modules usually include CH340G and CH340E models. CH340G operates from 0 C to 70 C, while CH340E operates from -40 C to 85 C. Both models support multiple baud rates and data bit and stop bit options to meet different serial communication requirements.
The CH340 module is convenient to use. After connecting the computer and development board, you only need to send commands through the serial port to communicate with the microcontroller. Its advantages include a simple interface, low price, and easy-to-use driver, so it is widely used in development and in projects that need to communicate with a computer.
The physical connection is shown below:
7.9 Serial Communication Verification
#define RXPIN 9
#define TXPIN 10
uint8_t dataSent[100];
// Receive interrupt callback function
void onReceiveFunction(void)
{
// Length of data received from serial port 1
size_t available = Serial1.available();
// Display the received length
Serial.printf("onReceive Callback:: There are %d bytes available: ", available);
// Keep decrementing while the received length is not 0
while (available --)
{
// Display the data received by serial port 1 through serial port 0
Serial.print((char)Serial1.read());
}
// Display newline
Serial.println();
}
// Serial, Serial1, and Serial2 correspond to UART0, UART1, and UART2 respectively.
void setup()
{
// Initialize serial communication baud rate
// Initialize serial port 0
Serial.begin(115200);
// Initialize serial port 1. Baud rate 115200. SERIAL_8N1 = 8 data bits, no parity, 1 stop bit. RX pin is 9, TX pin is 10.
Serial1.begin(115200, SERIAL_8N1, RXPIN, TXPIN);
// Set callback function for serial port 1
Serial1.onReceive(onReceiveFunction);
// Serial port 1 sends data "hello LCKFB", 12 bytes
Serial1.write("hello LCKFB", 12);
}
void loop()
{
// Read input data from the Serial Monitor
if (Serial.available())
{
char data = Serial.read();
// Send data to UART1
Serial1.write(data);
}
// Read input data from UART1
if (Serial1.available())
{
char data = Serial1.read();
// Send data to UART0
Serial.write(data);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
7.10 Serial Communication Effect
After the development board powers on, serial port 1 outputs "hello LCKFB", and then serial port 0 and serial port 1 can send data to each other.