Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the Ring buffer of Serial Port in STM32

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail how to implement the serial port ring buffer in STM32. The content of the article is of high quality, so the editor shares it for you as a reference. I hope you will have some understanding of the relevant knowledge after reading this article.

The concept of queues

Before that, let's review the basic concepts of queues:

Queue (Queue): a first-in, first-out (FIFO) linear table that is only allowed to be inserted (queued) on one end and deleted (dequeued) on the other.

Characteristics of the queue

Similar to the ticket queue window, people who arrive first can buy tickets first, then go first, and later people can only buy tickets later.

Two common forms of queues

Ordinary queue

In a computer, each information is stored in a storage unit. Metaphorically, some of the small square squares in the picture above are storage units, which you can understand as common arrays that store our information one by one.

When there is a large amount of data, we cannot store all the data, so when the computer processes the data, it can only deal with the first come first. After processing, it will release the data and then deal with the next one. Then the memory of the data that has been processed will be wasted. Because the later data can only be queued back, if you want to move the rest of the data forward once, then the efficiency will be inefficient, which is certainly not realistic, so the circular queue appears.

Ring queue

Its queue is a ring, it avoids the shortcomings of ordinary queues, it is a bit difficult to understand, in fact, it is a queue, the same queue head, queue tail, the same is a first-in, first-out (FIFO). We sort the queues clockwise.

Queue header (Head): the end that allows deletion is called the queue header.

End of queue (Tail): the end of the queue that allows insertion is called the end of the queue.

The implementation of the ring queue: in the computer, there is no ring memory, but we have processed the sequential memory so that a certain section of memory forms a ring and connects them end to end. To put it simply, this is actually an array, but there are only two pointers, one pointing to the head of the queue and the other to the end of the queue. The pointer to the head of the queue (Head) is the readable data of the buffer, and the pointer to the end of the queue (Tail) is the writable data of the buffer. By moving these two pointers (Head) & (Tail), you can read and write the data of the buffer until the buffer is full (end to end). When the data is processed, the data can be released and new data can be stored.

The principle of implementation: during initialization, both the head of the queue and the end of the queue point to 0. When there is data storage, the data is stored in the address space of'0', and the end of the queue points to the next place where data can be stored. When data comes, the data is stored to the address'1', and then the end of the queue points to the next address'2'. When the data is to be processed, the data in the'0' space, that is, the data in the queue head, must be processed first. after the data is processed, the data in the'0' address space is released, and the queue head points to the next address that can process the data,'1'. So as to realize the data reading and writing of the whole ring buffer.

Look at the figure, the queue header points to the data that has been stored, and this data is waiting to be processed. The data processed by the next CPU is 1; the end of the queue points to the address where the data can be written. When 1 is dealt with, it will be released. And point the head of the queue to 2. When a data 6 is written, the pointer at the end of the queue points to the next address that can be written.

Implementation of buffer from queue to Serial Port

Serial ring buffer transceiver: in many entry-level tutorials, we know that serial transceiver is to receive a data, trigger an interrupt, and then send the data back. There is no buffer in this way, when the quantity is too large, or when the data is received too fast, we do not have time to process the received data, then, when the data is received again, the previously unprocessed data will be overwritten. Then there will be the phenomenon of packet loss, which is a fatal trauma to our program.

So how to prevent this from happening? obviously, some of the queue features mentioned above can easily help us achieve the situation we need. Cache the accepted data so that the processing speed can be buffered a little, so that the processing speed can catch up with the receiving speed. The above has analyzed the advantages and disadvantages of ordinary queues and ring queues, so we must use ring queues to implement. Here is the implementation of the code:

Define a structure: typedef struct {u16 Head; U16 Tail; U16 Lenght; U8 Ring_ buffer [RINGBUFF _ LEN];} RingBuff_t;RingBuff_t ringBuff;// creates a buffer initialization for ringBuff

Initialize structure related information: so that our ring buffer is connected from end to end, and there is no data in it, that is, an empty queue.

/ * @ brief RingBuff_Init * @ param void * @ return void * @ author Jay * @ date 2018 * @ version v1.0 * @ note initialization ring buffer * / void RingBuff_Init (void) {/ / initialization information ringBuff.Head = 0; ringBuff.Tail = 0; ringBuff.Lenght = 0;}

The initialization effect is as follows:

Code implementation for writing the ring buffer: / * * @ brief Write_RingBuff * @ param U8 data * @ return FLASE: the ring buffer is full and the write failed TRUE: write successfully * @ author Jay * @ date 2018 * @ version v1.0 * @ note writes U8 Write_RingBuff (U8 data) {if (ringBuff.Lenght > = RINGBUFF_LEN) / / determine whether the buffer is full {return FLASE;} ringBuff.Ring_ buffer [ringBuff.tail] = data;// ringBuff.Tail++; ringBuff.Tail = (ringBuff.Tail+1)% RINGBUFF_LEN / / Code implementation to prevent illegal access to ringBuff.Lenght++; return TRUE;} read buffer data: / * * @ brief Read_RingBuff * @ param U8 * rData, used to save read data * @ return FLASE: ring buffer has no data, read failed TRUE: read successfully * @ author Jay * @ date 2018 * @ version v1.0 * @ note read a U8 type of data from the ring buffer * / U8 Read_RingBuff (U8 * rData) {if (ringBuff.Lenght = = 0) / determine that it is not empty {return FLASE;} * rData = ringBuff.Ring_Buff [ringBuff.Head]; / / FIFO FIFO, exit / / ringBuff.Head++ from the buffer header RingBuff.Head = (ringBuff.Head+1)% RINGBUFF_LEN;// to prevent illegal access to ringBuff.Lenght--; return TRUE; across boundaries}

There are two things to pay attention to for read and write operations:

To determine whether the queue is empty or full, if it is empty, it is not allowed to read data, and return FLASE. If it is full, it is not allowed to write data to avoid overwriting the existing data. Then if the processing speed can not catch up with the receiving speed, you can appropriately increase the size of the buffer and trade space for time.

To prevent illegal access to the pointer across the boundary, the program has instructions, which requires the user to grasp the size of the entire buffer.

Then in the serial port receiver function:

Void USART1_IRQHandler (void) {if (USART_GetITStatus (USART1,USART_IT_RXNE)! = RESET) / / receive interrupt {USART_ClearITPendingBit (USART1,USART_IT_RXNE); / / clear flag bit Write_RingBuff (USART_ReceiveData (USART1)); / / read received data}} test effect

There is no packet loss in the test data.

Supplement

At this stage, Jay, I am slowly learning to standardize when I write the code. All the code snippets are highly readable and portable. I use the macro definition to decide whether to open the ring buffer to send and receive data. Porting to your code will not have any other side effects, just open the macro definition and use it.

# define USER_RINGBUFF 1 / / use ring buffer to receive data # if USER_RINGBUFF / * * if you use ring buffer to receive serial data * * / # define RINGBUFF_LEN 200 / / define the maximum number of bytes to be received: 200 # define FLASE 1 # define TRUE 0 void RingBuff_Init (void); U8 Write_RingBuff (U8 data); U8 Read_RingBuff (U8 * rData) # endif on how to implement the serial port ring buffer in STM32 is shared here. I hope the above content can be of some help and learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report