WIFI 4-addr frame

部署运行你感兴趣的模型镜像

下面是普通WIFI management packet的格式,我们看到它有3个地址,但是Data frame有可能有4个地址。

 

下面是普通WIFI data packet的格式,我们看到它有4个地址,其中前3个是必须的,第4个地址是可选的。

第4个地址只有WDS模式时用道。

 

WIFI data frame中4个地址的用法如下表。

 

下图是WDS结构,其中SA(Source Address), DA(Destination Address); TA(Target Address), RA(Receiver Address)。

 

您可能感兴趣的与本文相关的镜像

Anything-LLM

Anything-LLM

AI应用

AnythingLLM是一个全栈应用程序,可以使用商用或开源的LLM/嵌入器/语义向量数据库模型,帮助用户在本地或云端搭建个性化的聊天机器人系统,且无需复杂设置

main.c /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2025 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "spi.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "rs485.h" #include "wifi.h" #include "mqtt.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_SPI2_Init(); MX_USART1_UART_Init(); MX_USART3_UART_Init(); MX_UART5_Init(); /* USER CODE BEGIN 2 */ USART1_Init(); UART5_Init(); printf("串口初始化完成\n"); USART3_Init(); WIFI_STAConnectAP();//连接热点 WIFI_Huawei_ConnectService(); uint8_t res=0; res=MQTT_Connect(MQTT_CLIENT_ID,MQTT_USERNAME,MQTT_PASSWD,6000); printf("res = %d\n",res); res=MQTT_SubscribeOneTopic(MQTT_Subscribe_Topic2,6000); printf("res = %d\n",res); uint32_t modbus_req_timer = 0; // 请求定时器 /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { // 1. LED闪烁 HAL_GPIO_TogglePin(LED5_GPIO_Port,LED4_Pin); HAL_GPIO_TogglePin(LED5_GPIO_Port,LED5_Pin); HAL_GPIO_TogglePin(LED5_GPIO_Port,LED6_Pin); HAL_Delay(1000); // 2. 每1秒发送一次Modbus请求 if (HAL_GetTick() - modbus_req_timer >= 1000) { modbus_req_timer = HAL_GetTick(); // 构建请求帧(从站0x01,读取寄存器0x0000开始的4个寄存器) Modbus_Master_BuildReq(SLAVE_ADDR, REG_START_ADDR, REG_NUM); // 通过RS485发送请求帧 RS485_SendBuff(modbus_req_frame, sizeof(modbus_req_frame)); // printf("已发送Modbus请求帧\r\n"); } // 3. 处理USART3接收(解析响应) USART3_RevDeal(); // 4. 保留原USART1处理 USART1_RevDeal(); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 25; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ usart.c /** ****************************************************************************** * @file usart.c * @brief This file provides code for the configuration * of the USART instances. ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2025 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usart.h" /* USER CODE BEGIN 0 */ #include "rs485.h" #include "modbus_common.h" #include "wifi.h" #include "stm32f4xx_hal_uart.h" //extern struct USART_DATA wifi_data; struct USART_DATA usart1_data = {.rx_count=0,.rx_over_flag=0}; /* USER CODE END 0 */ UART_HandleTypeDef huart5; UART_HandleTypeDef huart1; UART_HandleTypeDef huart3; /* UART5 init function */ void MX_UART5_Init(void) { /* USER CODE BEGIN UART5_Init 0 */ /* USER CODE END UART5_Init 0 */ /* USER CODE BEGIN UART5_Init 1 */ /* USER CODE END UART5_Init 1 */ huart5.Instance = UART5; huart5.Init.BaudRate = 9600; huart5.Init.WordLength = UART_WORDLENGTH_8B; huart5.Init.StopBits = UART_STOPBITS_1; huart5.Init.Parity = UART_PARITY_NONE; huart5.Init.Mode = UART_MODE_TX_RX; huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart5.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart5) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN UART5_Init 2 */ HAL_UARTEx_ReceiveToIdle_IT(&huart5, usart1_data.rx_buff, USART_RX_LEN); // HAL_UARTEx_ReceiveToIdle_IT(&huart5, wifi_data.rx_buff, USART_RX_LEN); /* USER CODE END UART5_Init 2 */ } /* USART1 init function */ void MX_USART1_UART_Init(void) { /* USER CODE BEGIN USART1_Init 0 */ /* USER CODE END USART1_Init 0 */ /* USER CODE BEGIN USART1_Init 1 */ /* USER CODE END USART1_Init 1 */ huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART1_Init 2 */ HAL_UARTEx_ReceiveToIdle_IT(&huart1, wifi_data.rx_buff, USART_RX_LEN); // HAL_UARTEx_ReceiveToIdle_IT(&huart1, usart1_data.rx_buff, USART_RX_LEN); /* USER CODE END USART1_Init 2 */ } /* USART3 init function */ void MX_USART3_UART_Init(void) { /* USER CODE BEGIN USART3_Init 0 */ /* USER CODE END USART3_Init 0 */ /* USER CODE BEGIN USART3_Init 1 */ /* USER CODE END USART3_Init 1 */ huart3.Instance = USART3; huart3.Init.BaudRate = 9600; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART3_Init 2 */ /* USER CODE END USART3_Init 2 */ } void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==UART5) { /* USER CODE BEGIN UART5_MspInit 0 */ /* USER CODE END UART5_MspInit 0 */ /* UART5 clock enable */ __HAL_RCC_UART5_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /**UART5 GPIO Configuration PC12 ------> UART5_TX PD2 ------> UART5_RX */ GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_UART5; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF8_UART5; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /* UART5 interrupt Init */ HAL_NVIC_SetPriority(UART5_IRQn, 1, 0); HAL_NVIC_EnableIRQ(UART5_IRQn); /* USER CODE BEGIN UART5_MspInit 1 */ /* USER CODE END UART5_MspInit 1 */ } else if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 2, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ } else if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART3_MspInit 0 */ /* USER CODE END USART3_MspInit 0 */ /* USART3 clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USART3 interrupt Init */ HAL_NVIC_SetPriority(USART3_IRQn, 3, 0); HAL_NVIC_EnableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspInit 1 */ /* USER CODE END USART3_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==UART5) { /* USER CODE BEGIN UART5_MspDeInit 0 */ /* USER CODE END UART5_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_UART5_CLK_DISABLE(); /**UART5 GPIO Configuration PC12 ------> UART5_TX PD2 ------> UART5_RX */ HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12); HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); /* UART5 interrupt Deinit */ HAL_NVIC_DisableIRQ(UART5_IRQn); /* USER CODE BEGIN UART5_MspDeInit 1 */ /* USER CODE END UART5_MspDeInit 1 */ } else if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); /* USART1 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ } else if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART3_MspDeInit 0 */ /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); /* USART3 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspDeInit 1 */ /* USER CODE END USART3_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ /*fputc函数,确定输出流*/ struct USART_DATA wifi_data={.rx_count=0,.rx_over_flag=0}; int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,100); return ch; } /******************************************************************************* 函数名称:USART1_Init 函数作用:串口1初始化:启动接收中断 *********************************************************************************/ uint8_t USART1Rev=0; uint8_t usart5_rx_data; void USART1_Init(void) { // HAL_UART_Receive_IT(&huart1,&USART1Rev,1); __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE); } void UART5_Init(void) { // HAL_UART_Receive_IT(&huart5,&usart5_rx_data,1); __HAL_UART_ENABLE_IT(&huart5, UART_IT_RXNE); __HAL_UART_ENABLE_IT(&huart5,UART_IT_IDLE); } /*串口回调函数处理任务*/ uint8_t revBuff[1024]={0}; uint32_t revCount=0; /******************************************************************************* 函数名称:HAL_UART_RxCpltCallback 函数作用:接收处理回调函数 函数入口:*huart:执行回调函数的串口 *********************************************************************************/ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // if(huart->Instance == USART1) // { // revBuff[revCount++] = USART1Rev; // if(revCount >= sizeof(revBuff)) revCount = 0; // HAL_UART_Receive_IT(&huart1,&USART1Rev,1); // } if(huart->Instance == USART3) { rev3Buff[rev3Count++] = USART3Rev; if(rev3Count >= sizeof(rev3Buff)-1) rev3Count = 0; HAL_UART_Receive_IT(&huart3,&USART3Rev,1); } } void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if(huart->Instance == USART1) { usart1_data.rx_count = Size; usart1_data.rx_buff[Size] = '\0'; usart1_data.rx_over_flag = 1; HAL_UARTEx_ReceiveToIdle_IT(&huart1, usart1_data.rx_buff, USART_RX_LEN); } if(huart->Instance == UART5) { wifi_data.rx_count = Size; wifi_data.rx_buff[Size] = '\0'; wifi_data.rx_over_flag = 1; HAL_UARTEx_ReceiveToIdle_IT(&huart5, wifi_data.rx_buff, USART_RX_LEN); } } /******************************************************************************* 函数名称:USART1_RevDeal 函数作用:串口1接收处理 *********************************************************************************/ void USART1_RevDeal(void) { if(revCount>=4) { RS485_SendString(revBuff); memset(revBuff,0,revCount); revCount=0; } } /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ usart.h /** ****************************************************************************** * @file usart.h * @brief This file contains all the function prototypes for * the usart.c file ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2025 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __USART_H__ #define __USART_H__ #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ #include "main.h" /* USER CODE BEGIN Includes */ #include "stdio.h" #include "string.h" /* USER CODE END Includes */ extern UART_HandleTypeDef huart5; extern UART_HandleTypeDef huart1; extern UART_HandleTypeDef huart3; /* USER CODE BEGIN Private defines */ /* USER CODE END Private defines */ void MX_UART5_Init(void); void MX_USART1_UART_Init(void); void MX_USART3_UART_Init(void); /* USER CODE BEGIN Prototypes */ void USART1_Init(void); void USART1_RevDeal(void); void UART5_Init(void); #define USART_RX_LEN 1024 struct USART_DATA { uint8_t rx_buff[USART_RX_LEN];//保存接收到的数据 uint32_t rx_count; //保存接收到数据的个数 uint8_t rx_over_flag; //接收完成标志0 -- 没有接收完成 // 1 -- 接收完成 }; extern struct USART_DATA wifi_data; extern struct USART_DATA usart1_data; /* USER CODE END Prototypes */ #ifdef __cplusplus } #endif #endif /* __USART_H__ */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ wifi.c #include "wifi.h" #include "usart.h" #include <string.h> #include <stdio.h> void wifi_Sendbuff(uint8_t *pdata,uint32_t len) { if (pdata == NULL || len == 0) // 增加空指针和长度检查,更健壮 return; HAL_UART_Transmit(&huart5, pdata, len, 100); } char *WIFI_FindStr(char *buff,char *ack,uint32_t timeout) { while((timeout--) && (strstr(buff,ack) == NULL))//解决busy的bug { HAL_Delay(1); } return strstr(buff,ack); } uint8_t wifi_sendcmd_revack(char *cmd,char *ack,uint32_t timeout,uint8_t cnt) { uint32_t len=strlen(cmd);//求出cmd字符串的长度 if(cmd==NULL) return 1; do { //1.发送指令 memset(&wifi_data,0,sizeof(wifi_data));//清除接收缓冲区 wifi_Sendbuff((uint8_t *)cmd,len); wifi_Sendbuff((uint8_t *)"\r\n",2);//命令以回车+换行结尾 printf("发送指令:%s\n", cmd); // 打印发送的AT指令 //2.等待和判断 if(ack != NULL){ if(WIFI_FindStr((char *)wifi_data.rx_buff,ack,timeout) != NULL) { return 0; } } }while(cnt--); return 2; } uint8_t WIFI_STAConnectAP(void) { uint8_t res = 0; char buff[128]="\0"; //1.测试AT res = wifi_sendcmd_revack("AT","OK",1000,1); if(res != 0){ printf("AT测试失败\r\n"); return 1; } printf("AT测试成功\r\n"); //2.设置Station模式 res = wifi_sendcmd_revack("AT+CWMODE=1","OK",1000,2); if(res != 0){ printf("AT+CWMODE,设置station模式失败\r\n"); return 2; } printf("AT+CWMODE,设置station模式成功\r\n"); //3.连接热点 //sprintf(buff,"AT+CWJAP=\"%s\",\"%s\"",SSID,PASSSWD); sprintf(buff,"AT+CWJAP=\"%s\",\"%s\"",SSID,PASSSWD); res = wifi_sendcmd_revack(buff,"GOT IP",3000,10); if(res != 0){ printf("AT+CWJAP,连接热点失败\r\n"); return 3; } printf("AT+CWJAP,连接热点成功\r\n"); return 0; } uint8_t WIFI_Huawei_ConnectService(void) { uint8_t res = 0; char buff[128]="\0"; //1.连接服务器 sprintf(buff,"AT+CIPSTART=\"TCP\",\"%s\",%s",IP,PORT); res = wifi_sendcmd_revack(buff,"CONNECT",3000,5); if(res != 0){ printf("AT+CIPSTART,连接服务器失败\r\n"); return 1; } printf("AT+CIPSTART,连接服务器成功\r\n"); //2.设置为透传模式 res = wifi_sendcmd_revack("AT+CIPMODE=1","OK",3000,5); if(res != 0){ printf("AT+CIPMODE,设置透传模式失败\r\n"); return 2; } printf("AT+CIPMODE,设置透传模式成功\r\n"); //3.发送AT+CIPSEND指令 res = wifi_sendcmd_revack("AT+CIPSEND",">",3000,5); if(res != 0){ printf("AT+CIPSEND,发送指令失败\r\n"); return 3; } printf("AT+CIPSEND,发送指令成功\r\n"); return 0; } wifi.h #ifndef _WIFI_H_ #define _WIFI_H_ #include "stm32f4xx.h" #include "usart.h" #include "string.h" //#include "stm32_eval_spi_flash.h" #define SSID "abcde"//要连接热点的名字 #define PASSSWD "12345678"//要连接热点的密码 //安信可的透传云 //#define IP "36.137.226.30" //#define PORT "42504" #define IP "04ebd3a6bb.st1.iotda-device.cn-east-3.myhuaweicloud.com" #define PORT "1883" void wifi_Sendbuff(uint8_t *pdata,uint32_t len); char *WIFI_FindStr(char *buff,char *ack,uint32_t timeout); uint8_t wifi_sendcmd_revack(char *cmd,char *ack,uint32_t timeout,uint8_t cnt); uint8_t WIFI_STAConnectAP(void); uint8_t WIFI_Huawei_ConnectService(void); #endif mqtt.c #include "mqtt.h" #define WIFI_TX_MAX_LEN 1024 uint8_t wifi_tx_buff[WIFI_TX_MAX_LEN]="\0";//存放报文的缓冲区 uint32_t wifi_tx_len = 0;//wifi发送数据的个数 uint8_t MQTT_Connect(char *client_id,char *username,char *passwd,uint32_t timeout) { uint8_t res = 0;//保存返回值 //1.构成Connect报文(N个二进制数据) MQTTPacket_connectData options = MQTTPacket_connectData_initializer;//结构体初始化 // options.cleansession = 1;//开启清除会话 options.clientID.cstring = client_id;//保存设备ID号 options.keepAliveInterval = 120; // options.MQTTVersion = 4;//MQTT版本号:3.1.1 options.password.cstring = passwd;//保存用户密码 options.username.cstring = username;//保存用户名 // options.willFlag = 0;//不使用遗嘱功能 wifi_tx_len = MQTTSerialize_connect(wifi_tx_buff,WIFI_TX_MAX_LEN,&options); //2.通过WIFI发送给华为云服务器 //2.1 清除WIFI接收缓冲区,方便后续接收服务器应答 memset(&wifi_data,0,sizeof(wifi_data)); //2.2 发送Connect报文 wifi_Sendbuff(wifi_tx_buff,wifi_tx_len); // 固定报头 可变报头(会话标志+连接返回码) //3.等待CONNACK报文(云服务器给设备端) 0x20 0x02 0x00/0x01 0x00(成功) ~ 0x05 while(timeout && wifi_data.rx_over_flag == 0) { timeout--; HAL_Delay(1); } if(timeout == 0){//超时 res = 1; goto over; } if(wifi_data.rx_count < 4){//数据不完整 res = 2; goto over; } switch(wifi_data.rx_buff[3])//解析数据 -- 可变报头中的连接返回码 { case 0:res = 0;break; default:res = wifi_data.rx_buff[3]+2;break; } over: wifi_data.rx_count = 0; wifi_data.rx_over_flag = 0; return res; } uint8_t MQTT_Publish(char *topic,char *pdata) { //MQTTString topicName = {NULL,{0,NULL}}; //MQTTString topicName = MQTTString_initializer; MQTTString topicName = {0}; int len = strlen(pdata); //1.生成Publish报文 topicName.cstring = topic; wifi_tx_len = MQTTSerialize_publish(wifi_tx_buff,WIFI_TX_MAX_LEN,0,0,0,0,topicName,(uint8_t *)pdata,len); //2.通过WIFI发送给华为云服务器 //2.1 清除WIFI接收缓冲区,方便后续接收服务器应答 memset(&wifi_data,0,sizeof(wifi_data)); //2.2 发送Connect报文 wifi_Sendbuff(wifi_tx_buff,wifi_tx_len); return 0; } uint8_t dht11_t; uint8_t dht11_h; uint16_t temp_mq2,temp_mq135; uint16_t light_val; // 光照值 uint16_t people_state; // 人体检测状态(0=无人,1=有人) #define PUBLISH_DATA_MAX_LEN 512 char publish_data_buff[PUBLISH_DATA_MAX_LEN]="\0"; char *GetPublish_Topic1Data(void) { //1.缓冲区清零 memset(publish_data_buff,0,PUBLISH_DATA_MAX_LEN); //2.赋值 sprintf(publish_data_buff,"{\ \"services\": [{\ \"service_id\": \"value_sensor\",\ \"properties\": {\ \"temp\":%.1f,\ \"hum\":%.1f,\ \"light\":%d,\ \"MQ2\":%d,\ \"MQ135\":%d\ \"people\":%d\ }\ }]\ }",dht11_t,dht11_h,light_val,temp_mq2, temp_mq135 ,people_state); return publish_data_buff; } uint8_t MQTT_SubscribeOneTopic(char *topic,uint32_t timeout) { uint8_t res = 0;//保存返回值 MQTTString topicFilters[1];//保存topic列表 -- 只保存1个 int requestedQoSs[1];//每个主题列表的QoS topicFilters[0].cstring = topic; //1.构成Subscribe报文(N个二进制数据) wifi_tx_len = MQTTSerialize_subscribe(wifi_tx_buff,WIFI_TX_MAX_LEN,0,10,1,topicFilters,requestedQoSs); //2.通过WIFI发送给华为云服务器 //2.1 清除WIFI接收缓冲区,方便后续接收服务器应答 memset(&wifi_data,0,sizeof(wifi_data)); //2.2 发送Connect报文 wifi_Sendbuff(wifi_tx_buff,wifi_tx_len); // 固定报头 可变报头(报文标识符) 有效载荷 //3.等待SUBACK报文(云服务器给设备端) 0x90 0x03 0x00 0x0A 0x80失败 其他成功 while(timeout && wifi_data.rx_over_flag == 0) { timeout--; HAL_Delay(1); } if(timeout == 0){//超时 res = 1; goto over; } if(wifi_data.rx_count < 4){//数据不完整 res = 2; goto over; } switch(wifi_data.rx_buff[4])//解析数据 -- 可变报头中的连接返回码 { case 0x80:res = 3;break; default:res = 0;break; } over: wifi_data.rx_count = 0; wifi_data.rx_over_flag = 0; return res; } char *GetPublish_Topic2Data(void) { //1.缓冲区清零 memset(publish_data_buff,0,PUBLISH_DATA_MAX_LEN); //2.赋值 sprintf(publish_data_buff,"{ \ \"object_device_id\": \"{object_device_id}\", \ \"services\": [{ \ \"service_id\": \"$time_sync\", \ \"event_type\": \"time_sync_request\", \ \"event_time\": \"20151212T121212Z\",\ \"paras\": { \ \"device_send_time\": 1582685678789\ } \ }] \ }"); return publish_data_buff; } mqtt.h #ifndef _MQTT_H_ #define _MQTT_H_ #include "stm32f4xx.h" #include "MQTTPacket.h" #include "usart.h" #include "wifi.h" #include "stdio.h" #include "string.h" #include "stdlib.h" #define MQTT_CLIENT_ID "68e775f754ed1814a9b1d74d_znly_0_0_2025100911" #define MQTT_USERNAME "68e775f754ed1814a9b1d74d_znly" #define MQTT_PASSWD "dbf32623f0a67d2c1ea4734ca1a939ceea83d66a3ce9ee320f4c1ba8a8b71032" #define MQTT_Publish_Topic1 "$oc/devices/68e775f754ed1814a9b1d74d_znly/sys/properties/report" #define MQTT_Publish_Topic2 "$oc/devices/68e775f754ed1814a9b1d74d_znly/sys/events/up" #define MQTT_Subscribe_Topic1 "$oc/devices/68e775f754ed1814a9b1d74d_znly/user/beep" #define MQTT_Subscribe_Topic2 "$oc/devices/68e775f754ed1814a9b1d74d_znly/sys/events/down" uint8_t MQTT_Connect(char *client_id,char *username,char *passwd,uint32_t timeout); uint8_t MQTT_Publish(char *topic,char *pdata); char *GetPublish_Topic1Data(void); uint8_t MQTT_SubscribeOneTopic(char *topic,uint32_t timeout); char *GetPublish_Topic2Data(void); //uint8_t MQTT_RTC_Sync(void); #endif 结合上述所有代码,仔细分析为什么AT指令发送不出去,为什么AT测试失败,是不是串口的问题
最新发布
10-11
<think>我们注意到在usart.c文件中,串口初始化的回调函数中,UART5(用于WiFi模块)和USART1(用于调试串口)的接收缓冲区配置出现了交叉错误: - 在UART5的初始化中,使用了`usart1_data.rx_buff`作为接收缓冲区 - 在USART1的初始化中,使用了`wifi_data.rx_buff`作为接收缓冲区 这个错误会导致: 1. 发送给WiFi模块的AT指令,其响应本该被接收到`wifi_data`缓冲区,但实际上被写入了`usart1_data`缓冲区。 2. 而调试串口USART1接收的数据被写入了`wifi_data`缓冲区。 因此,在`wifi_sendcmd_revack`函数中,我们检查`wifi_data.rx_buff`是否有预期的响应(如"OK")时,实际上`wifi_data.rx_buff`中并没有WiFi模块的响应数据,因为响应数据在`usart1_data.rx_buff`中。这样就导致AT指令发送后检测不到响应,从而认为失败。 此外,在`wifi_sendcmd_revack`函数中,每次发送命令前都会用`memset(&wifi_data,0,sizeof(wifi_data))`清除`wifi_data`结构体。由于实际数据不在`wifi_data`中,所以这个清除操作也没有意义。 解决方案: 1. 交换两个串口的接收缓冲区分配,使其正确对应。 2. 确保在WiFi相关函数中,使用的是正确的缓冲区(即UART5对应的缓冲区应该是`wifi_data`)。 具体修改如下: 在`usart.c`文件中,修改两个串口的接收缓冲区配置: ```c // 在MX_UART5_Init函数中,将接收缓冲区改为wifi_data /* USER CODE BEGIN UART5_Init 2 */ // 修改前:HAL_UARTEx_ReceiveToIdle_IT(&huart5, usart1_data.rx_buff, USART_RX_LEN); // 修改后: HAL_UARTEx_ReceiveToIdle_IT(&huart5, wifi_data.rx_buff, USART_RX_LEN); /* USER CODE END UART5_Init 2 */ // 在MX_USART1_UART_Init函数中,将接收缓冲区改为usart1_data /* USER CODE BEGIN USART1_Init 2 */ // 修改前:HAL_UARTEx_ReceiveToIdle_IT(&huart1, wifi_data.rx_buff, USART_RX_LEN); // 修改后: HAL_UARTEx_ReceiveToIdle_IT(&huart1, usart1_data.rx_buff, USART_RX_LEN); /* USER CODE END USART1_Init 2 */ ``` 这样,WiFi模块(UART5)的数据就会接收到`wifi_data`结构体的缓冲区中,而调试串口(USART1)的数据会接收到`usart1_data`结构体的缓冲区中。 另外,在`wifi_sendcmd_revack`函数中,我们清除和检查的缓冲区是`wifi_data`,现在这个缓冲区就是UART5接收的数据,所以逻辑就正确了。 但是,我们还需要注意:在`HAL_UARTEx_RxEventCallback`回调函数中,我们也需要修改对应的重新启动接收的函数调用,确保使用正确的缓冲区。在该回调函数中,已经根据串口实例区分了缓冲区,所以目前来看是区分处理的,不需要修改。但是为了清晰,我们可以再次确认: 在`HAL_UARTEx_RxEventCallback`中: ```c if(huart->Instance == USART1) { // 这里使用的是usart1_data,正确 ... HAL_UARTEx_ReceiveToIdle_IT(&huart1, usart1_data.rx_buff, USART_RX_LEN); } if(huart->Instance == UART5) { // 这里使用的是wifi_data,正确 ... HAL_UARTEx_ReceiveToIdle_IT(&huart5, wifi_data.rx_buff, USART_RX_LEN); } ``` 因此,只需要修改初始化部分即可。 此外,还需要检查中断优先级设置。在`HAL_UART_MspInit`中,UART5的中断优先级是1,USART1的中断优先级是2,USART3的中断优先级是3。由于WiFi通信需要及时响应,建议将UART5的中断优先级设置为最高(数值最小): ```c // 修改UART5的中断优先级为0,高于其他串口 HAL_NVIC_SetPriority(UART5_IRQn, 0, 0); // 修改前是1,0 ``` 修改后,重新编译并测试。 如果问题仍未解决,可以尝试以下调试措施: 1. 使用示波器或逻辑分析仪检查UART5的TX引脚(PC12)是否有AT指令发出,以及格式是否正确(包括回车换行)。 2. 在`wifi_sendcmd_revack`函数中,加入打印接收到的数据的内容,以确认是否接收到任何数据以及数据内容。 例如,在`wifi_sendcmd_revack`函数中,发送命令后,可以在超时循环中加入打印: ```c printf("等待响应,当前接收: %s\n", wifi_data.rx_buff); ``` 这样可以通过调试串口观察WiFi模块的响应。 注意:由于WiFi模块的响应可能包含不可打印字符,建议以十六进制形式打印。 综上所述,串口缓冲区配置错误是导致AT指令测试失败的主要原因。通过交换缓冲区配置,应该可以解决此问题。 最后,如果问题仍然存在,请检查硬件连接(WiFi模块的RX、TX是否与MCU的UART5的TX、RX交叉连接,注意是交叉连接)以及WiFi模块的供电是否稳定。 §§相关问题§§: 1. 在STM32中如何使用多个串口进行通信? 2. 如何调试STM32的串口通信问题? 3. AT指令通信的基本流程和常见问题有哪些? 4. 在STM32中如何配置串口的中断优先级? </think>### 问题分析:AT指令发送失败的原因 根据您的代码分析,AT指令发送失败的主要原因是**串口缓冲区配置错误**和**中断处理逻辑问题**。以下是详细分析: #### 1. 串口缓冲区交叉配置(关键问题) 在`usart.c`中,UART5和USART1的接收缓冲区被错误地交叉配置: ```c // MX_UART5_Init() 中: HAL_UARTEx_ReceiveToIdle_IT(&huart5, usart1_data.rx_buff, USART_RX_LEN); // ❌ 错误 // MX_USART1_UART_Init() 中: HAL_UARTEx_ReceiveToIdle_IT(&huart1, wifi_data.rx_buff, USART_RX_LEN); // ❌ 错误 ``` 这导致: - WiFi模块(UART5)的数据被写入`usart1_data`缓冲区 - 调试串口(USART1)的数据被写入`wifi_data`缓冲区 - AT指令响应无法被正确识别 #### 2. 中断回调函数逻辑问题 在`HAL_UARTEx_RxEventCallback`中: ```c void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if(huart->Instance == USART1) { // 处理USART1(实际应是调试串口) } if(huart->Instance == UART5) { // 处理UART5(实际应是WiFi模块) wifi_data.rx_count = Size; // ❌ 使用了错误的缓冲区 } } ``` #### 3. 缓冲区清除逻辑错误 在`wifi_sendcmd_revack`函数中: ```c uint8_t wifi_sendcmd_revack(...) { memset(&wifi_data, 0, sizeof(wifi_data)); // ❌ 清除的是错误的缓冲区 // ... } ``` #### 4. 中断优先级冲突 ```c HAL_NVIC_SetPriority(UART5_IRQn, 1, 0); // WiFi串口优先级 HAL_NVIC_SetPriority(USART1_IRQn, 2, 0); // 调试串口优先级 ``` 可能导致WiFi数据接收被高优先级任务打断。 --- ### 解决方案 #### 1. 修复串口缓冲区配置(关键修复) 修改`usart.c`中的缓冲区分配: ```c /* USER CODE BEGIN UART5_Init 2 */ // 修复:UART5使用wifi_data缓冲区 HAL_UARTEx_ReceiveToIdle_IT(&huart5, wifi_data.rx_buff, USART_RX_LEN); /* USER CODE END UART5_Init 2 */ /* USER CODE BEGIN USART1_Init 2 */ // 修复:USART1使用usart1_data缓冲区 HAL_UARTEx_ReceiveToIdle_IT(&huart1, usart1_data.rx_buff, USART_RX_LEN); /* USER CODE END USART1_Init 2 */ ``` #### 2. 修正中断回调函数 确保使用正确的缓冲区: ```c void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if(huart->Instance == USART1) { // 调试串口处理 usart1_data.rx_count = Size; usart1_data.rx_buff[Size] = '\0'; usart1_data.rx_over_flag = 1; HAL_UARTEx_ReceiveToIdle_IT(&huart1, usart1_data.rx_buff, USART_RX_LEN); } if(huart->Instance == UART5) { // WiFi串口处理 wifi_data.rx_count = Size; wifi_data.rx_buff[Size] = '\0'; wifi_data.rx_over_flag = 1; HAL_UARTEx_ReceiveToIdle_IT(&huart5, wifi_data.rx_buff, USART_RX_LEN); } } ``` #### 3. 修正WiFi响应检查逻辑 修改`wifi.c`中的函数: ```c uint8_t wifi_sendcmd_revack(char *cmd, char *ack, uint32_t timeout, uint8_t cnt) { uint32_t len = strlen(cmd); if(cmd == NULL) return 1; do { // 清除正确的缓冲区 memset(wifi_data.rx_buff, 0, USART_RX_LEN); wifi_data.rx_count = 0; wifi_data.rx_over_flag = 0; // 发送指令 wifi_Sendbuff((uint8_t *)cmd, len); wifi_Sendbuff((uint8_t *)"\r\n", 2); printf("发送指令:%s\n", cmd); // 等待响应(带超时) uint32_t start = HAL_GetTick(); while((HAL_GetTick() - start) < timeout) { if(wifi_data.rx_over_flag && wifi_data.rx_count > 0) { if(strstr((char *)wifi_data.rx_buff, ack) != NULL) { return 0; // 成功找到响应 } } HAL_Delay(10); } } while(cnt--); return 2; // 失败 } ``` #### 4. 优化中断优先级 ```c // 提高WiFi串口中断优先级 HAL_NVIC_SetPriority(UART5_IRQn, 0, 0); // 最高优先级 HAL_NVIC_SetPriority(USART1_IRQn, 1, 0); // 中优先级 HAL_NVIC_SetPriority(USART3_IRQn, 2, 0); // 最低优先级 ``` #### 5. 添加调试输出 在`main.c`中添加调试信息: ```c int main(void) { // ...初始化代码... printf("WiFi缓冲区地址: %p\n", wifi_data.rx_buff); printf("UART5实际缓冲区: %p\n", huart5.pRxBuffPtr); // 测试AT指令发送 wifi_Sendbuff((uint8_t *)"AT\r\n", 4); HAL_Delay(100); printf("收到的响应: %s\n", wifi_data.rx_buff); // ...后续代码... } ``` --- ### 根本原因总结 | 问题 | 原因 | 解决方案 | |------|------|----------| | AT指令无响应 | 串口缓冲区配置错误 | 修正UART5使用wifi_data缓冲区 | | 响应识别失败 | 缓冲区清除逻辑错误 | 显式重置wifi_data结构体 | | 数据丢失 | 中断优先级过低 | 提高UART5中断优先级 | | 超时处理不当 | 被动等待机制 | 使用主动轮询+超时检测 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值