news 2026/4/23 11:27:10

一、在freertos上使用esp01s模块并配置使用sta模式进行数据通信传输测试。

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一、在freertos上使用esp01s模块并配置使用sta模式进行数据通信传输测试。

一、前期配置情况




二、代码部分展示

1、数据定义:

#defineUSART1_DMA_BUF_SIZE256#defineUART_RX_BUF_SIZE256#defineUSART2_DMA_BUF_SIZE256#defineAT_CMD_TIMEOUT3000typedefstruct{uint8_tdata[UART_RX_BUF_SIZE];uint16_tlen;}ESP01_UART_Data_t;uint8_tESP01_SendATCmd(constchar*cmd,constchar*resp_ok,constchar*resp_err,uint32_ttimeout);#defineTASK_LIST_BUF_SIZE512chartask_list_buf[TASK_LIST_BUF_SIZE];uint8_tFLG_CWLAP=0;typedefstructwifiinfo{charwifi_ssid[160];charwifi_pwd[160];chartcp_server_ip[11];}uwifi_info;uwifi_info use_wifi={0};

二、重要函数编写

uint8_tusart1_dma_buf[USART1_DMA_BUF_SIZE]={0};uint8_tusart2_dma_buf[USART2_DMA_BUF_SIZE]={0};__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);// 启动DMA循环接收(和串口2逻辑一致)HAL_UART_Receive_DMA(&huart1,usart1_dma_buf,USART1_DMA_BUF_SIZE);//串口1和2的中断服务函数类似voidUSART1_IRQHandler(void){ESP01_UART_Data_t rx_data={0};if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET){__HAL_UART_CLEAR_IDLEFLAG(&huart1);HAL_UART_DMAStop(&huart1);// 计算接收长度rx_data.len=USART1_DMA_BUF_SIZE-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);if(rx_data.len>0&&rx_data.len<=USART1_DMA_BUF_SIZE){memcpy(rx_data.data,usart1_dma_buf,rx_data.len);// 中断中发送数据到队列if(osMessageQueuePut(myQueue01Handle,(void*)&rx_data,0,0)==osOK){}osThreadYield();}// 重启DMA接收HAL_UART_Receive_DMA(&huart1,usart1_dma_buf,USART1_DMA_BUF_SIZE);}HAL_UART_IRQHandler(&huart1);}uint8_tESP01_SendATCmd(constchar*cmd,constchar*resp_ok,constchar*resp_err,uint32_ttimeout){uint8_tretry=0;ESP01_UART_Data_t rx_data={0};TickType_t xStartTick=xTaskGetTickCount();chartemp_buf[USART2_DMA_BUF_SIZE*2]={0};uint16_ttemp_len=0;while(retry<3){osMessageQueueReset(myQueue02Handle);memset(temp_buf,0,sizeof(temp_buf));temp_len=0;xStartTick=xTaskGetTickCount();HAL_UART_Transmit(&huart2,(uint8_t*)cmd,strlen(cmd),100);HAL_UART_Transmit(&huart2,(uint8_t*)"\r\n",2,100);// printf("AT指令(配置阶段)%s\r\n", cmd);while((xTaskGetTickCount()-xStartTick)<pdMS_TO_TICKS(timeout)){if(osMessageQueueGet(myQueue02Handle,(void*)&rx_data,NULL,10)==osOK){if(temp_len+rx_data.len<sizeof(temp_buf)){memcpy(temp_buf+temp_len,rx_data.data,rx_data.len);temp_len+=rx_data.len;}//printf("接收数据%s(原始字节:%d)\r\n", temp_buf, temp_len);if(strstr(temp_buf,resp_ok)!=NULL){// printf("匹配到成功响应:%s\r\n", resp_ok);return1;}// 5. 匹配失败响应if(strstr(temp_buf,resp_err)!=NULL){// printf("匹配到失败响应:%s\r\n", resp_err);break;}}}retry++;vTaskDelay(50);}return0;}

任务调用

voidStartTask02(void*argument){ESP01_UART_Data_t rx_data={0};charcmd_buf[UART_RX_BUF_SIZE]={0};charat_cmd[128]={0};printf("串口1调试指令接收任务已启动,支持指令:\r\n");printf("1. LED_ON - 点亮LED\r\n");printf("2. LED_OFF - 关闭LED\r\n");printf("3. ESP_AT+CMD - 配置ESP01命令\r\n");for(;;){if(osMessageQueueGet(myQueue01Handle,(void*)&rx_data,NULL,5000)==osOK){// 清空指令缓冲区,去除换行/空格等无效字�??memset(cmd_buf,0,sizeof(cmd_buf));strncpy(cmd_buf,(char*)rx_data.data,rx_data.len);// 去除字符串末尾的\r\n(串口助手输入的换行�??cmd_buf[strcspn(cmd_buf,"\r\n")]='\0';printf("串口1收到指令:%s\r\n",cmd_buf);// ========== 1. LED控制指令解析 ==========if(strcmp(cmd_buf,"LED_ON")==0){printf("执行指令:点亮LED,当前状态:%s\r\n","ON");HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET);}elseif(strcmp(cmd_buf,"LED_OFF")==0){printf("执行指令:关闭LED,当前状态:%s\r\n","OFF");HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET);}elseif(strncmp(cmd_buf,"WIFI_SSID+",10)==0){strncpy(at_cmd,cmd_buf+10,sizeof(at_cmd)-1);printf("CMD:%s\r\n",at_cmd);strcpy(use_wifi.wifi_ssid,at_cmd);}elseif(strncmp(cmd_buf,"WIFI_PWD+",9)==0){strncpy(at_cmd,cmd_buf+9,sizeof(at_cmd)-1);printf("CMD:%s\r\n",at_cmd);strcpy(use_wifi.wifi_pwd,at_cmd);}elseif(strncmp(cmd_buf,"TCP_SERVER_IP+",14)==0){strncpy(at_cmd,cmd_buf+14,sizeof(at_cmd)-1);printf("CMD:%s\r\n",at_cmd);strcpy(use_wifi.tcp_server_ip,at_cmd);}elseif(strcmp(cmd_buf,"INFOS")==0){printf("use_wifi tcp_server_ip:%s\n",use_wifi.tcp_server_ip);printf("use_wifi wifi_pwd:%s\n",use_wifi.wifi_pwd);printf("use_wifi wifi_ssid:%s\n",use_wifi.wifi_ssid);}elseif(strncmp(cmd_buf,"ESP_AT+",7)==0){// 提取AT指令(去掉前�?ESP_AT+,得到真正的AT指令�?strncpy(at_cmd,cmd_buf+7,sizeof(at_cmd)-1);printf("手动发AT指令给ESP01:%s\r\n",at_cmd);if(strcmp(at_cmd,"STA")==0){HAL_UART_Transmit(&huart2,(uint8_t*)"+++",3,100);osDelay(1000);if(!ESP01_SendATCmd("AT","OK","ERROR",AT_CMD_TIMEOUT)){printf("AT失败\r\n");}if(!ESP01_SendATCmd("AT+CWMODE=1","OK","ERROR",AT_CMD_TIMEOUT)){printf("AT+CWMODE=1失败\r\n");}if(!ESP01_SendATCmd("AT+CWQAP","OK","ERROR",AT_CMD_TIMEOUT)){printf("AT+CWQAP失败\r\n");}osDelay(20);//用之前定义的use_wifi,替换 tcp_server_ip,wifi_pwd,wifi_ssidsnprintf(at_cmd,sizeof(at_cmd),"AT+CWJAP=\"%s\",\"%s\"",WIFI_SSID,WIFI_PWD);if(!ESP01_SendATCmd(at_cmd,"WIFI CONNECTED","ERROR",AT_CMD_TIMEOUT)){printf("AT+CWJAP=失败\r\n");}if(!ESP01_SendATCmd("AT+CIPMUX=0","OK","ERROR",AT_CMD_TIMEOUT)){printf("TCP配置失败:关闭多路连接失败\r\n");}snprintf(at_cmd,sizeof(at_cmd),"AT+CIPSTART=\"TCP\",\"%s\",%d",TCP_SERVER_IP,TCP_SERVER_PORT);if(!ESP01_SendATCmd(at_cmd,"CONNECT","ERROR",AT_CMD_TIMEOUT)){printf("TCP配置失败:连接服务器%s:%d失败\r\n",TCP_SERVER_IP,TCP_SERVER_PORT);}if(!ESP01_SendATCmd("AT+CIPMODE=1","OK","ERROR",AT_CMD_TIMEOUT)){printf("TCP配置失败:传模式失败\r\n");}if(!ESP01_SendATCmd("AT+CIPSEND",">","ERROR",AT_CMD_TIMEOUT)){printf("TCP配置失败:AT+CIPSEND 透传失败\r\n");}else{printf("透传开启\r\n");charstate_str[32]={0};snprintf(state_str,sizeof(state_str),"esp01s open status:%s\r\n","ON");HAL_UART_Transmit(&huart2,(uint8_t*)state_str,strlen(state_str),100);FLG_CWLAP=1;osThreadSuspend(myTask02Handle);}}}}osDelay(10);}}voidStartTask03(void*argument){ESP01_UART_Data_t rx_data={0};charstate_str[256]={0};for(;;){if(osMessageQueueGet(myQueue02Handle,(void*)&rx_data,NULL,5000)==osOK){if(FLG_CWLAP==1){// 打印ESP01响应snprintf(state_str,sizeof(state_str),":%s\r\n",rx_data.data);// 通过ESP01的TCP透传发到服务器:用于检查HAL_UART_Transmit(&huart2,(uint8_t*)state_str,strlen(state_str),100);if(strstr(state_str,":LED_ON")!=NULL){printf("执行指令:点亮LED,当前状态:%s\r\n","ON");HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET);}//添加任务恢复和通信退出即可。}osDelay(2);}osDelay(10);}}voidStartDefaultTask(void*argument){for(;;){printf("\r\n===== FreeRTOS Task Status ====\r\n");memset(task_list_buf,0,TASK_LIST_BUF_SIZE);vTaskList(task_list_buf);printf("%s",task_list_buf);printf("===============================\r\n");osDelay(2000);// 2秒打印一次,释放CPU}}

三、细节说明:

1、关于队列初始化

需要修改大小。否则可能疏忽后,在哪里调试串口。

myQueue01Handle=osMessageQueueNew(5,sizeof(ESP01_UART_Data_t),&myQueue01_attributes);
2、关于任务大小

根据任务的实际分配大小以及内部变量大小出适当改变。若不够可能造成运行异常的问题。

3、关于测试模块

供电上需要独立或稳定的供电条件。若条件不够可能配置总是失败。

4、关于任务优先级

上需要做出调整,优先进行模块的初始化配置,配置完成挂起,当退出模块通信后就恢复挂起的任务。

5、关于模块测试时

每次初始化配置完成后,客户端上需要重新打开服务器的监听进行刷新客户端的状态,否则可能客户端仅能监听无法进行传输通信。
效果图

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 3:37:53

Ubuntu下Qt/C++程序终止全攻略

在Ubuntu系统中&#xff0c;结合Qt和C开发的应用程序可通过以下多种方式安全或强制终止&#xff0c;具体可分为系统级、Qt框架、C标准及线程管理四大类&#xff1a;系统级方法终端命令kill/pkill/killall&#xff1a;通过进程ID或名称发送信号&#xff08;如SIGTERM正常终止&am…

作者头像 李华
网站建设 2026/4/12 16:10:53

Linux信号处理:SIGTERM的底层机制与应用控制

1.Linux信号处理&#xff1a;SIGTERM的底层机制与应用控制在Linux/Unix系统中&#xff0c;捕获SIGTERM信号的行为是由应用程序自主实现的&#xff0c;操作系统仅提供信号传递的底层机制和默认处理逻辑。以下是技术层面的详细解析&#xff1a;1. 操作系统内核的职责信号传递机制…

作者头像 李华
网站建设 2026/4/19 15:01:37

QCoreApplication::applicationDirPath: Please instantiate the QApplication object first

这个错误的核心原因在于QCoreApplication::applicationDirPath()函数必须在QApplication&#xff08;或QCoreApplication&#xff09;实例化之后才能调用。以下是详细分析和解决方案&#xff1a;错误原因分析Qt应用初始化顺序要求Qt框架规定&#xff1a;任何涉及应用程序上下文…

作者头像 李华
网站建设 2026/4/16 23:47:17

12bit 100MHz pipelined SAR ADC模数转换器 设计 65nm工艺,电...

12bit 100MHz pipelined SAR ADC模数转换器 设计 65nm工艺&#xff0c;电源电压1.2V,ENOB11.6 有详细教程原理文档 有工艺库&#xff0c;直接导入自己的cadence [绿圆]结构: 栅压自举开关 CDAC 两级动态比较器 第一级6位SAR ADC 余量放大器 第二级8位SAR ADC 同步和异步SAR l…

作者头像 李华
网站建设 2026/4/19 9:47:38

Emotn TV桌面修改版:三版本满足不同需求,优化时间天气显示与系统性能

Emotn TV桌面作为一款备受用户喜爱的电视桌面应用&#xff0c;经过技术爱好者的优化修改&#xff0c;目前形成了三个各具特色的版本&#xff0c;满足不同用户群体的使用需求。这些修改版在保持原版稳定性的基础上&#xff0c;针对界面显示和系统性能进行了专项优化。 获取地址…

作者头像 李华