WIFI
1 ESP32-C3
ESP32-C3 搭载 RISC-V 32 位单核处理器,时钟频率高达 160 MHz。具有 22 个可编程 GPIO 管脚、内置 400 KB SRAM。
2 项目准备
2.1 固件烧录工具下载
https://www.espressif.com.cn/zh- ... _type_tid%5B%5D=785
2.2 固件下载
https://docs.espressif.com/proje ... nloading_guide.html
2.3 烧录固件
2.4 关于AT指令
ESP-AT 提供了大量功能不同的 AT 命令,如 Wi-Fi 命令、TCP/IP 命令、Bluetooth LE 命令、Bluetooth 命令、MQTT 命令、HTTP 命令、Ethernet 命令等。
AT 命令以 “AT” 开始,代表 Attention,以新的一行 (CR LF) 为结尾。输入的每条命令都会返回 OK 或 ERROR 的响应,表示当前命令的最终执行结果。注意,所有 AT 命令均为串行执行,每次只能执行一条命令。因此,在使用 AT 命令时,应等待上一条命令执行完毕后,再发送下一条命令。如果上一条命令未执行完毕,又发送了新的命令,则会返回 busy p
3 案例
STM32通过串口UART2与ESP32-C3连接
3.1 案例1:测试AT指令
需求:测试AT指令,测试AT指令是否能够正常控制ESP32的wifi,比如重启,读取设备信息等。
CubeMX配置
Inf_ESP32.c
ESP32初始化
#include "Inf_ESP32.h"
uint8_t rBuff[128];
uint16_t rDataLength;
uint8_t responseBuff[1024];
uint16_t resDataLength;
// 需要使用的回调函数
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
// 健壮性判断
if (huart->Instance == USART2)
{
// 此时是ESP32回复消息了
rDataLength = Size;
// 一次调用HAL_UARTEx_ReceiveToIdle_IT 只能触发一次回调
HAL_UARTEx_ReceiveToIdle_IT(&huart2, rBuff, 128);
// 最简单的方式 => 直接打印接收到的数据
// 原则性问题:不能在中断处理中使用运行时间过长的函数
// printf("接收到ESP32的消息:%s\n", rBuff);
}
}
void Inf_Handle_Response(void)
{
// 循环等待接收多次5消息 => 一直到接收完毕 或者 收到OK或者ERROR
uint8_t count = 5;
/* 1. 初始化responseBuff */
memset(responseBuff, 0, 1024);
resDataLength = 0;
do
{
// 将单次接收到的数据存放到responseBuff中
while (rDataLength == 0)
;
/* 2. 直到等到有数据过来 => 存放到大的缓存中*/
memcpy(&responseBuff[resDataLength], rBuff, rDataLength);
resDataLength += rDataLength;
rDataLength = 0;
memset(rBuff, 0, 128);
} while (count-- && (strstr((char *)responseBuff, "OK") == NULL) && (strstr((char *)responseBuff, "ERROR") == NULL));
printf("%s\n",responseBuff);
printf("-------------------\n");
}
void Inf_ESP32_SendCmd(uint8_t *cmd)
{
// 直接使用USART2发送消息就是发送AT命令
HAL_UART_Transmit(&huart2, cmd, strlen((char *)cmd), 1000);
// 由于不能一次执行多个指令 => 挂起等待执行响应
Inf_Handle_Response();
}
void Inf_ESP32_Init(void)
{
/* 1. 初始化usart2 */
MX_USART2_UART_Init();
/* 2. 提前调用接收ESP32返回的消息的函数 => 会触发对应的回调函数 HAL_UARTEx_RxEventCallback*/
HAL_UARTEx_ReceiveToIdle_IT(&huart2, rBuff, 128);
/* 3. 发送AT指令让ESP32重置 */
uint8_t *cmd = "AT+RST=0\r\n";
Inf_ESP32_SendCmd(cmd);
// 延时3s等待ESP32重启
HAL_Delay(3000);
}
main.c
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
// MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
printf("hello wifi...\n");
Inf_ESP32_Init();
// 测试AT响应
uint8_t *cmd = "AT\r\n";
Inf_ESP32_SendCmd(cmd);
// ESP32指令是串行的 不能同时执行两个指令
// HAL_Delay(100);
cmd = "AT+GMR\r\n";
Inf_ESP32_SendCmd(cmd);
/* USER CODE END 2 */
测试结果
3.2 案例2:TCP通讯
需求:TCP通讯,使用AT指令在ESP32上面启动一个TCP服务器,从而可以与其他TCP客户端实现TCP通讯。
项目开发
1. 初始化ESP32
(1) 初始化底层驱动 usart2
(2) 调用接收ESP32信息的函数
(3) 重置ESP32即可 => 延时3s
2. 初始化WIFI
(1) 设置充当的WIFI角色 => station 站点 => 用来连接别人的热点
注意:电脑开热点的时候一定要选2.4G的
(2) 连接热点 => 填写WIFI的账号和密码即可
3. 启动TCP服务端
(1) 开启多连接
(2) 创建TCP服务端
(3) 设置IPDInfo信息
4. 编写接收消息的函数
(1) +IPD,0,2,“192.168.137.1”,1179:OK 固定格式
(2) sscanf拆分匹配对应的数据
(3) strtok切分data数据
5. 编写发送数据的函数
(1) 发送需要发送数据的AT指令
AT+CIPSEND=id,length\r\n
(2) 使用USART2发送数据 => 长度达到length自动发送
Inf_ESP32.c
在上个案例的基础上加以下函数
准备好连接WiFi的名称和密码
void Inf_ESP32_WIFI_Init(void)
{
/*1. 初始化ESP32*/
Inf_ESP32_Init();
/*2. 设置站点模式*/
/*AT+CWMODE=<mode>
<mode>:模式
0: 无 Wi-Fi 模式,并且关闭 Wi-Fi RF
1: Station 模式
2: SoftAP 模式
3: SoftAP+Station 模式*/
uint8_t * cmd = "AT+CWMODE=1\r\n";
Inf_ESP32_SendCmd(cmd);
/*3. 连接AP热点*/
cmd = "AT+CWJAP=\"DESKTOP-2UH9TD7\",\"<257M5x4\"\r\n";
Inf_ESP32_SendCmd(cmd);
}
void Inf_ESP32_Start_TCP_server(void)
{
/*1. 开启多链接模式*/
uint8_t *cmd = "AT+CIPMUX=1\r\n";
Inf_ESP32_SendCmd(cmd);
/*2. 建立TCP连接*/
cmd = "AT+CIPSERVER=1,8080\r\n";
Inf_ESP32_SendCmd(cmd);
/*3. 设置IPDInfo信息*/
cmd = "AT+CIPDINFO=1\r\n";
Inf_ESP32_SendCmd(cmd);
}
void Inf_ESP32_ReadData(uint8_t rxBuff[],uint8_t * id,uint16_t * recvDataLength,uint8_t * ip,uint16_t * port)
{
//0. 健壮性判断
if (rDataLength == 0)
{
return;
}
//1. 初始化rxBuff
memset(rxBuff,0,sizeof(rxBuff));
//2. 拆分匹配数据
// %*忽略/r/n +IPD, %[^\"] 匹配字符串直到遇见"
sscanf((char *)rBuff,"%*[\r\n]+IPD,%d,%d,\"%[^\"]\",%d",
(int *)id,
(int *)recvDataLength,
ip,
(int *)port);
// 切分字符串
strtok((char *)rBuff,":"); // 获取到切分之前的字符串
memcpy(rxBuff,strtok(NULL,":"),*recvDataLength);
//3. 接收数据清空
memset(rBuff,0,128);
rDataLength = 0;
}
void Inf_ESP32_SendData(uint8_t id,uint8_t data[],uint16_t dataSize)
{
uint8_t cmd[100] = {0};
sprintf((char *)cmd,"AT+CIPSEND=%d,%d\r\n",id,dataSize);
// 1. 发送请求发送数据的命令
Inf_ESP32_SendCmd(cmd);
// 2. 发送数据 => 达到dataSize的长度固定开始发送
HAL_UART_Transmit(&huart2,data,dataSize,1000);
}
main.c
/* USER CODE BEGIN 2 */
printf("hello WIFI...\n");
// Inf_ESP32_Init();
Inf_ESP32_WIFI_Init();
Inf_ESP32_Start_TCP_server();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
uint8_t rxBuff[128] = {0};
uint8_t id = 0;
uint8_t ip[16] = {0};
uint16_t recvDataLength = 0;
uint16_t port = 0;
while (1)
{
Inf_ESP32_ReadData(rxBuff, &id, &recvDataLength, ip, &port);
if (recvDataLength > 0)
{
printf("id:%d,ip:%s,port:%d,data:%s\n", id, ip, port, rxBuff);
Inf_ESP32_SendData(id, rxBuff,recvDataLength);
// 清空收到数据的长度 => 给下次收数据做准备
recvDataLength = 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
实验结果
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_74967868/article/details/143098721
|
|