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)

不然会一直重启。

相关推荐
stm32 菜鸟3 小时前
nucleo-f411re学习记录-9,双轴XY摇杆传感器
学习
南子北游3 小时前
Python学习(基础语法1)
开发语言·python·学习
Atri厨5 小时前
X86存储器的段描述符学习随笔
学习
星幻元宇VR5 小时前
VR航空航天科普设备助力航天知识普及
人工智能·科技·学习·安全·vr·虚拟现实
d111111111d5 小时前
STM32-UART封装问题解析
笔记·stm32·单片机·嵌入式硬件·学习·算法
寒秋花开曾相惜5 小时前
(学习笔记)4.2 逻辑设计和硬件控制语言HCL(4.2.1 逻辑门&4.2.2 组合电路和HCL布尔表达式)
linux·网络·数据结构·笔记·学习·fpga开发
叶子野格6 小时前
《C语言学习:指针》12
c语言·开发语言·c++·学习·visual studio
光影少年6 小时前
前端线上屏幕出现卡顿如何排查?
开发语言·前端·javascript·学习·前端框架·node.js
aacd27198 小时前
C语言之预处理详解ヾ(•ω•`)o
c语言·学习