Detailed explanation of serial communication (more suitable for data string reception above 1K, more stable than timer)

Foreword: The stability of data reception determines the quality of the product

purpose

In order to solve the problem of data error (unstable) caused by frequent use of the timer,
describe
the blog I wrote before (Detailed explanation of serial communication). If you read it, there will be a certain logic. The timer is interrupted to initialize the timer, and once the time for receiving data expires , It will save the data and wait for the judgment and processing of the thread. There is no problem logically. However, in the subsequent data transmission, the editor has a very small amount of data loss. This can be anxious, the editor, hurry up and look at the log. After logging, I finally found the timer problem. Different chips have different configurations and different performances. This point of view is only for Realtek XX chips. If the reader’s chip is powerful enough, this might be another kind of serial port reception. mechanism.

logic

Here we only talk about logic, and the environment will not be mentioned again. If you change the environment, the logic is still the same:
first we still need to call the library function of the (actual) operating system and interrupt the data acquisition (one byte size). There is a principle That is, in the data receiving interrupt, try to do as little work as possible, put the receiving and processing in other threads (such as while()), and each time you enter the serial port to receive the interrupt, directly transfer one byte of data to the data processing function , Save the value in the array, of course, data saving means that the data and the buff are correct, that is, the data format is correct, the buff has not overflowed, and the buff has not overflowed. This condition is good to judge, but the data format has many conditions: the
data format conditions
are still here. Need to use time as a condition, one to read Beijing (current), of course, other times are also possible, this time is directly used as the basis for the interval of data reception, as long as there is data transmission in a certain period of time, it can be based on the characteristics of the received data Or the flag bit ends the reception of this segment of data. After successful reception, it will be copied to the buff we opened immediately. On the contrary, if this period of time is exceeded, the data in this cache report will be cleared!
If the correct data is saved, the data information can be analyzed, and the corresponding reply and operation can be performed on it

Code

Serial port interrupt function:

static void uart_irq(uint32_t id, SerialIrq event)
{
    
    
    serial_t *sobj = (void *)id;
    if (event == RxIrq)
    {
    
    
        volatile uint8_t Data = (uint8_t)serial_getc(sobj);//数据接收函数
        recive_data(Data);
    }
}

**serial_getc() is the time acquisition function, which defines a local variable and transmits it directly to recive_data(Data); **data processing function
data filtering function:
the comments on the code can explain to a certain extent

void recive_data(uint8_t data)
{
    
    
    static uint8_t Index = 0;
    static uint8_t flag = FALSE;
    static uint8_t g_rx_data[DATA_MAX_SIZE] = {
    
    0}; //数据接收缓存
    static uint16_t g_rx_cnt = 0;                  //数据接收个数
    static time_t time_sec = 0; //上一次接收到有效啊数据的时间
    uint8_t busy = 0;//判断数据是否繁忙
    
    if (g_rx_cnt > DATA_MAX_SIZE || rtc_read() - time_sec >= 2) //超过buff大小或者接收数据间时间超时
    {
    
       
        memset(g_rx_data, 0, DATA_MAX_SIZE);//清零buff
        g_rx_cnt = 0;
        flag = FALSE;
    }
    if (flag == TRUE || data == 'A') //满足条件的头指针数据,标志存储开始
    {
    
    
        flag = TRUE;

        g_rx_data[g_rx_cnt++] = data;
        time_sec = rtc_read();
        if (data == '\n')//接收到'\0'单个结束字符
        {
    
    
            while (g_uart[Index].GotDataFlg == TRUE) //看存不存在空buff存到来的数据
            {
    
    
                my_printf("检测到有占用的buff\r\n");
                Index = (Index + 1) % UART_BUF_INDEX;
                busy++;
                if (busy > UART_BUF_INDEX)
                {
    
    
                    return; //无空buff,直接返回
                }
            }
            memset(g_uart[Index].Data, 0, DATA_MAX_SIZE);//开始赋值给全局变量
            g_uart[Index].RecvLen = g_rx_cnt;
            memcpy(g_uart[Index].Data, g_rx_data, strlen(g_rx_data));
            g_uart[Index].GotDataFlg = TRUE;

            memset(g_rx_data, 0, DATA_MAX_SIZE);
            g_rx_cnt = 0;
            flag = FALSE;
        }
    }
}

Of course, the data processing logic according to the specific accord is just an example

Seeing the above logic may be unclear, I will replace the program with a simple text description below:

void 数据接收处理函数(uint8_t data)
{
    
    
    static uint8_t Index = 0;
    static uint8_t flag = FALSE;
    static uint8_t g_rx_data[DATA_MAX_SIZE] = {
    
    0}; //数据接收缓存
    static uint16_t g_rx_cnt = 0;                  //数据接收个数
    static time_t time_sec = 0; //上一次接收到有效啊数据的时间
    uint8_t busy = 0;//判断buff是否繁忙
    if (接收到的数据超过临时开启的buff或者超时) //超过buff大小或者接收数据间时间超时
    {
    
    
        //     my_printf("数据重新开始接收\r\n");
        清除本临时缓存数据;
        统计个数清零;
        标志位置FALSE;
    }
    if (flag == TRUE || 第一次到来的数据正确) //满足条件的数据开始存储,且头数据为字符A我才接收
    {
    
    
		    标志位置TRUE	;
		    数据存储;
		    如果数据未超时;
		    将最新的数据传给中间量;
        if (收到结束字符)
        {
    
    
            while (判断全局缓存是否被占用) //循环看存不存在空buff存到来的数据
            {
    
    
                my_printf("检测到有占用的buff\r\n");
                如果有占用,buff序号++;
                busy++;
                if (一个空的buff都不存在)
                {
    
    
                    无空buff,直接返回
                }
            }
            
            将成功得到的数据赋值给全局buff
            将数据的个数赋值给全局变量
            全局变量标志位置TRUE

            清除临时缓存
            临时数据个数变量置零
        }
    }
}

result

For shorter data, the timer is no problem, but this customized data receiving and processing will be accurate

Guess you like

Origin blog.csdn.net/weixin_42271802/article/details/105633873