nucleo-f411re学习记录-12,Wifi模块ESP8684

代码仓库

本次使用的外设是WiFi模块ESP8484,该模块搭载AT固件,可通过AT指令进行配置和操作,其通信方式与蓝牙模块类似。模块通过串口与MCU连接,用MCU的最后一个可用串口UART1来实现通信。

建议在连接WiFi前,先通过USB转TTL连接模块,使用电脑发送AT指令测试模块功能是否正常。

初始化

c 复制代码
void UART_WIFI_Init(uint32_t buad)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    USART_InitTypeDef USART_InitStruct;

    //时钟开启
    RCC_AHB1PeriphClockCmd(UARTx_WIFI_GPIO_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(UARTx_WIFI_RCC_CLK, ENABLE);
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(UARTx_WIFI_TX_GPIO_PORT, UARTx_WIFI_TX_PIN_SOURCE, UARTx_WIFI_TX_AF);
	GPIO_PinAFConfig(UARTx_WIFI_RX_GPIO_PORT, UARTx_WIFI_RX_PIN_SOURCE, UARTx_WIFI_RX_AF);
    /* Reset GPIO init structure parameters values */
    GPIO_InitStruct.GPIO_Pin    = UARTx_WIFI_TX_PIN | UARTx_WIFI_RX_PIN;
    GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_OType  = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd   = GPIO_PuPd_UP;
    GPIO_Init(UARTx_WIFI_TX_GPIO_PORT, &GPIO_InitStruct);
    
    /* USART_InitStruct members default value */
    USART_InitStruct.USART_BaudRate               = buad;
    USART_InitStruct.USART_WordLength             = USART_WordLength_8b;
    USART_InitStruct.USART_StopBits               = USART_StopBits_1;
    USART_InitStruct.USART_Parity                 = USART_Parity_No ;
    USART_InitStruct.USART_Mode                   = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct.USART_HardwareFlowControl    = USART_HardwareFlowControl_None;  
    USART_Init(UARTx_WIFI, &USART_InitStruct);

    // 使能接收中断 (RXNE)
    USART_ITConfig(UARTx_WIFI, USART_IT_RXNE, ENABLE);
    //使能
    USART_Cmd(UARTx_WIFI, ENABLE);
}

也是由中断来接收数据

c 复制代码
void NVIC_WIFI_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
        
    NVIC_InitStructure.NVIC_IRQChannel                      = USART1_IRQn;  // 中断通道为 USART1
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority    = 0;            // 抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority           = 1;            // 响应优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd                   = ENABLE;       // 使能中断
    NVIC_Init(&NVIC_InitStructure);
}
void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(UARTx_WIFI, USART_IT_RXNE) != RESET)
    {
        if (USARTx_WIFI_Rx_Index < 4096)
        {
            USARTx_WIFI_Rx_Data[USARTx_WIFI_Rx_Index++] = (uint8_t)USART_ReceiveData(UARTx_WIFI);
        }
        else
        {
            // 缓冲区满,丢弃数据并重置索引
            (void)USART_ReceiveData(UARTx_WIFI);
            USARTx_WIFI_Rx_Index = 0;  // 重置避免溢出
        }
    }
    // printf("Received: %.*s\r\n", USARTx_WIFI_Rx_Index, USARTx_WIFI_Rx_Data);
}

接收后的数据处理任务

c 复制代码
void Wifi_RxTask(void *pvParameters)
{
    uint16_t len;
    uint16_t last_index = 0;
    uint32_t last_recv_time = 0;
    while (1)
    {
        if (USARTx_WIFI_Rx_Index > 0)
        {
            if (last_index != USARTx_WIFI_Rx_Index) 
            {
                // 有新的数据到达,更新时间戳
                last_index = USARTx_WIFI_Rx_Index;
                last_recv_time = xTaskGetTickCount();
            } 
            // 检查是否超过10ms没有新数据
            else if ((xTaskGetTickCount() - last_recv_time) > pdMS_TO_TICKS(50) && last_index == USARTx_WIFI_Rx_Index) 
            {
                // 超时,认为接收完成
                taskENTER_CRITICAL();
                len = USARTx_WIFI_Rx_Index;
                USARTx_WIFI_Rx_Index = 0;
                taskEXIT_CRITICAL();
                last_index = 0;
                printf("Received: %.*s\r\n", len, USARTx_WIFI_Rx_Data);
            }
        }
        else {
            last_index = 0;  // 重置
        }
        
        vTaskDelay(pdMS_TO_TICKS(1));  // 1ms轮询
    }
}

发送接口

c 复制代码
uint16_t USARTx_Wifi_Send(uint8_t *data, uint16_t length)
{
    USARTx_Wifi_TxPacket_t packet;
        // 检查队列是否已创建
    if (USARTx_Wifi_TxQueue == NULL)
    {
        printf("Queue not initialized!\r\n");
        return USART_WIFI_QUEUE_CREATION_FAILED;
    }
//    printf("Queueing data for transmission: %.*s\r\n", length, data);
    packet.length = length;
    if (packet.length > 1024) 
        return USART_WIFI_SEND_LEN_ERROR;
    memcpy(packet.buffer, data, packet.length);
    BaseType_t ret = xQueueSend(USARTx_Wifi_TxQueue, &packet, pdMS_TO_TICKS(100));
    if (ret != pdTRUE)
    {
        printf("Queue send failed!\r\n");
        return USART_WIFI_QUEUE_SEND_FAILED;
    }
    return 0;
}

发送任务

c 复制代码
void Wifi_TxTask(void *pvParameters)
{
    USARTx_Wifi_TxPacket_t packet;
    USARTx_Wifi_TxQueue = xQueueCreate(10, sizeof(USARTx_Wifi_TxPacket_t));
        // 添加队列创建失败的检查
    if (USARTx_Wifi_TxQueue == NULL)
    {
        printf("USARTx_Wifi_TxQueue creation failed!\r\n");
        while(1);  // 队列创建失败,停机(喂狗任务也无法执行,会复位)
    }
    printf("USARTx_Wifi_TxQueue created successfully.\r\n");
    while(1)
    {
        if (xQueueReceive(USARTx_Wifi_TxQueue, &packet, portMAX_DELAY) == pdTRUE)
        {
            // printf("Sending data: %.*s\r\n", packet.length, packet.buffer);
            for (int i = 0; i < packet.length; i++)
            {
                USART_SendData(UARTx_WIFI, packet.buffer[i]);
                while (USART_GetFlagStatus(UARTx_WIFI, USART_FLAG_TXE) == RESET);
            }
        }
    }
}

先使用几个AT指令测试通讯是否正常

c 复制代码
uint16_t Wifi_Send_AT_Command(char *command)
{
    return USARTx_Wifi_Send((uint8_t *)command, strlen(command));
}
static uint16_t Wifi_command_init(void)
{
    Wifi_Send_AT_Command("AT\r\n");// 测试AT启动
    vTaskDelay(pdMS_TO_TICKS(100));

    Wifi_Send_AT_Command("ATE0\r\n");// 关闭回显
    vTaskDelay(pdMS_TO_TICKS(100));

//    Wifi_Send_AT_Command("AT+GMR\r\n");// 查看版本信息
//    vTaskDelay(pdMS_TO_TICKS(100));
    
    Wifi_Send_AT_Command("AT+CWHOSTNAME?\r\n");// 查询作为Station时的名称
    vTaskDelay(pdMS_TO_TICKS(100));
    return 0;
}

void Wifi_Init_Task(void *pvParameters)
{
    printf("Wifi initialization task started\r\n");
    
    while (xWifiTxTaskHandle == NULL || xWifiRxTaskHandle == NULL)
    {
        vTaskDelay(pdMS_TO_TICKS(50));  // 等待50ms再检查
    }
    
    // 额外延迟一点,确保队列等资源也初始化完成
    vTaskDelay(pdMS_TO_TICKS(100));
    
    // 执行wifi初始化
    printf("Starting Wifi AT commands...\r\n");
    Wifi_command_init();
    
    printf("Wifi initialization completed, deleting this task\r\n");
    vTaskDelete(NULL);
}

测试结果

c 复制代码
Serial communication is normal
Free heap before any task: 0 bytes
After Key_Task: 40592 bytes
After Feeddog_Task: 40360 bytes
After Wifi_TxTask: 36160 bytes
After Wifi_RxTask: 31960 bytes
After Wifi_Init_Task: 29808 bytes
USARTx_Wifi_TxQueue created successfully.
Wifi initialization task started
Starting Wifi AT commands...
Received: 
OK

Received: 
OK

Received: +CWHOSTNAME:espressif

OK

Wifi initialization completed, deleting this task

注意:当之后若是打开多个外设,需要创建多个任务,那么就需要合理分配堆栈空间

c 复制代码
static void All_Task_Create(void)
{
    printf("Free heap before any task: %d bytes\r\n", xPortGetFreeHeapSize());
    
    xTaskCreate(Key_Task, "Key_Task", 64, NULL, 1, NULL);
    printf("After Key_Task: %d bytes\r\n", xPortGetFreeHeapSize());
    
    xTaskCreate(Feeddog_Task, "Feeddog_Task", 32, NULL, 1, NULL);
    printf("After Feeddog_Task: %d bytes\r\n", xPortGetFreeHeapSize());

    if(dht11_init_flag)
    {
        xTaskCreate(DHT11_Read_Task, "DHT11_Task", 512, NULL, 2, NULL);
        printf("After DHT11_Read_Task: %d bytes\r\n", xPortGetFreeHeapSize());
    }

#if USE_PERIPHERALS_ROCKER
    xTaskCreate(Rocker_Read_Task, "Rocker_Task", 1024, NULL, 2, NULL);
    printf("After Rocker_Read_Task: %d bytes\r\n", xPortGetFreeHeapSize());
#endif

#if USE_PERIPHERALS_BT
    xTaskCreate(BT_TxTask, "BT_TxTask", 512, NULL, 2, &xBTTxTaskHandle);
    printf("After BT_TxTask: %d bytes\r\n", xPortGetFreeHeapSize());
    
    xTaskCreate(BT_RxTask, "BT_RxTask", 512, NULL, 2, &xBTRxTaskHandle);
    printf("After BT_RxTask: %d bytes\r\n", xPortGetFreeHeapSize());

    xTaskCreate(Bluetooth_Init_Task, "Bluetooth_Init_Task", 512, NULL, 3, NULL);
    printf("After Bluetooth_Init_Task: %d bytes\r\n", xPortGetFreeHeapSize());
#endif
    
#if USE_PERIPHERALS_WIFI
    xTaskCreate(Wifi_TxTask, "Wifi_TxTask", 1024, NULL, 2, &xWifiTxTaskHandle);
    printf("After Wifi_TxTask: %d bytes\r\n", xPortGetFreeHeapSize());

    xTaskCreate(Wifi_RxTask, "Wifi_RxTask", 1024, NULL, 2, &xWifiRxTaskHandle);
    printf("After Wifi_RxTask: %d bytes\r\n", xPortGetFreeHeapSize());

    xTaskCreate(Wifi_Init_Task, "Wifi_Init_Task", 512, NULL, 2, NULL);
    printf("After Wifi_Init_Task: %d bytes\r\n", xPortGetFreeHeapSize());
#endif
}

或者设置大一些的总堆空间

c 复制代码
#define configTOTAL_HEAP_SIZE                        (40 * 1024)

不然会一直重启。

相关推荐
伶俜6615 小时前
零基础学 ArkUI 传感器(专题二):从加速度计到指南针,玩转硬件能力
学习·华为·harmonyos
进击的小头16 小时前
第8篇:IGBT 从零到精通:核心原理、关键参数、选型指南与工业级应用要点
经验分享·嵌入式硬件·学习
小陈phd16 小时前
Text2SQL智能体学习笔记(一)——NL2SQL及执行流程介绍
笔记·学习
风栖柳白杨16 小时前
【大模型学习】主流大模型统计
学习
lengxuemo16 小时前
ICC2学习之PG
学习
稷下元歌16 小时前
系统学习plc 基础指令上篇,官方资料课程笔记整 理
笔记·学习
我的xiaodoujiao16 小时前
API 接口自动化测试详细图文教程学习系列25--继续处理testCase中的数据
python·学习·测试工具·pytest
你的保护色16 小时前
数据库第一章-基础知识学习
数据库·学习
数智工坊16 小时前
【ROS 2 全栈入门指南一】:从本质认知到环境搭建与核心原理解析
学习·机器人