编程模型 ------ 如何合理接收WIFI模块、4G模块等AT指令形式的数据

通信模块配置(比如设置连接服务器的IP和port)完之后分为透传接收和命令接收,先讨论透传接收:

前提:服务器发给通信模块的数据是一包一包的,每一包数据包含包头、包长和数据,比如一包数据位:AA AA 00 08 01 02 45 FA,其中AA AA表示包头,00 08是包长,01 02 45 FA表示数据(其中01 02是命令,45 FA是命令内容)。

方式一:

每接收到一个字节数据,进入接收中断,并在中断程序中判断是否接收到包头,如果不是包头,index清零;根据接收到的包长判断是否接收完一包数据,接收完进行相应记录,之后接收到的数据继续检测是否是包头。

优点:节省RAM资源,需要一个大数组按顺序接收每个包,一个二维数组记录每个包的起始结束位置。

缺点:中断程序稍微长点,要进行的判断比较多。

 

......

 

方法二:

需要用到接收中断、空闲中断。首先需要一个数组A循环接收收到的数据,接收中断程序只要把每字节数据放入数组A即可;空闲中断产生后发布一个信号读取数组A的数据,在读取数据函数中根据包头和包长把一个个数据包取出放入大数组中,并通过二维数组记录每个包的位置信息。

优点:中断函数程序较短。

缺点:多用些RAM资源,包括一个数组A、需要一个大数组按顺序接收每个包,一个二维数组记录每个包的起始结束位置。

 

接收中断程序:

复制代码
    if(huart == &_2_4G_UART)
    {
        __HAL_UNLOCK(&_2_4G_UART);
        

        g_from4G[g_from4G_index] = g_recv_4G_value;
        g_from4G_index++;
        g_from4G_cnt++;
        if(g_from4G_index >= FROM4G_SIZE)
        {
            g_from4G_index = 0;
        }

        
        HAL_UART_Receive_IT(&_2_4G_UART,(uint8_t *)&g_recv_4G_value,1);
    }
复制代码

 

空闲中断函数

  if(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE) == 1)
  {
      __HAL_UART_CLEAR_IDLEFLAG(&huart3);
      g_from4G_index_tmp = g_from4G_cnt;//这两个变量只在命令模式有用到
      xTaskNotifyFromISR( xTaskhandle_uartInt, 0x01, eSetBits, &xHigherPriorityTaskWoken );
  }

 

空闲中断发出信号执行如下程序:

复制代码
        if(g_flag_4G_cmd_or_data == 1)/*现在是命令接收*/
        {
            //            g_from4G[g_from4G_index_tmp] = '\0';
            
            //命令反馈
            if(my_strstr((u8 *)g_from4G, g_from4G_index_tmp, "OK") != NULL)
            {
                xSemaphoreGive( xSemaphoreBinary_4G_cmd );
            }else if(my_strstr((u8 *)g_from4G, g_from4G_index_tmp, "ERROR") != NULL)
            {
                xSemaphoreGive( xSemaphoreBinary_4G_cmd );
            }//URC
            if(my_strstr((u8 *)g_from4G, g_from4G_index_tmp, "Unknown error") != NULL)
            {
                xTaskNotify( xTaskhandle_URC, g_URC_event[URC_UNKNOWN_ERROR], eSetBits );
            }
            if(my_strstr((u8 *)g_from4G, g_from4G_index_tmp, "RDY") != NULL)
            {
                xSemaphoreGive( xSemaphoreBinary_4G_cmd );
            }
        }else
        {
            u16 index = g_from4G_index;
            u16 data_length;
            if(g_from4G_index_after <= index)
            {
                data_length = index - g_from4G_index_after;
            }else
            {
                data_length = FROM4G_SIZE - g_from4G_index_after;
                data_length += index;
            }

            u16 tmp_index;
            static u16 packet_length = 0;
            static u16 tmp_offset = 0;
            for(i=0; i<data_length; i++)
            {
                if(g_from4G_index_after <= index)
                {
                    g_serverPackageBuf[g_serverPackageBuf_index] = g_from4G[g_from4G_index_after+i];
                }else
                {
                    if(i < FROM4G_SIZE - g_from4G_index_after)
                    {
                        g_serverPackageBuf[g_serverPackageBuf_index] = g_from4G[g_from4G_index_after+i];
                    }else
                    {
                        g_serverPackageBuf[g_serverPackageBuf_index] = g_from4G[i-(FROM4G_SIZE - g_from4G_index_after)];
                    }
                }
                
                
                
                
                tmp_index = g_serverPackageBuf_index;
                g_serverPackageBuf_index++;
                if(g_serverPackageBuf_index >= SERVERBUF_SIZE)
                {
                    g_serverPackageBuf_index = 0;
                }
                
                if(tmp_index == judge_server_index(4 + g_serverPackageBuf_packet_start_index))//长度字段
                {
                    if(g_serverPackageBuf[judge_server_index(g_serverPackageBuf_packet_start_index+4)] == 0x00)
                    {//说明长度字段是4字节
                        tmp_offset = 8;
                    }else
                    {
                        packet_length = g_serverPackageBuf[judge_server_index(g_serverPackageBuf_packet_start_index+4)];
                        tmp_offset = 5;
                    }
                }
                if(tmp_offset == 8)
                {
                    if(tmp_index == judge_server_index(7 + g_serverPackageBuf_packet_start_index))
                    {
                        packet_length = (g_serverPackageBuf[judge_server_index(g_serverPackageBuf_packet_start_index+6)]<<8) | 
                            g_serverPackageBuf[judge_server_index(g_serverPackageBuf_packet_start_index+7)];
                    }
                }
                
                
                
                
                if(tmp_index == judge_server_index(0 + g_serverPackageBuf_packet_start_index))//包头第一字节
                {
                    if(g_serverPackageBuf[tmp_index] != 0xAA)
                    {
                        g_serverPackageBuf_index = g_serverPackageBuf_packet_start_index;
                    }
                }else if(tmp_index == judge_server_index(1 + g_serverPackageBuf_packet_start_index))//包头第二字节
                {
                    if(g_serverPackageBuf[tmp_index] != 0xAA)
                    {
                        g_serverPackageBuf_index = g_serverPackageBuf_packet_start_index;
                    }
                }else if(tmp_index == judge_server_index(2 + g_serverPackageBuf_packet_start_index))//包头第三字节
                {
                    if(g_serverPackageBuf[tmp_index] != 0xAA)
                    {
                        g_serverPackageBuf_index = g_serverPackageBuf_packet_start_index;
                    }
                }else if(tmp_index == judge_server_index(3 + g_serverPackageBuf_packet_start_index))//包头第四字节
                {
                    if(g_serverPackageBuf[tmp_index] != 0xAA)
                    {
                        g_serverPackageBuf_index = g_serverPackageBuf_packet_start_index;
                    }
                }else if(tmp_index == judge_server_index(packet_length + tmp_offset + g_serverPackageBuf_packet_start_index))//包尾第一字节
                {
                    if(g_serverPackageBuf[tmp_index] != 0xAB)
                    {
                        g_serverPackageBuf_index = g_serverPackageBuf_packet_start_index;
                    }
                }else if(tmp_index == judge_server_index(packet_length + tmp_offset + 1 + g_serverPackageBuf_packet_start_index))//包尾第二字节
                {
                    if(g_serverPackageBuf[tmp_index] != 0xAB)
                    {
                        g_serverPackageBuf_index = g_serverPackageBuf_packet_start_index;
                    }
                }else if(tmp_index == judge_server_index(packet_length + tmp_offset + 2 + g_serverPackageBuf_packet_start_index))//包尾第三字节
                {
                    if(g_serverPackageBuf[tmp_index] != 0xAB)
                    {
                        g_serverPackageBuf_index = g_serverPackageBuf_packet_start_index;
                    }
                }else if(tmp_index == judge_server_index(packet_length + tmp_offset + 3 + g_serverPackageBuf_packet_start_index))//包尾第四字节
                {
                    
                    if(g_serverPackageBuf[tmp_index] != 0xAB)
                    {
                        g_serverPackageBuf_index = g_serverPackageBuf_packet_start_index;
                    }else //一个包接收完成
                    {
                        g_serverPackageBuf_property[g_serverPackageBuf_packet_record][0] = g_serverPackageBuf_packet_start_index;
                        g_serverPackageBuf_property[g_serverPackageBuf_packet_record][1] = judge_server_index(packet_length + tmp_offset + 3 + g_serverPackageBuf_packet_start_index);
                        g_serverPackageBuf_packet_start_index = g_serverPackageBuf_index;
                        
                        g_serverPackageBuf_packet_record++;
                        if(g_serverPackageBuf_packet_record >= SERVERBUF_PACKET_CAPACITY)
                        {
                            g_serverPackageBuf_packet_record = 0;
                        }
                        xTaskNotifyGive(xTaskhandle_server_communication);
                        tmp_offset = 0;
                    }
                }
            }
            g_from4G_index_after = index;
            
        }
复制代码

 

 

 

 

现在讨论命令模式接收数据:

需要用到接收中断,空闲中断;处理接收到的数据时要考虑多个数据包一起发给单片机,但只产生一次空闲中断

 

接收中断程序:

复制代码
    if(huart == &_1_4G_UART)
    {
        __HAL_UNLOCK(&_1_4G_UART);
        

        g_from4G1[g_from4G1_index] = g_recv_4G1_value;
        g_from4G1_index_previous = g_from4G1_index;
        g_from4G1_index++;
        if(g_from4G1_index >= FROM4G1_SIZE)
        {
            g_from4G1_index = 0;
        }

        
        HAL_UART_Receive_IT(&_1_4G_UART,(uint8_t *)&g_recv_4G1_value,1);
    }
复制代码

 

空闲中断程序:

  if(__HAL_UART_GET_FLAG(&huart6, UART_FLAG_IDLE) == 1)
  {
      __HAL_UART_CLEAR_IDLEFLAG(&huart6);
      g_from4G1_index_tmp = g_from4G1_index;
      xTaskNotifyFromISR( xTaskhandle_UART_4G1, 0x01, eSetBits, &xHigherPriorityTaskWoken );
  }

 

空闲中断发出信号执行如下程序:

复制代码
        if(g_flag_clear_semaphore == 1)//发送数据到4G模块,有回显,需要忽略掉回显的数据
        {
            if(g_from4G1_index_tmp > g_cnt_send_to_gddServer_data_len)
            {
                remainning_len = g_from4G1_index_tmp - g_cnt_send_to_gddServer_data_len;
                new_buffer = (u8 *)(g_from4G1 + g_cnt_send_to_gddServer_data_len);
            }else
            {
                remainning_len = 0;
                new_buffer = (u8 *)g_from4G1;
            }
        }else
        {
            remainning_len = g_from4G1_index_tmp;
            new_buffer = (u8 *)g_from4G1;
        }
        
    again:;
    //URC
    u8 *p;
    p = my_strstr((u8 *)new_buffer, remainning_len, "+QIURC: \"recv\",0,");
    if(p != NULL)
    {
        g_from4G1_index = 0;
        u8 index=0;
        u16 tmp;
        u16 len;
        tmp = remainning_len - (p - new_buffer);//表示从“+QIURC..."到结束的长度
        for(i=18; i<tmp; i++)
        {
            if(p[i] == '\n')
            {
                index = i+1;
                break;
            }
        }
        u8 num_byte;
        num_byte = index-19;
        len = 0;
        for(i=0; i<num_byte; i++)
        {
            len = len*10 + (p[17+i]-'0');
        }
        remainning_len = tmp - index - 2 - len;
        new_buffer = p + index + 2 + len;
        //            len = tmp-index-2;
        p = p + index;
        printf("\r\n\r\n\r\n");
        debug("recv gdd server data: <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
        debug_array((u8 *)p, len);
        
        u16 tmp_index;
        u16 data_length;
        for(i=0; i<len; i++)
        {
            g_gdd_serverPackageBuf[g_gdd_serverPackageBuf_index] = p[i];
            tmp_index = g_gdd_serverPackageBuf_index;
            g_gdd_serverPackageBuf_index++;
            if(g_gdd_serverPackageBuf_index >= GDD_SERVERBUF_SIZE)
            {
                g_gdd_serverPackageBuf_index = 0;
            }
            
            data_length = (g_gdd_serverPackageBuf[judge_gdd_server_index(g_gdd_serverPackageBuf_packet_start_index+2)]<<8) | 
                g_gdd_serverPackageBuf[judge_gdd_server_index(g_gdd_serverPackageBuf_packet_start_index+3)];
            
            
            if(tmp_index == judge_gdd_server_index(0 + g_gdd_serverPackageBuf_packet_start_index))
            {
                if(g_gdd_serverPackageBuf[tmp_index] != 0x01)
                {
                    g_gdd_serverPackageBuf_index = g_gdd_serverPackageBuf_packet_start_index;
                }
            }else if(tmp_index == judge_gdd_server_index(1 + g_gdd_serverPackageBuf_packet_start_index))
            {
            }else if(tmp_index == judge_gdd_server_index(2 + g_gdd_serverPackageBuf_packet_start_index))
            {
            }else if(tmp_index == judge_gdd_server_index(data_length - 1 + g_gdd_serverPackageBuf_packet_start_index))
            {
                g_gdd_serverPackageBuf_property[g_gdd_serverPackageBuf_packet_record][0] = g_gdd_serverPackageBuf_packet_start_index;
                g_gdd_serverPackageBuf_property[g_gdd_serverPackageBuf_packet_record][1] = judge_gdd_server_index(data_length - 1 + g_gdd_serverPackageBuf_packet_start_index);
                g_gdd_serverPackageBuf_packet_start_index = g_gdd_serverPackageBuf_index;
                
                g_gdd_serverPackageBuf_packet_record++;
                if(g_gdd_serverPackageBuf_packet_record >= GDD_SERVERBUF_PACKET_CAPACITY)
                {
                    g_gdd_serverPackageBuf_packet_record = 0;
                }
                xTaskNotifyGive(xTaskhandle_gdd_server_communication);
            }
        }
        if(remainning_len > 0)
        {
            goto again;
        }
    }else
    {
        //命令反馈
        if(my_strstr((u8 *)new_buffer, remainning_len, "SEND OK") != NULL)
        {
            debug("----------------------------------------------------------------------%d %s", remainning_len, "SEND OK");
            xSemaphoreGive( xSemaphoreBinary_4G1_cmd );
        }else if(my_strstr((u8 *)new_buffer, remainning_len, "ERROR") != NULL)
        {
            debug("----------------------------------------------------------------------%d %s", remainning_len, "ERROR");
            xSemaphoreGive( xSemaphoreBinary_4G1_cmd );
        }if(my_strstr((u8 *)new_buffer, remainning_len, "RDY") != NULL)
        {
            debug("----------------------------------------------------------------------%d %s", remainning_len, "RDY");
            xSemaphoreGive( xSemaphoreBinary_4G1_cmd );
        }
        p = my_strstr((u8 *)new_buffer, remainning_len, "+QIURC: \"closed\",0");
        if(p != NULL)
        {
            debug("----------------------------------------------------------------------%d %s", remainning_len, "+QIURC: \"closed\",0");
            g_from4G1_index = 0;
//            error("%s", p);
            error("gdd server close socket");
            notify_URC_ENTER_SLEEP_GDD();
        }
    }
复制代码

 

4G模块发送数据的函数:

复制代码
u8 LTE4G_send_data_cmd_gdd(u8 *buffer, u16 index, u16 length)
{
    u16 i;
    
    if(exec_cmd_gdd_server("AT+QISTATE=1,0\r", 10) != 0)
    {
        error("not connect to server, close and reconnect");
        return 1;
    }
    
    
    char cmd_send[100];
    sprintf(cmd_send, "AT+QISEND=0,%d\r", length);
    
    if(exec_cmd_gdd_server(cmd_send, 10) != 0)
    {
        error("%s, revc > timeout", cmd_send);
        return 2;
    }
    
    g_from4G1_index = 0;
    g_flag_clear_semaphore = 1;
    g_cnt_send_to_gddServer_data_len = length;
    u8 *p = buffer + index;
    for(i=0; i<length; i++)
    {
//        *p = 0x3E;
        HAL_UART_Transmit(&LET4G_uart, p, 1, 1000);
        
        p++;
    }
    
    if(xSemaphoreTake( xSemaphoreBinary_4G1_cmd, pdMS_TO_TICKS( 1000*5 )) == pdPASS)
    {
        g_flag_clear_semaphore = 0;
        if(my_strstr((u8 *)g_from4G1, g_from4G1_index_tmp, "SEND OK") != NULL)
        {
            debug("SEND OK");
            return 0;
        }else if(my_strstr((u8 *)g_from4G1, g_from4G1_index_tmp, "SEND FAIL") != NULL)
        {
            error("SEND FAIL");
            return 4;
        }else if(my_strstr((u8 *)g_from4G1, g_from4G1_index_tmp, "ERROR") != NULL)
        {
            error("ERROR");
            return 4;
        }else
        {
            error("unknow error, recv %.*s", g_from4G1_index_tmp, g_from4G1);
            return 4;
        }
    }else
    {
        g_flag_clear_semaphore = 0;
        error("AT+QISEND=0, recv SEND OK timeout");
        return 3;
    }
}
复制代码

 

posted @   流水灯  阅读(479)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
历史上的今天:
2016-05-19 RCC电路 - 自激式反激转换器
点击右上角即可分享
微信分享提示