硬件:
STM32F407ZGT6
SDK:HAL库
RTOS:RT-Thread
1 AT指令步骤
-
AT+RST
复位 -
设置WIFI模式:
AT+CWMODE_DEF=1
(设置为 station 模式) -
连接路由器
AT+CWJAP_DEF="ssid","password"
/(_DEF
保存flash) -
查询 ESP8266 设备的 IP 地址
AT+CIFSR
-
创建 UDP 连接:
AT+CIPSTART="UDP","192.168.101.110",8080,1112,2
192.168.101.110
和8080
:分别为远端ip和port;1112
:为esp模块端口;2
:表示当前 UDP 传输建⽴后,UDP 传输远端仍然会更改,UDP 传输远端会⾃动更改为最近⼀个与ESP8266 UDP 通信的远端。(即远端可变)
-
发送数据:
AT+CIPSEND=32
(32为数据长度 )
发送该指令后,紧接着可发送<=设定长度的字符数据 -
断开连接:AT+CIPCLOSE (连接后需要断开连接才能再次创建 UDP 传输)
2 ESP串口通信代码
2.1 串口缓冲队列
#define UART_QUEUE_MAXSIZE 512
typedef struct
{
uint16_t front;
uint16_t rear;
uint8_t data[UART_QUEUE_MAXSIZE];
} uart_queue_t;
static uint8_t esp_rx_buf[UART_QUEUE_MAXSIZE];
static uint16_t pos = 0;
uart_queue_t uart4_queue;
void uart_queue_push(uart_queue_t *q, const uint8_t *data)
{
if ((q->rear + 1) % UART_QUEUE_MAXSIZE == q->front)
return;
q->data[q->rear] = *data;
q->rear = (q->rear + 1) % UART_QUEUE_MAXSIZE;
}
void uart_queue_pop(uart_queue_t *q, uint8_t *data)
{
if (q->front == q->rear)
return;
*data = q->data[q->front];
q->front = (q->front + 1) % UART_QUEUE_MAXSIZE;
}
uint16_t uart_queue_get_data(uart_queue_t *q, uint8_t *pbuf)
{
uint8_t data;
while ((q->rear - q->front + UART_QUEUE_MAXSIZE) % UART_QUEUE_MAXSIZE)
{
uart_queue_pop(q, &data);
if (pos >= UART_QUEUE_MAXSIZE)
return 0;
pbuf[pos++] = data;
}
return pos;
}
void UART4_IRQHandler(void)
{
uint8_t rx_data;
if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_RXNE) != RESET){
rx_data = READ_REG(huart4.Instance->DR);
uart_queue_push(&uart4_queue, &rx_data);
}
}
2.2 发送AT指令
void usart_sendString(UART_HandleTypeDef *huart, const uint8_t *str)
{
while (*str != '\0')
{
HAL_UART_Transmit(huart, (uint8_t *)str, 1, 1000);
str++;
}
}
HAL_StatusTypeDef esp_send_cmd(const char *cmd, const char *reply, uint16_t timeout)
{
rt_memset(cmd_buf, 0, UART_QUEUE_MAXSIZE);
rt_memset(esp_rx_buf, 0, pos);
pos = 0;
strcpy(cmd_buf, cmd);
if (strstr(cmd_buf, "\r\n") == NULL)
strcat(cmd_buf, "\r\n");
usart_sendString(&huart4, cmd_buf);
while (timeout)
{
if (uart_queue_get_data(&uart4_queue, esp_rx_buf))
{
if (strstr(esp_rx_buf, reply) != NULL)
{
printf("%s", esp_rx_buf);
return HAL_OK;
}
}
timeout--;
rt_thread_mdelay(1);
}
return HAL_TIMEOUT;
}
cmd
:要发送的AT指令reply
:esp收到该指令后正确回复信息(如OK
)timeout
:超时等待时间,单位ms
2.3 发送UDP消息
void esp_send_udp(const char *data)
{
char cmd_buf[16];
sprintf(cmd_buf, "AT+CIPSEND=%d", strlen(data));
if (esp_send_cmd(cmd_buf, "OK", 500) == HAL_OK)
esp_send_cmd(data, "SEND OK", 1000);
}
示例:esp_send_udp("{\"data\":\"led\",\"status\":\"on\"}");
2.4 UDP通信初始化
void esp_init(void)
{
// 复位
esp_send_cmd("AT+RST", "OK", 800);
// 设置为 station 模式
esp_send_cmd("AT+CWMODE_CUR=3", "OK", 500);
// 连接wifi
esp_send_cmd("AT+CWJAP_CUR=\"ssid\",\"password\"", "OK", 5000);
// 创建 UDP 连接, 微信小程序端口为9999
esp_send_cmd("AT+CIPSTART=\"UDP\",\"192.168.239.14\",9999,1111,2", "OK", 1000);
// 获取esp8266 ip
esp_send_cmd("AT+CIFSR", "OK", 500);
}
END