本框架为了合宙Air780E开发,主要用来连接TCP服务器,通过透明传输进行数据交互。
硬件使用STM32H723ZGT6,通过UART7与4G模块进行交互。串口使用。软件使用Freertos。通过空闲中断+DMA方式进行接收并压入消息队列。

#ifndef BSP_AT_H_
#define BSP_AT_H_

#include "main.h"
#include "string.h"


// AT步骤定义(需与指令表序号对应)
typedef enum {
    STEP_AT,            // 0: 测试模块
    STEP_SIM,           // 1: 测试SIM
    STEP_ECHO_OFF,      // 2: 关闭回显
    STEP_CGATT,         // 3: 注册网络
    STEP_CSTT,          // 4: 配置数据网络
    STEP_CIICR,         // 5: 激活数据网络
    STEP_CIPMUX,                // 6:设置单链接
    STEP_CIPMODE,               // 7:开启透明传输
    STEP_CIPSTART,          // 8:建立TCP连接
    STEP_TRANSMIT,      // 9:透传数据
    STEP_MAX            // a:步骤总数(不可删除)
} AT_STEP_t;

typedef struct{
    const char* desc;       // 步骤描述(用于打印)
    const char* cmd;        // AT指令(NULL表示无指令)
    const char* success_flag; // 成功标志(字符串匹配)
    AT_STEP_t next_step;    // 成功后跳转的步骤
} AT_CMD_TABLE_t;


void at_callback_fun(void);


#endif
#include "bsp_at.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <string.h>
#include <stdio.h>

uint8_t air780_rec_buf[100] = {0};
uint8_t tcp_rec_buf[100] = {0};
QueueHandle_t At_Message_Queue = NULL; /* AT消息队列句柄 */
QueueHandle_t Tcp_Raw_Message_Queue = NULL; /* TCP透传接消息队列句柄 */

void Ykc_Task(void const *argument) 
{
    Tcp_Raw_Message_Queue = xQueueCreate(10, 100);
    for(;;)
    {
        if (xQueueReceive(Tcp_Raw_Message_Queue, &tcp_rec_buf, 10) == pdPASS) 
        {
            printf("data:%s\r\n",tcp_rec_buf);
        }
        vTaskDelay(1);
    }
}

// 任务参数
#define STEP_TIMEOUT_MS  5000
#define SERVER_IP        "112.125.89.8"
#define SERVER_PORT      34673

// AT指令表(核心修改区:增减步骤只需修改此表)

const AT_CMD_TABLE_t at_cmd_table[STEP_MAX] = {
    {"测试模块通信", "AT", "OK", STEP_SIM},
    {"测试SIM模块", "AT+CPIN?", "+CPIN: READY", STEP_ECHO_OFF},
    {"关闭回显", "ATE0", "OK", STEP_CGATT},
    {"注册网络", "AT+CGATT?", "+CGATT: 1", STEP_CIPMUX},
        {"设置单链接模式", "AT+CIPMUX=0", "OK", STEP_CSTT},
    {"配置数据网络", "AT+CSTT", "OK", STEP_CIICR},    
    {"激活数据网络", "AT+CIICR", "OK", STEP_CIPMODE},
    {"开启透明传输模式", "AT+CIPMODE=1", "OK", STEP_CIPSTART},
    {"建立TCP连接", NULL, "CONNECT", STEP_TRANSMIT}, 
    {"透传数据传输", NULL, NULL, STEP_TRANSMIT}
};

// 全局变量
AT_STEP_t current_step = STEP_AT;       // 当前步骤(初始为第一步)
TickType_t step_start_time;             // 步骤开始时间戳

// 串口发送AT命令
void AT_Send(const char* cmd) {
    if (cmd && strlen(cmd) > 0) {
        HAL_UART_Transmit(&huart7, (uint8_t*)cmd, strlen(cmd), 1000);
        HAL_UART_Transmit(&huart7, (uint8_t*)"\r\n", 2, 1000);
    }
}

// 启动指定步骤(含日志打印)
void step_start(AT_STEP_t step) {
    if (step >= STEP_MAX) return;
    
    current_step = step;
    step_start_time = xTaskGetTickCount();
    const AT_CMD_TABLE_t* entry = &at_cmd_table[step];
    printf("[AT] 开始步骤 %d: %s\n", step, entry->desc);
 
    if (entry->cmd) {
        AT_Send(entry->cmd); // 固定指令直接发送
    } else if (step == STEP_CIPSTART) {
        char cmd[64];
        sprintf(cmd, "AT+CIPSTART=\"TCP\",\"%s\",%d", SERVER_IP, SERVER_PORT);
        AT_Send(cmd);
    }
}


// AT Task - 二维数组指令表驱动
void At_Task(void const* argument) {
    uint8_t at_rx_msg[100];
    At_Message_Queue = xQueueCreate(10, 100);
    step_start(STEP_AT); 

    for (;;) {
        // 超时检测(透传模式下关闭)
        if (current_step != STEP_TRANSMIT && 
            (xTaskGetTickCount() - step_start_time) > pdMS_TO_TICKS(STEP_TIMEOUT_MS)) {
            printf("[ERR] 步骤 %d 超时! 重发当前命令\n", current_step);
            step_start(current_step); // 超时重发当前步骤
        }
        // 接收AT回复并处理
        if (xQueueReceive(At_Message_Queue, &at_rx_msg, 10) == pdPASS) {
            const AT_CMD_TABLE_t* entry = &at_cmd_table[current_step];
            if (current_step == STEP_TRANSMIT) {              
              xQueueSend(Tcp_Raw_Message_Queue, at_rx_msg, 0);  
            } else if (entry->success_flag && strstr((char*)at_rx_msg, entry->success_flag)) {
                step_start(entry->next_step);
            }
        }
    }
}

// UART7空闲中断回调(放队列)
void at_callback_fun() {
    uint8_t temp;
    if (__HAL_UART_GET_FLAG(&huart7, UART_FLAG_IDLE) != RESET) {
        HAL_UART_DMAStop(&huart7);
        __HAL_UART_CLEAR_IDLEFLAG(&huart7);
        __HAL_UART_CLEAR_OREFLAG(&huart7);
        temp = __HAL_DMA_GET_COUNTER(&hdma_uart7_rx);
        HAL_UART_Receive_DMA(&huart7, air780_rec_buf, 100);
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        xQueueSendFromISR(At_Message_Queue, air780_rec_buf, &xHigherPriorityTaskWoken);
        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        memset(air780_rec_buf, 0x00, 100);
    }
}
最后修改:2025 年 09 月 23 日 10 : 59 AM
如果觉得我的文章对你有用,请随意赞赏