How to code the STM32 serial port to receive messages more efficiently

Publisher:huanguuLatest update time:2017-09-18 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Abstract
This article introduces the design of a circular queue data structure to achieve more stable serial port message reception and effectively prevent packet loss. I

have been studying multi-rotor aircraft and other things during this period. I haven't updated my blog. If I don't stick to it, I'm afraid it will be abandoned.

In the previous article, I simply implemented the parsing of the MAVLink protocol, demonstrated the execution of corresponding event processing according to the designed commands, and added CRC verification to achieve more stable communication. However, at the end of the above article, it was mentioned that when a packet is parsed and the corresponding event is processed, new data cannot be received until the event processing is completed and the Msg_Rev.Get state is set to RECEIVING before new data can be received. At this time, when event processing takes a certain amount of time and new data is continuously sent, it is easy to cause data loss.

How to improve the efficiency of serial port communication and avoid packet loss?

In order to improve efficiency, the first thing to think of is to use DMA. However, after consideration, it is found that the received data packets are not fixed; and even if DMA is used, if the MAVLink receive buffer is still designed to receive only one message size, the packet loss problem will still exist.

So I wonder if there is a way to implement it with software. It is like opening a cache space, putting the continuously received data there, and the packet parsing function can take out certain data from it one by one for processing. In this way, as long as the design is reasonable, the packet loss caused by software blocking can be easily solved. So what kind of cache should be designed? In fact, it is easy to think of a queue (first-in-first-out feature), and in order to use space more effectively and reasonably, the data structure of a circular queue will come to mind.

First of all, let's talk about the data structure design and the insertion and deletion operations. I won't say much. The code is as follows:

#define MAX_QUEUE_LEN (4096) // 4K
#define RW_OK 0
#define FULL_ERROR 1
#define EMPTY_ERROR 2

typedef uint8_t boolean;

typedef struct
{
    u16 MemFrontSendIndex ;
    u16 MemRearRecvIndex ;
    u16 MemLength ;
    u8 MemDataBuf[MAX_QUEUE_LEN];
} Queue_Mem_Struct , * Queue_Mem_Struct_p ;

Queue_Mem_Struct Queue_Recv ;

boolean QueueMemDataInsert(u8 data)
{
    if (MAX_QUEUE_LEN == Queue_Recv.MemLength)
    {
        return FULL_ERROR;
    }
    else
    {
        Queue_Recv.MemDataBuf[Queue_Recv.MemRearRecvIndex] = data;
        // if(++Queue_Recv.MemRearRecvIndex >= MAX_QUEUE_LEN){Queue_Recv.MemRearRecvIndex = 0;}
        Queue_Recv.MemRearRecvIndex = (Queue_Recv.MemRearRecv Index + 1) % MAX_QUEUE_LEN;
        Queue_Recv.MemLength ++ ;
        return RW_OK;
    }
}

boolean QueueMemDataDel(u8 *data)
{
    if (0 == Queue_Recv.MemLength)
    {
        return EMPTY_ERROR;
    }
    else
    {
        *data = Queue_Recv.MemDataBuf[Queue_Recv.MemFrontSendIndex] ;
        Queue_Recv.MemFrontSendIndex = (Queue_Recv.MemFrontSendIndex + 1) % MAX_QUEUE_LEN;
        Queue_Recv.MemLength -- ;
        return RW_OK;
    }
}

In this way, the data received by the serial port can be filled into the buffer Queue_Recv.MemDataBuf in sequence through the QueueMemDataInsert function. When processing, the QueueMemDataDel function is called to extract the corresponding number of data for processing. This avoids the problem of packet loss caused by the inability to receive data at the same time during the entire processing process. Of course, at this time, it is necessary to ensure that the data in the buffer is processed in time, otherwise, especially when the amount of data is large, after the queue is filled, it will cause the data to be unable to be filled in.

In addition, it will be found that the above design can be combined with the DMA method. If the design is good, the STM32 utilization and system operation efficiency can be further greatly improved!

Keywords:STM32 Reference address:How to code the STM32 serial port to receive messages more efficiently

Previous article:Summary of stm32 serial communication debugging
Next article:STM32 network communication DM9000A circuit design

Recommended ReadingLatest update time:2024-11-16 15:36

STM32 code debugging on RAM in Keil MDK environment
I haven't touched Keil since 51. I started using Keil MDK again yesterday afternoon, but this time it's for ARM. The STM32W108 debugging in the past few days was all done on IAR. I just debugged a routine on STM32F103ZE-EK, and found that there is a way to configure code debugging in RAM. I knew there was an iar-cfg.i
[Microcontroller]
An easy-to-understand entry-level example of I2C for stm32
I bought a core board, which means I have my own STM32 board, so I also learned about I2C (because it is 24C02, hehe, it is more familiar). At the beginning, I wrote a read and write program according to the routine in the reference book, but there was no data output from the serial port when I downloaded the program
[Microcontroller]
An easy-to-understand entry-level example of I2C for stm32
STM32 timer TIM2 PWM output PB3
After a long time of searching and reading many articles, I finally solved it by using PB3.  Pin Configuration void GPIO_TimPWM(void) {  GPIO_InitTypeDef GPIO_InitStructure;        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);      GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);    
[Microcontroller]
STM32 Learning: Internal Flash
When we develop applications, we often need to save some program running parameters, such as some correction coefficients. The characteristics of these data are: small in number and do not need to be modified frequently, but they cannot be defined as constants, because each device may be different and may be modified
[Microcontroller]
STM32 Learning: Internal Flash
Based on STM32 serial port ring buffer queue processing mechanism - entry level (single byte)
1.1 Experimental Introduction   The simplest serial port data processing mechanism is to receive data and send it back as is: successfully receive a number, trigger an interrupt, read the data in the interrupt function, and then immediately. This data processing mechanism is a "non-buffered interrupt mode". Althou
[Microcontroller]
Based on STM32 serial port ring buffer queue processing mechanism - entry level (single byte)
STM32 AD uses external voltage reference IC to improve accuracy and stability
The STM32F103 series MCUs with 64 pins and below have VDDA and VREF connected together internally, without separate pins. However, 100 pins and above have separate pins. Generally, if we do not require high acquisition accuracy, VDDA and VREF are directly connected to the 3.3V power supply VDD, and a stable and high
[Microcontroller]
STM32 AD uses external voltage reference IC to improve accuracy and stability
STM32-PWM wave-control servo
Register configuration stm32 device 1. Enable the clock of the peripheral: APB1ENR, APB2ENR 2. Configuration register or control register. When configuring stm32 peripherals, you must enable the clock of the peripheral at any time! And each control register is likely to include 1 mode register, 2 enable register, and
[Microcontroller]
Notes on stm32 free control of io ports
I just got stm32 and wanted to start with the simplest control of io port. I followed the process and wrote a program to control PA15 port to continuously output low level. However, no matter what I did, I couldn't pull the IO port down and always output 3.3V. I was so confused! Later, I asked my classmates carefully a
[Microcontroller]
Notes on stm32 free control of io ports
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号