This article introduces how to use a serial port with FIFO to reduce the number of receiving interruptions, and provides a frame packaging method through a custom communication protocol format. Then it introduces a special serial port data sending method that can avoid using the serial port to send interrupts. , improve the response speed of the system.
1 Overview
Before that, let’s first list the shortcomings of traditional serial port data transmission and reception:
Each time a byte of data is received, a receive interrupt is generated. The serial port hardware FIFO cannot be effectively used to reduce the number of interrupts.
The response data adopts the method of waiting to be sent. Since the serial data transmission time is far less than the CPU processing time, waiting for the serial port to finish sending the current byte before sending the next byte will cause a waste of CPU resources and is not conducive to the overall system response (at 1200bps, sending one byte It takes about 10ms. If dozens of bytes of data are sent at a time, the CPU will be waiting for a long time).
Response data is sent using interrupts. Adding an interrupt source will increase the number of interrupts in the system, which will affect the overall stability of the system (from a reliability perspective, the fewer interrupt events, the better).
To address the above shortcomings, a complete solution will be provided by combining a commonly used custom communication protocol.
2. Serial FIFO
The serial port FIFO can be understood as a dedicated buffer for the serial port, which adopts a first-in-first-out method. The data receiving FIFO and the data sending FIFO are usually two independent pieces of hardware. The data received by the serial port is first put into the receiving FIFO. When the data in the FIFO reaches the trigger value (usually the trigger value is 1, 2, 4, 8, 14 bytes) or the data in the FIFO does not reach the set value but a period of If no data is received within a certain period of time (usually 3.5 character transmission time), the CPU will be notified to generate a receiving interrupt; the data to be sent must first be written into the sending FIFO. As long as the sending FIFO is not empty, the hardware will automatically send the data in the FIFO. The number of bytes written to the transmit FIFO is affected by the maximum depth of the FIFO. Usually, a maximum of 16 bytes is allowed for one write. The data listed above are related to the specific hardware. Different CPU types have different characteristics. You should refer to the corresponding data manual before use.
3. Data receiving and packaging
FIFO can buffer the data received by the serial port, so we can use FIFO to reduce the number of interrupts. Taking NXP's lpc1778 chip as an example, the trigger level of the receive FIFO can be set to 1, 2, 4, 8, and 14 bytes. It is recommended to use 8 bytes or 14 bytes, which is also the default value of the PC serial port receive FIFO. In this way, when a large amount of data is received, an interrupt will be generated every 8 bytes or 14 bytes (except for the last reception). Compared with receiving one byte and generating an interrupt, this method has a much higher number of serial port reception interrupts. reduce. Setting the receive FIFO to 8 or 14 bytes is also very simple. Taking lpc1778 as an example, you only need to set the UART FIFO control register UnFCR. The received data must comply with the communication protocol, and data and protocol are inseparable. Usually we need to package the received data into a frame according to the protocol, and then hand it over to the upper layer for processing. The following introduces a custom protocol frame format and gives a general method of packaging into frames. The custom protocol format is shown in Figure 3-1.
Frame header: usually 3~5 0xFF or 0xEE
Address number: The address number of the device to be communicated with, 1 byte
Command number: corresponding to different functions, 1 byte
Length: the number of bytes in the data area, 1 byte
Data: related to the specific command number, the length of the data area can be 0, and the length of the entire frame should not exceed 256 bytes
Check: XOR sum check (1 byte) or CRC16 check (2 bytes), this example uses CRC16 check
The following describes how to pack the received data into a frame according to the format shown in Figure 3-1. 3.1 Define data structure typedefstruct
{
uint8_t * dst_buf; //Point to the receive buffer
uint8_t sfd; //Frame first flag, 0xFF or 0xEE
uint8_t sfd_flag; //Find the beginning of the frame, usually 3~5 FF or EE
uint8_t sfd_count; //The number of frame headers, usually 3~5
uint8_t received_len; //Number of bytes received
uint8_t find_frame_flag; //After finding the complete frame, set it to 1
uint8_t frame_len; //Total length of data in this frame, this area is optional
}find_frame_struct;3.2 Initialize data structure, usually placed in serial port initialization/**
* @brief Initialize the data structure of the search frame
* @param p_fine_frame: Points to the packed frame data structure variable
* @param dst_buf: points to the frame buffer
* @param sfd: frame first flag, usually 0xFF or 0xEE
*/
voidinit_find_frame_struct(find_frame_struct * p_find_frame,uint8_t *dst_buf,uint8_t sfd)
{
p_find_frame->dst_buf=dst_buf;
p_find_frame->sfd=sfd;
p_find_frame->find_fram_flag=0;
p_find_frame->frame_len=10;
p_find_frame->received_len=0;
p_find_frame->sfd_count=0;
p_find_frame->sfd_flag=0;
} 3.3 Data Packaging Program/**
* @brief Search for a frame of data and return the number of processed data
* @param p_find_frame: Points to the packed frame data structure variable
* @param src_buf: Points to the original data received by the serial port
* @param data_len: src_buf The number of original data received by the serial port this time
* @param sum_len: the maximum length of the frame buffer
* @return The number of data processed this time
*/
uint32_tfind_one_frame(find_frame_struct * p_find_frame,constuint8_t * src_buf,uint32_t data_len,uint32_t sum_len)
{
uint32_t src_len=0;
while(data_len--)
{
if(p_find_frame ->sfd_flag==0)
{ //Start frame not found
if(src_buf[src_len++]==p_find_frame ->sfd)
{
p_find_frame ->dst_buf[p_find_frame ->received_len++]=p_find_frame ->sfd;
if(++p_find_frame ->sfd_count==5)
{
p_find_frame ->sfd_flag=1;
p_find_frame ->sfd_count=0;
p_find_frame ->frame_len=10;
}
}
else
{
p_find_frame ->sfd_count=0;
p_find_frame ->received_len=0;
}
}
else
{ //Is it the "length" byte? Y->Get the data length of this frame
if(7==p_find_frame ->received_len)
{
p_find_frame->frame_len=src_buf[src_len]+5+1+1+1+2; //Frame header+address number+command number+data length+check
if(p_find_frame->frame_len>=sum_len)
{ //The processing method here may not be the same depending on the specific application.
MY_DEBUGF(SLAVE_DEBUG,("Data length exceeds cache!n"));
p_find_frame->frame_len= sum_len;
}
}
p_find_frame ->dst_buf[p_find_frame->received_len++]=src_buf[src_len++];
if(p_find_frame ->received_len==p_find_frame ->frame_len)
{
p_find_frame ->received_len=0; //One frame completed
p_find_frame ->sfd_flag=0;
p_find_frame ->find_fram_flag=1;
return src_len;
}
}
}
p_find_frame ->find_fram_flag=0;
return src_len;
}
Usage example: Define data structure variable: find_frame_struct slave_find_frame_srt; Define receive data buffer: #define SLAVE_REC_DATA_LEN 128
uint8_t slave_rec_buf[SLAVE_REC_DATA_LEN]; Call the structure variable initialization function in the serial port initialization: init_find_frame_struct(&slave_find_frame_srt, slave_rec_buf,0xEE); Call the data packaging function in the serial port reception interrupt: find_one_frame(&slave_find_frame_srt,tmp_rec_buf,data_len,SLAVE_ DATA_LEN);
Among them, rec_buf is the temporary buffer for serial port reception, and data_len is the length of the data received this time.
4. Data sending
As mentioned earlier, the traditional waiting to send method will waste CPU resources, while the interrupt sending method will not cause a waste of CPU resources, but it also adds an interrupt source. In our use, we found that timer interrupts are used by almost every application. We can use timer interrupts and hardware FIFO to send data. After reasonable design, such a sending method will not cause a waste of CPU resources. There will not be more interrupt sources and interrupt events. It should be noted in advance that this method is not suitable for all applications. This method is certainly not supported for applications that do not have timer interrupts enabled. In addition, if the timer interrupt interval is long and the communication baud rate is particularly high, , this method is not suitable either. The communication baud rate currently used by the company is generally relatively small (1200bps, 2400bps). Under these baud rates, the timer interval is 10ms or less (including 10ms). If the timer interval is less than 1ms (including 1ms), 115200bps can be used. The main idea of this method is: after the timer interrupt is triggered, determine whether there is data to be sent. If there is data to be sent and the sending conditions are met, the data is put into the sending FIFO. For lpc1778, up to 16 bytes can be put in at a time. data. The hardware will then automatically start sending without CPU involvement. The following describes how to use a timer to send data. The hardware carrier is RS485. Because sending requires operating the serial port register and the RS485 direction control pin, it needs to be closely related to the hardware. The hardware used in the following code is lpc1778, but the idea is universal. 4.1 Define data structure /*Serial port frame sending structure*/
typedefstruct
{
uint16_t send_sum_len; //The length of the frame data to be sent
uint8_t send_cur_len; //The length of data currently sent
uint8_t send_flag; //Whether to send the flag
uint8_t * send_data; //Point to the data buffer to be sent
}uart_send_struct;
4.2 Timing processing function/**
Previous article:Is the main function of the microcontroller executed in the interrupt function?
Next article:Microcontroller port input and output impedance
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- How to enable UART flow control?
- Looking for experts to develop ALTERA CYCLONE board
- [NXP Rapid IoT Review] + 2. App connects to Rapid IoT
- Small household appliances frequency control through EMC method
- LSM6DSO(X) sensor driver key code analysis: read_data_polling routine related resources
- [Gesture recognition and scene reproduction based on ESP32] Material unboxing—ESP32-S2-KALUGA-1 and k210
- How to design a type-c interface for lithium battery power supply circuit design
- PCB copper plating problem
- [Project source code] Using scripts in Quartus II to convert sof to rbf files
- [Flower carving DIY] Interesting and fun music visualization series of small projects (07) --- large square spectrum light