一、前期配置情况




二、代码部分展示
1、数据定义:
c
#define USART1_DMA_BUF_SIZE 256
#define UART_RX_BUF_SIZE 256
#define USART2_DMA_BUF_SIZE 256
#define AT_CMD_TIMEOUT 3000
typedef struct {
uint8_t data[UART_RX_BUF_SIZE];
uint16_t len;
} ESP01_UART_Data_t;
uint8_t ESP01_SendATCmd(const char *cmd, const char *resp_ok, const char *resp_err, uint32_t timeout);
#define TASK_LIST_BUF_SIZE 512
char task_list_buf[TASK_LIST_BUF_SIZE];
uint8_t FLG_CWLAP=0;
typedef struct wifiinfo
{
char wifi_ssid[160];
char wifi_pwd[160];
char tcp_server_ip[11];
} uwifi_info;
uwifi_info use_wifi={0};
二、重要函数编写
c
uint8_t usart1_dma_buf[USART1_DMA_BUF_SIZE] = {0};
uint8_t usart2_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的中断服务函数类似
void USART1_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_t ESP01_SendATCmd(const char *cmd, const char *resp_ok, const char *resp_err, uint32_t timeout)
{
uint8_t retry = 0;
ESP01_UART_Data_t rx_data = {0};
TickType_t xStartTick = xTaskGetTickCount();
char temp_buf[USART2_DMA_BUF_SIZE * 2] = {0};
uint16_t temp_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);
return 1;
} // 5. 匹配失败响应
if (strstr(temp_buf, resp_err) != NULL)
{
// printf("匹配到失败响应:%s\r\n", resp_err);
break;
}
}
}
retry++;
vTaskDelay(50);
}
return 0;
}
任务调用
c
void StartTask02 (void *argument)
{
ESP01_UART_Data_t rx_data =
{ 0 };
char cmd_buf[UART_RX_BUF_SIZE] =
{ 0 };
char at_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);
}
else if (strcmp (cmd_buf, "LED_OFF") == 0)
{
printf ("执行指令:关闭LED,当前状态:%s\r\n", "OFF");
HAL_GPIO_WritePin (GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
}
else if (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);
}
else if (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);
}
else if (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);
}
else if(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);
}
else if (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_ssid
snprintf (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");
char state_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);
}
}
void StartTask03 (void *argument)
{
ESP01_UART_Data_t rx_data = {0};
char state_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);
}
}
void StartDefaultTask(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、关于队列初始化
需要修改大小。否则可能疏忽后,在哪里调试串口。
c
myQueue01Handle = osMessageQueueNew(5, sizeof(ESP01_UART_Data_t),
&myQueue01_attributes);
2、关于任务大小
根据任务的实际分配大小以及内部变量大小出适当改变。若不够可能造成运行异常的问题。
3、关于测试模块
供电上需要独立或稳定的供电条件。若条件不够可能配置总是失败。
4、关于任务优先级
上需要做出调整,优先进行模块的初始化配置,配置完成挂起,当退出模块通信后就恢复挂起的任务。
5、关于模块测试时
每次初始化配置完成后,客户端上需要重新打开服务器的监听进行刷新客户端的状态,否则可能客户端仅能监听无法进行传输通信。
效果图 :

源码:https://download.csdn.net/download/weixin_44386927/92458219?spm=1001.2014.3001.5501