本次使用的外设是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)
不然会一直重启。