上一篇Clion开发STM32之ESP8266系列(二)
/*******************************************************************************
* @author scl
* @email [email protected]
* @brief 串口封装驱动
******************************************************************************/
#ifndef STM32F103VET6_ESP8266_BSP_SERIAL_H
#define STM32F103VET6_ESP8266_BSP_SERIAL_H
#include "bsp_include.h"
/** @brief 检查是否设置了指定的 UART 标志。*/
#define UART_GET_FLAG(__UART__, __FLAG__) (((__UART__)->SR & (__FLAG__)) == (__FLAG__))
/** @brief 使能具体的中断源标志位*/
#define UART_ENABLE_IT(__UART__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__UART__)->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
(((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__UART__)->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
((__UART__)->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))
/** @brief Disable 具体的中断源标志位.*/
#define UART_DISABLE_IT(__UART__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__UART__)->CR1 &= ~((__INTERRUPT__) & UART_IT_MASK)): \
(((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__UART__)->CR2 &= ~((__INTERRUPT__) & UART_IT_MASK)): \
((__UART__)->CR3 &= ~ ((__INTERRUPT__) & UART_IT_MASK)))
#define COM_SIZE 4 /*串口数量*/
typedef enum {
com1 = 0,
com2,
com3,
com4
} serial_port_type;
/********************************串口1 中断**********************************************/
#define COM1_IT_ENABLE (0) // 中断使能
#define COM1_IT_PreemptPriority (0) // 抢占优先级
#define COM1_IT_SubPriority (0) // 响应优先级
/********************************串口2 中断**********************************************/
/********************************串口3 中断**********************************************/
#define COM3_IT_ENABLE (1) // 中断使能
#define COM3_IT_PreemptPriority (0) // 抢占优先级
#define COM3_IT_SubPriority (0) // 响应优先级
/********************************串口4 中断**********************************************/
/********************************串口 通用**********************************************/
UART_HandleTypeDef *com_handle_get(serial_port_type port);
/**
* @brief 串口1初始化
* @param baud 波特率
*/
void com1_init(uint32_t baud);
/**
* @brief 串口3初始化
* @param baud 波特率
*/
void com3_init(uint32_t baud);
#endif //STM32F103VET6_ESP8266_BSP_SERIAL_H
/*******************************************************************************
* @author scl
* @email [email protected]
******************************************************************************/
#include "bsp_serial.h"
/*串口句柄存放数组*/
static UART_HandleTypeDef com_tb[COM_SIZE];
/********************************串口 通用**********************************************/
/**
* @brief 获取串口句柄
* @param port
* @return
*/
inline UART_HandleTypeDef *com_handle_get(serial_port_type port) {
return &com_tb[port];
}
/********************************串口1 START**********************************************/
void com1_init(uint32_t baud) {
UART_HandleTypeDef *ptr = com_handle_get(com1);
ptr->Instance = USART1;
ptr->Init.BaudRate = baud;
ptr->Init.WordLength = UART_WORDLENGTH_8B;
ptr->Init.StopBits = UART_STOPBITS_1;
ptr->Init.Parity = UART_PARITY_NONE;
ptr->Init.Mode = UART_MODE_TX_RX;
ptr->Init.HwFlowCtl = UART_HWCONTROL_NONE;
ptr->Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_DeInit(ptr);
if (HAL_UART_Init(ptr) != HAL_OK) {
error_handle();
}
}
/********************************串口1 END**********************************************/
/********************************串口3 START**********************************************/
void com3_init(uint32_t baud) {
UART_HandleTypeDef *ptr = com_handle_get(com3);
ptr->Instance = USART3;
ptr->Init.BaudRate = baud;
ptr->Init.WordLength = UART_WORDLENGTH_8B;
ptr->Init.StopBits = UART_STOPBITS_1;
ptr->Init.Parity = UART_PARITY_NONE;
ptr->Init.Mode = UART_MODE_TX_RX;
ptr->Init.HwFlowCtl = UART_HWCONTROL_NONE;
ptr->Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_DeInit(ptr);
if (HAL_UART_Init(ptr) != HAL_OK) {
error_handle();
}
}
/********************************串口3 END**********************************************/
/********************************HAL 库串口硬件通用**********************************************/
static inline void com_gpio_init(GPIO_TypeDef *tx_port, uint32_t tx_pin, GPIO_TypeDef *rx_port, uint32_t rx_pin) {
GPIO_InitTypeDef GPIO_InitStruct = {.Pin=tx_pin, .Mode=GPIO_MODE_AF_PP, .Speed=GPIO_SPEED_FREQ_HIGH};
HAL_GPIO_Init(tx_port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = rx_pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(rx_port, &GPIO_InitStruct);
}
/********************************HAL 库串口硬件驱动初始化**********************************************/
void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle) {
if (uartHandle->Instance == USART1) {
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
com_gpio_init(GPIOA, GPIO_PIN_9, GPIOA, GPIO_PIN_10);
#if COM1_IT_ENABLE
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, COM1_IT_PreemptPriority, COM1_IT_SubPriority);
HAL_NVIC_EnableIRQ(USART1_IRQn);
#endif
} else if (uartHandle->Instance == USART3) {
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
com_gpio_init(GPIOB, GPIO_PIN_10, GPIOB, GPIO_PIN_11);
#if COM3_IT_ENABLE
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, COM3_IT_PreemptPriority, COM3_IT_SubPriority);
HAL_NVIC_EnableIRQ(USART3_IRQn);
#endif
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef *uartHandle) {
if (uartHandle->Instance == USART1) {
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);
#if COM1_IT_ENABLE
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
#endif
} else if (uartHandle->Instance == USART3) {
__HAL_RCC_USART3_CLK_DISABLE();
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10 | GPIO_PIN_11);
#if COM3_IT_ENABLE
/* interrupt Deinit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
#endif
}
}
/*******************************************************************************
* @author scl
* @email [email protected]
******************************************************************************/
/*******************************************************************************
* @author scl
* @email [email protected]
******************************************************************************/
#ifndef STM32F103VET6_ESP8266_MODULE_ESP8266_H
#define STM32F103VET6_ESP8266_MODULE_ESP8266_H
#include "app_dr_include.h"
#define ESP_CLOSED_MSG "CLOSED\r\n"
#define RX_BUF_MAX_LEN 1024 // 最大接收缓存字节数
typedef enum {
ap_mode = 0, /* 设置 ESP8266 SoftAP*/
sta_mode = 1, /* 设置 ESP8266 Station*/
sta_ap_mode = 2 /*设置 ESP8266 SoftAP 和 Station*/
} esp8266_net_mode;
typedef enum {
open_mode = 0,
wep_mode = 1,
wpa_psk_mode = 2,
wpa2_psk_mode = 3,
wpa_wpa2_psk_mode = 4,
} esp8266_ap_psd_mode;
typedef enum {
multiple_id_0 = 0,
multiple_id_1 = 1,
multiple_id_2 = 2,
multiple_id_3 = 3,
multiple_id_4 = 4,
single_id_0 = 5, /*单连接模式*/
} esp8266_id_no;
typedef enum {
link_error = 0,/*获取状态失败*/
link_get_ip = 2, /*获取ip*/
link_established = 3, /*建立连接*/
link_lose_connect = 4, /*失去连接*/
} esp8266_link_status;
/**
* @brief esp 延迟函数指针定义
* */
typedef void (*esp_delay_def)(uint32_t ms);
/**
* @brief esp 调试函数指针定义
*/
typedef void (*esp_debug_def)(char *format, ...);
/*************************************************外部实现接口***************************************************/
/**
* @brief esp8266 驱动外设初始化
*/
extern void esp8266_driver_init();
/**
* @brief esp8266 复位引脚
* @param flag true: 置高; false: 置低
*/
extern void esp8266_rst_pin(bool flag);
/**
* @brief esp8266 使能引脚
* @param flag true: 使能
*/
extern void esp8266_ch_enable(bool flag);
/**
* @brief esp8266 发送数据
* @param data
* @param len
*/
extern void esp8266_send(void *data, uint16_t len);
/**
* @brief 清空接收缓冲区
*/
extern void esp8266_clear_buf(void);
/**
* @brief esp8266 接收数据
* @return 接收数据
*/
extern char *esp8266_rec();
/**
* @brief esp8266 构造指令的缓存区
* @return
*/
extern char *esp8266_get_cmd_buf();
/*************************************************底层收发接口***************************************************/
/**
* @brief esp8266发送和接收
* @param data 数据
* @param wait_time 等待响应的时间
* @return 返回结果
*/
char *esp8266_send_and_rec(char *data, uint32_t wait_time);
/**
* @brief esp8266发送和接收 并进行验证
* @param cmd 数据
* @param reply1 期待的响应1,为NULL表不需响应
* @param reply2 期待的响应2,为NULL表不需响应
* reply1和reply2为或逻辑关系
* @param wait_time
* @return
*/
char *esp8266_send_cmd_msg(char *cmd, const char *reply1, const char *reply2, uint32_t wait_time);
/**
* @brief 对WF-ESP8266模块发送AT指令
* @param cmd 发送的指令
* @param reply1 期待的响应1,为NULL表不需响应
* @param reply2 期待的响应2,为NULL表不需响应
* reply1和reply2为或逻辑关系
* @param wait_time 等待响应的时间
* @return
*/
bool esp8266_send_cmd(char *cmd, const char *reply1, const char *reply2, uint32_t wait_time);
/*************************************************函数回调接口***************************************************/
/**
* @brief 设置esp8266 延迟函数回调
* @param call
*/
void esp8266_set_delay_call(esp_delay_def call);
/**
* @brief 设置esp8266 调试函数回调
* @param call
*/
void esp8266_set_debug_call(esp_debug_def call);
/*************************************************基础接口***************************************************/
/**
* @brief 对WF-ESP8266模块进行AT测试启动
* @param try_cnt 尝试次数
* @param wait_time 设置esp8266 延迟函数回调
* @return
*/
bool esp8266_base_at_cmd_test(uint8_t try_cnt, uint32_t wait_time);
/**
* @brief 开关回显功能
* @param en
* true: 开回显
* false: 关回显
* @param wait_time 设置esp8266 延迟函数回调(默认 200)
*/
bool esp8266_base_ate_conf(bool en, uint32_t wait_time);
/**
* @brief 恢复出厂设置
* @param wait_time 设置esp8266 延迟函数回调(默认 200)
*/
bool esp8266_base_factory_reset_conf(uint32_t wait_time);
/**
* @brief 重启WF-ESP8266模块
* @param wait_time 等待响应的时间 (-1,默认为 500 )
*/
void esp8266_base_rst(bool soft, uint32_t wait_time);
/****************************************ESP8266 WIFI 配置**************************************************/
/**
* @brief 设置当前 Wi-Fi 模式,@note 不保存到 Flash
* @param mode
* ap_mode 设置 ESP8266 SoftAP
* sta_mode 设置 ESP8266 Station
* sta_ap_mode 设置 ESP8266 SoftAP 和 Station
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_wifi_mode_cur_set(esp8266_net_mode mode, int wait_time);
/**
* @brief 临时连接 AP
* @note
* 1. 参数设置需要开启 Station 模式,相关配置请查看 @see esp8266_wifi_mode_cur_set
* 2. 若 SSID 或者password 中含有特殊符号,例如 , 或者 “ 或者 \ 时,需要进行转义,其它字符转义无效。
* @param ssid WiFi名称字符串
* @param pwd WiFi密码字符串
* @param bssid 目标 AP 的 MAC 地址(可选配置)
* @param wait_time 等待响应的时间 (-1,默认为 3000 )
* @return
*/
bool esp8266_wifi_join_cur_set(char *ssid, char *pwd, char *bssid, int wait_time);
/**
* @brief 断开与 AP 的连接
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_wifi_disconnect(int wait_time);
/**
* @brief 配置 ESP8266 SoftAP 当前参数
* @note 指令只有在 SoftAP 模式开启后有效,相关配置请查看 @see esp8266_wifi_mode_cur_set
* @param ssid WiFi名称字符串
* @param pwd WiFi密码字符串
* @param channel 通道号
* @param psd_mode 加密方式,不支持 WEP
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_wifi_conf_cur_set(char *ssid, char *pwd, uint8_t channel,
esp8266_ap_psd_mode psd_mode, int wait_time);
/****************************************ESP8266 DHCP 配置**************************************************/
/**
* @brief 设置 DHCP,不保存到 Flash
* @note
* 1. 本设置指令与设置静态 IP 的指令(AT+CIPSTA 系列列和 AT+CIPAP 系列)互相影响
* > 设置使能 DHCP,则静态 IP 无效
* > 设置静态 IP,则 DHCP 关闭
* > 以最后的设置为准
* @param mode
* ap_mode 设置 ESP8266 SoftAP
* sta_mode 设置 ESP8266 Station
* sta_ap_mode 设置 ESP8266 SoftAP 和 Station
* @param en
* true: 开启DHCP
* false: 关闭DHCP
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_dhcp_cur_set(esp8266_net_mode mode, bool en, int wait_time);
/**
* @brief 设置 ESP8266 SoftAP DHCP 分配的 IP 范围,不不保存到 Flash
* @note
* 1. 本指令必须在 ESP8266 SoftAP 模式使能, @see esp8266_wifi_mode_cur_set
* 2. 且开启 DHCP 的情况下使用, @see esp8266_dhcp_cur_set
* 3. 设置的 IP 范围必须与 ESP8266
SoftAP 在同⼀一⽹网段。
* @param en
* false: 清除设置 IP 范围,恢复默认值,后续参数无需填写
* true: 使能设置 IP 范围,后续参数必须填写
* @param lease_min 租约时间,单位:分钟,取值范围 [1, 2880]
* @param start_ip DHCP 服务器 IP 池的起始 IP
* @param end_ip DHCP 服务器 IP 池的结束 IP
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_dhcp_ip_cur_set(bool en, uint16_t lease_min, char *start_ip, char *end_ip, int wait_time);
/****************************************ESP8266 MAC地址 配置**************************************************/
/**
* @brief 设置 ESP8266 Station 当前 MAC 地址,不保存到 Flash
* @note
* 1. ESP8266 SoftAP 和 Station 的 MAC 地址并不相同,请勿将其设置为同一 MAC 地址。
* 2. ESP8266 MAC 地址第一个字节的 bit 0 不不能为 1,例如,MAC 地址可以为 "18:…" 但不不能为 "15:…"。
* @param mac mac地址
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_mac_sta_cur_set(char *mac, int wait_time);
/**
* @brief 设置 ESP8266 SoftAP 当前 MAC 地址,不保存到 Flash
* @note
* 1. ESP8266 SoftAP 和 Station 的 MAC 地址并不相同,请勿将其设置为同一 MAC 地址。
* 2. ESP8266 MAC 地址第一个字节的 bit 0 不不能为 1,例如,MAC 地址可以为 "18:…" 但不不能为 "15:…"。
* @param mac mac地址
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_mac_ap_cur_set(char *mac, int wait_time);
/****************************************ESP8266 IP地址 配置**************************************************/
/**
* @brief 设置 ESP8266 Station 的 IP 地址,不不保存到 Flash
* @note
* 1. 本设置指令与设置 DHCP 的指令(AT+CWDHCP 系列)互相影响: @see esp8266_dhcp_cur_set
* ‣ 设置静态 IP,则 DHCP 关闭;
* ‣ 设置使能 DHCP,则静态 IP 无效;
* ‣ 以最后的设置为准。
* 2. 目前仅支持 C 类 IP 地址
* @param ip 字符串,
* @param gw 网关
* @param sub 子⽹网掩码
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_ip_sta_cur_set(char *ip, char *gw, char *sub, int wait_time);
/**
* @brief 设置 ESP8266 SoftAP 的 IP 地址,不保存到 Flash
* @note
* 1. 本设置指令与设置 DHCP 的指令(AT+CWDHCP 系列)互相影响: @see esp8266_dhcp_cur_set
* ‣ 设置静态 IP,则 DHCP 关闭;
* ‣ 设置使能 DHCP,则静态 IP 无效;
* ‣ 以最后的设置为准。
* 2. 目前仅支持 C 类 IP 地址
* @param ip 字符串,
* @param gw 网关
* @param sub 子网掩码
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_ip_ap_cur_set(char *ip, char *gw, char *sub, int wait_time);
/**
* @brief 获取 F-ESP8266 的 AP IP
* @note ESP8266 Station IP 需连上 AP 后,才可以查询
* @param ret_ip 存放 AP IP 的数组的首地址
* @param len 数组的长度
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_ip_ap_inquire(char *ret_ip, uint8_t len, int wait_time);
/**
* @brief 查询本地 IP 地址
* @note
* 1. ESP8266 Station IP 需连上 AP 后,才可以查询。
* @param dstIp 保存查询结果
* @param len dstIp的长度
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_ip_sta_inquire(char *dstIp, uint8_t len, int wait_time);
/****************************************ESP8266 功能指令**************************************************/
/**
* @brief 获取 WF-ESP8266 的连接状态,较适合单端口时使用
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
esp8266_link_status esp8266_net_link_status(int wait_time);
/**
* @brief 建立 TCP 连接,UDP 传输或 SSL 连接(单连接)
* @param type
* 1: tcp
* 2: udp
* 3: ssl
* @param server_addr 服务器地址
* @param port 服务器端口
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_net_single_socket_build(uint8_t type, char *server_addr, uint16_t port, int wait_time);
/**
* @brief 建立 TCP 连接,UDP 传输或 SSL 连接(多连接)
* @param type
* 1: tcp
* 2: udp
* 3: ssl
* @param link_id 网络连接 ID (0 ~ 4),用于多连接的情况
* @param server_addr 服务器地址
* @param port 服务器端口
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_net_mul_socket_build(uint8_t type, uint8_t link_id, char *server_addr, uint16_t port, int wait_time);
/**
* @brief 关闭 TCP/UDP/SSL 传输
* AT+CIPCLOSE=
* @note
* 需要关闭的连接 ID 号。当 ID 为 5 时,关闭所有连接。(开启 server 后 ID 为 5 无效)
* @param id
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_socket_close(esp8266_id_no id, int wait_time);
/*************************************************ESP8266 服务器和客户端通用***************************************************/
/**
* @brief WF-ESP8266模块启动多连接
* @note
* 1. 默认为单连接;
* 2. 只有⾮透传模式 (AT+CIPMODE=0),才能设置为多连接
* 3. 必须在没有连接建⽴的情况下,设置连接模式;
* 4. 如果建⽴了 TCP 服务器,想切换为单连接,必须关闭服务器 (AT+CIPSERVER=0),服务器仅⽀持多连接
* @param en true: 多连接模式;false 单连接模式
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_mul_connect_set(bool en, int wait_time);
/*************************************************ESP8266 服务端***************************************************/
/**
* @brief 设置服务器允许建⽴立的最大连接数。
* @note
* 1.如需设置最⼤大连接数,请在创建服务器之前设置。
* @param mx_conn 连接数(范围是 1-5)
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_server_connect_num_set(uint8_t mx_conn, int wait_time);
/**
* @brief 设置 TCP 服务器超时时间
* @note
* 1. ESP8266 作为 TCP 服务器,会断开一直不通信直至超时了的 TCP 客户端连接
* 2. 如果设置 AT+CIPSTO=0,则永远不会超时,不建议这样设置
* @param timeout TCP 服务器超时时间,取值范围 0 ~ 7200s
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_server_tcp_timeout_set(uint16_t timeout, int wait_time);
/**
* @brief tcp 服务器建立
* @note
* 1. 多连接情况下 (AT+CIPMUX=1),才能开启 TCP 服务器。
* 2. 创建 TCP 服务器后,自动建立 TCP 服务器监听。
* 3. 当有 TCP 客户端接⼊入,会自动占用一个连接 ID。
* @param en
* true: 开启服务器
* false: 关闭服务器
* @param port 端口
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_server_tcp_start(bool en, uint16_t port, int wait_time);
/**
* @brief 普通模式下发送数据
* @param ucId 客户端连接id号
* @param data 发送的字符串
* @param len 发送的字符串的长度
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_server_tcp_send_to(esp8266_id_no ucId, char *data, uint16_t len, int wait_time);
/*************************************************ESP8266 客户端***************************************************/
/**
* @brief 设置传输模式
* AT+CIPMODE=
* @param en true: 透传模式;false 普通模式
* @note
* 1. 透传模式,仅⽀支持 TCP 单连接和 UDP 固定通信对端的情况
* 2. 本设置不不保存到 Flash。
* 3. 透传模式传输时,如果连接断开, ESP8266 会不不停尝试重连,此时单独输⼊入 +++ 退出透传,则停⽌止重连;
* 普通传输模式则不会重连,提示连接断开。
*
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_transmission_mode_enter(bool en, int wait_time);
/**
* @brief 退出透传模式
* @note
* 1. 仅当传输模式为透传时
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
void esp8266_transmission_mode_exit(int wait_time);
/**
* @brief 在tcp 客户端 透传模式下,更新连接关闭状态标志为
* @param close_status
* true: 已关闭连接
* false: 处于连接中
*/
void esp8266_tcp_update_closed_flag(bool close_status);
/**
* @brief 在tcp 客户端 透传模式下,读取连接关闭状态标志为
* @return
* true: 已关闭连接
* false: 处于连接中
*/
bool esp8266_tcp_read_closed_flag();
/**
* @brief 透传模式下发送数据
* @param str 数据
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return 如果对端不反数据,则为NULL
*/
char *esp8266_transmission_mode_send(char *str, int wait_time);
/**
* @brief WF-ESP8266模块发送字符串
* @param ucId 哪个ID发送的字符串
* @param already_tm_flag 是否已使能了透传模式
* @param str 要发送的字符串
* @param len 字符串的字节数
* @param wait_time 等待响应的时间 (-1,默认为 1000 )
* @return
*/
bool esp8266_send_str(esp8266_id_no ucId, bool already_tm_flag, char *str, uint32_t len, int wait_time);
#endif //STM32F103VET6_ESP8266_MODULE_ESP8266_H
/*******************************************************************************
* @author scl
* @email [email protected]
******************************************************************************/
#include "module_esp8266.h"
#define LEVEL_DELAY 200
#define DELAY_500 500
#define OK_MSG "OK"
#define NO_CHANGE_MSG "no change"
/**
* @brief 判断参数是否为空
* */
#define esp8266_is_null(par) ((par)==NULL)
/**
* @brief 判断带参函数指针是否为空,不为空则执行
*/
#define esp8266_asset_not_nul_run(ptr, par) if((ptr)!=NULL) ptr(par)
/**
* @brief 判断参数是否等于某个值,并重新赋值
*/
#define esp8266_assert_equal_set(par, equal_value, new_value) if((par)==(equal_value)) par=new_value
static void (*esp8266_delay)(uint32_t ms) =NULL;
static void (*esp8266_debug)(char *format, ...) =NULL;
static char *p_cmd = NULL;
#define esp8266_assert_log(log) if(esp8266_debug!=NULL) log
/**
*
* @param call
*/
void esp8266_set_delay_call(esp_delay_def call) {
esp8266_delay = call;
}
void esp8266_set_debug_call(esp_debug_def call) {
esp8266_debug = call;
}
char *esp8266_send_and_rec(char *data, uint32_t wait_time) {
// 发送数据
esp8266_send(data, strlen(data));
/* 发送数据DEBUG */
if (!esp8266_is_null(esp8266_debug) && !esp8266_is_null(data)) {
esp8266_debug("[esp8266_send]%s\r\n", data);
}
// 延迟
esp8266_asset_not_nul_run(esp8266_delay, wait_time);
// 读取数据
char *rec = esp8266_rec();
/* 接收数据DEBUG */
if (!esp8266_is_null(esp8266_debug) && !esp8266_is_null(rec)) {
esp8266_debug("[esp8266_rec]%s\r\n", rec);
}
return rec;
}
char *esp8266_send_cmd_msg(char *cmd, const char *reply1, const char *reply2, uint32_t wait_time) {
bool flag = false;
char *rec_data = esp8266_send_and_rec(cmd, wait_time);
// 判断是否需要接收数据
if (esp8266_is_null(reply1) && esp8266_is_null(reply2)) {
return NULL;
}
// 接收超时
if (esp8266_is_null(rec_data)) return NULL;
if (!esp8266_is_null(reply1) && !esp8266_is_null(reply2)) {
flag = (bool) strstr(rec_data, reply1) || (bool) strstr(rec_data, reply2);
} else if (!esp8266_is_null(reply1)) {
flag = (bool) strstr(rec_data, reply1);
} else {
flag = (bool) strstr(rec_data, reply2);
}
if (flag) {
return rec_data;
}
return NULL;
}
bool esp8266_send_cmd(char *cmd, const char *reply1, const char *reply2, uint32_t wait_time) {
// 清空接收缓冲区
esp8266_clear_buf();
char *msg = esp8266_send_and_rec(cmd, wait_time);
if (esp8266_is_null(reply1) && esp8266_is_null(reply2)) {
return true;
}
if (esp8266_is_null(msg)) {
return false;
}
return true;
}
/*************************************************基础接口***************************************************/
/**
* @brief 对WF-ESP8266模块进行AT测试启动
* @param try_cnt 尝试次数
* @param wait_time 设置esp8266 延迟函数回调
* @return
*/
bool esp8266_base_at_cmd_test(uint8_t try_cnt, uint32_t wait_time) {
esp8266_rst_pin(true);
esp8266_asset_not_nul_run(esp8266_delay, wait_time);
for (int i = 0; i < try_cnt; ++i) {
if (esp8266_send_cmd("AT\r\n", OK_MSG, NULL, wait_time)) {
return true;
} else {
esp8266_base_rst(false, -1);
}
}
return false;
}
bool esp8266_base_ate_conf(bool en, uint32_t wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
if (en) {
return esp8266_send_cmd("ATE1\r\n", OK_MSG, NULL, wait_time);
}
return esp8266_send_cmd("ATE0\r\n", OK_MSG, NULL, wait_time);
}
bool esp8266_base_factory_reset_conf(uint32_t wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
return esp8266_send_cmd("AT+RESTORE\r\n", OK_MSG, NULL, wait_time);
}
void esp8266_base_rst(bool soft, uint32_t wait_time) {
esp8266_assert_equal_set(wait_time, -1, 500);
if (soft) {
esp8266_send_cmd("AT+RST\r\n", OK_MSG, "ready", 2500);
} else {
esp8266_rst_pin(false);
esp8266_asset_not_nul_run(esp8266_delay, wait_time);
esp8266_rst_pin(true);
}
}
/****************************************ESP8266 WIFI 配置**************************************************/
/**
* @brief 设置当前 Wi-Fi 模式,@note 不保存到 Flash
* @param mode
* ap_mode 设置 ESP8266 SoftAP
* sta_mode 设置 ESP8266 Station
* sta_ap_mode 设置 ESP8266 SoftAP 和 Station
* @param wait_time
* @return
*/
bool esp8266_wifi_mode_cur_set(esp8266_net_mode mode, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CWMODE_CUR=%d\r\n", mode);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/**
* @brief 临时连接 AP
* @note
* 1. 参数设置需要开启 Station 模式,相关配置请查看 @see esp8266_wifi_mode_cur_set
* 2. 若 SSID 或者password 中含有特殊符号,例如 , 或者 “ 或者 \ 时,需要进行转义,其它字符转义无效。
* @param ssid WiFi名称字符串
* @param pwd WiFi密码字符串
* @param bssid 目标 AP 的 MAC 地址(可选配置)
* @param wait_time 等待响应的时间 (-1,默认为 3000 )
* @return
*/
bool esp8266_wifi_join_cur_set(char *ssid, char *pwd, char *bssid, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 3000);
p_cmd = esp8266_get_cmd_buf();
if (bssid == NULL) {
sprintf(p_cmd, "AT+CWJAP_CUR=\"%s\",\"%s\"\r\n", ssid, pwd);
} else {
sprintf(p_cmd, "AT+CWJAP_CUR=\"%s\",\"%s\",\"%s\"\r\n", ssid, pwd, bssid);
}
return esp8266_send_cmd(p_cmd, OK_MSG, NO_CHANGE_MSG, wait_time);
}
/**
* @brief 断开与 AP 的连接
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_wifi_disconnect(int wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
return esp8266_send_cmd("AT+CWQAP\r\n", OK_MSG, NO_CHANGE_MSG, wait_time);
}
/**
* @brief 配置 ESP8266 SoftAP 当前参数
* @note 指令只有在 SoftAP 模式开启后有效,相关配置请查看 @see esp8266_wifi_mode_cur_set
* @param ssid WiFi名称字符串
* @param pwd WiFi密码字符串
* @param channel 通道号
* @param psd_mode 加密方式,不支持 WEP
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_wifi_conf_cur_set(char *ssid, char *pwd, uint8_t channel,
esp8266_ap_psd_mode psd_mode, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CWSAP_CUR=\"%s\",\"%s\",%d,%d\r\n", ssid, pwd, channel, psd_mode);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/****************************************ESP8266 DHCP 配置**************************************************/
/**
* @brief 设置 DHCP,不保存到 Flash
* 设置指令: AT+CWDHCP=,
* 响应结果: OK
* @param mode
* ap_mode 设置 ESP8266 SoftAP
* sta_mode 设置 ESP8266 Station
* sta_ap_mode 设置 ESP8266 SoftAP 和 Station
* @param en
* true: 开启DHCP
* false: 关闭DHCP
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_dhcp_cur_set(esp8266_net_mode mode, bool en, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, DELAY_500);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CWDHCP_CUR=%d,%d\r\n", mode, en);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/**
* @brief 设置 ESP8266 SoftAP DHCP 分配的 IP 范围,不不保存到 Flash
* @param en
* false: 清除设置 IP 范围,恢复默认值,后续参数无需填写
* true: 使能设置 IP 范围,后续参数必须填写
* @param lease_min 租约时间,单位:分钟,取值范围 [1, 2880]
* @param start_ip DHCP 服务器 IP 池的起始 IP
* @param end_ip DHCP 服务器 IP 池的结束 IP
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_dhcp_ip_cur_set(bool en, uint16_t lease_min, char *start_ip, char *end_ip, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, DELAY_500);
p_cmd = esp8266_get_cmd_buf();
if (en) {
sprintf(p_cmd, "AT+CWDHCPS_CUR=1,%d,\"%s\",\"%s\"\r\n", lease_min, start_ip, end_ip);
} else {
sprintf(p_cmd, "AT+CWDHCPS_CUR=0\r\n");
}
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/****************************************ESP8266 MAC地址 配置**************************************************/
/**
* @brief 设置 ESP8266 Station 当前 MAC 地址,不保存到 Flash
* @note
* 1. ESP8266 SoftAP 和 Station 的 MAC 地址并不相同,请勿将其设置为同一 MAC 地址。
* 2. ESP8266 MAC 地址第一个字节的 bit 0 不不能为 1,例如,MAC 地址可以为 "18:…" 但不不能为 "15:…"。
* @param mac mac地址
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_mac_sta_cur_set(char *mac, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, DELAY_500);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPSTAMAC_CUR=\"%s\"\r\n", mac);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/**
* @brief 设置 ESP8266 SoftAP 当前 MAC 地址,不保存到 Flash
* @note
* 1. ESP8266 SoftAP 和 Station 的 MAC 地址并不相同,请勿将其设置为同一 MAC 地址。
* 2. ESP8266 MAC 地址第一个字节的 bit 0 不不能为 1,例如,MAC 地址可以为 "18:…" 但不不能为 "15:…"。
* @param mac mac地址
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_mac_ap_cur_set(char *mac, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, DELAY_500);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPAPMAC_CUR=\"%s\"\r\n", mac);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/****************************************ESP8266 IP地址 配置**************************************************/
/**
* @brief 设置 ESP8266 Station 的 IP 地址,不不保存到 Flash
* @note
* 1. 本设置指令与设置 DHCP 的指令(AT+CWDHCP 系列列)互相影响:
* ‣ 设置静态 IP,则 DHCP 关闭;
* ‣ 设置使能 DHCP,则静态 IP ⽆无效;
* ‣ 以最后的设置为准。
* @param ip 字符串串, ESP8266 Station 的 IP 地址
* @param gw 网关
* @param sub 子⽹网掩码
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_ip_sta_cur_set(char *ip, char *gw, char *sub, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, DELAY_500);
p_cmd = esp8266_get_cmd_buf();
if (!esp8266_is_null(gw) && !esp8266_is_null(sub)) {
sprintf(p_cmd, "AT+CIPSTA_CUR=\"%s\",\"%s\",\"%s\"\r\n", ip, gw, sub);
} else {
sprintf(p_cmd, "AT+CIPSTA_CUR=\"%s\"\r\n", ip);
}
return esp8266_send_cmd(p_cmd, OK_MSG, NO_CHANGE_MSG, wait_time);
}
/**
* @brief 设置 ESP8266 SoftAP 的 IP 地址,不保存到 Flash
* @note
* 1. 本设置指令与设置 DHCP 的指令(AT+CWDHCP 系列)互相影响: @see esp8266_dhcp_cur_set
* ‣ 设置静态 IP,则 DHCP 关闭;
* ‣ 设置使能 DHCP,则静态 IP 无效;
* ‣ 以最后的设置为准。
* 2. 目前仅支持 C 类 IP 地址
* @param ip 字符串,
* @param gw 网关
* @param sub 子网掩码
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_ip_ap_cur_set(char *ip, char *gw, char *sub, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, DELAY_500);
p_cmd = esp8266_get_cmd_buf();
if (!esp8266_is_null(gw) && !esp8266_is_null(sub)) {
sprintf(p_cmd, "AT+CIPAP_CUR=\"%s\",\"%s\",\"%s\"\r\n", ip, gw, sub);
} else {
sprintf(p_cmd, "AT+CIPAP_CUR=\"%s\"\r\n", ip);
}
return esp8266_send_cmd(p_cmd, OK_MSG, NO_CHANGE_MSG, wait_time);
}
/****************************************ESP8266 功能指令**************************************************/
esp8266_link_status esp8266_net_link_status(int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 200);
p_cmd = esp8266_get_cmd_buf();
char *msg = esp8266_send_cmd_msg("AT+CIPSTATUS\r\n", OK_MSG, NULL, wait_time);
if (esp8266_is_null(msg)) {
return link_error;
}
if (strstr(msg, "STATUS:2\r\n"))
return link_get_ip;
else if (strstr(msg, "STATUS:3\r\n"))
return link_established;
else if (strstr(msg, "STATUS:4\r\n"))
return link_lose_connect;
return link_error;
}
/**
* @brief 建立 TCP 连接,UDP 传输或 SSL 连接(单连接)
* @param type
* 1: tcp
* 2: udp
* 3: ssl
* @param server_addr 服务器地址
* @param port 服务器端口
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_net_single_socket_build(uint8_t type, char *server_addr, uint16_t port, int wait_time) {
char *pro = type == 1 ? "TCP" : type == 2 ? "UDP" : type == 3 ? "SSL" : NULL;
if (pro == NULL) return false;
esp8266_assert_equal_set(wait_time, -1, DELAY_500);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPSTART=\"%s\",\"%s\",%d\r\n", pro, server_addr, port);
return esp8266_send_cmd(p_cmd, OK_MSG, "CONNECTED", wait_time);
}
/**
* @brief 建立 TCP 连接,UDP 传输或 SSL 连接(多连接)
* @param type
* 1: tcp
* 2: udp
* 3: ssl
* @param link_id 网络连接 ID (0 ~ 4),用于多连接的情况
* @param server_addr 服务器地址
* @param port 服务器端口
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_net_mul_socket_build(uint8_t type, uint8_t link_id, char *server_addr, uint16_t port, int wait_time) {
char *pro = type == 1 ? "TCP" : type == 2 ? "UDP" : type == 3 ? "SSL" : NULL;
if (pro == NULL || link_id > 4) return false;
esp8266_assert_equal_set(wait_time, -1, DELAY_500);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPSTART=%d,\"%s\",\"%s\",%d\r\n", link_id, pro, server_addr, port);
return esp8266_send_cmd(p_cmd, OK_MSG, "CONNECTED", wait_time);
}
/**
* @brief 关闭 TCP/UDP/SSL 传输
* AT+CIPCLOSE=
* @note
* 需要关闭的连接 ID 号。当 ID 为 5 时,关闭所有连接。(开启 server 后 ID 为 5 无效)
* @param id
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_socket_close(esp8266_id_no id, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
p_cmd = esp8266_get_cmd_buf();
if (id < 5) {
sprintf(p_cmd, "AT+CIPCLOSE=%d\r\n", id);
} else {
sprintf(p_cmd, "AT+CIPCLOSE\r\n");
}
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/*************************************************ESP8266 服务器和客户端通用***************************************************/
/**
* @brief WF-ESP8266模块启动多连接
* @note
* 1. 默认为单连接;
* 2. 只有⾮透传模式 (AT+CIPMODE=0),才能设置为多连接
* 3. 必须在没有连接建⽴的情况下,设置连接模式;
* 4. 如果建⽴了 TCP 服务器,想切换为单连接,必须关闭服务器 (AT+CIPSERVER=0),服务器仅⽀持多连接
* @param en true: 多连接模式;false 单连接模式
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_mul_connect_set(bool en, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 500);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPMUX=%d\r\n", en);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/*************************************************ESP8266 服务端***************************************************/
/**
* @brief 设置服务器允许建⽴立的最大连接数。
* @note
* 1.如需设置最⼤大连接数,请在创建服务器之前设置。
* @param mx_conn 连接数(范围是 1-5)
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_server_connect_num_set(uint8_t mx_conn, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
if (mx_conn < 1 || mx_conn > 5) return false;
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPSERVERMAXCONN=%d\r\n", mx_conn);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/**
* @brief 设置 TCP 服务器超时时间
* @note
* 1. ESP8266 作为 TCP 服务器,会断开一直不通信直至超时了的 TCP 客户端连接
* 2. 如果设置 AT+CIPSTO=0,则永远不会超时,不建议这样设置
* @param timeout TCP 服务器超时时间,取值范围 0 ~ 7200s
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_server_tcp_timeout_set(uint16_t timeout, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPSTO=%d\r\n", timeout);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/**
* @brief tcp 服务器建立
* @note
* 1. 多连接情况下 (AT+CIPMUX=1),才能开启 TCP 服务器。
* 2. 创建 TCP 服务器后,自动建立 TCP 服务器监听。
* 3. 当有 TCP 客户端接⼊入,会自动占用一个连接 ID。
* @param en
* true: 开启服务器
* false: 关闭服务器
* @param port 端口
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_server_tcp_start(bool en, uint16_t port, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPSERVER=%d,%d\r\n", en, port);
return esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time);
}
/**
* @brief 普通模式下发送数据
* @param ucId 客户端连接id号
* @param data 发送的字符串
* @param len 发送的字符串的长度
* @param wait_time 等待响应的时间 (-1,默认为 100 )
* @return
*/
bool esp8266_server_tcp_send_to(esp8266_id_no ucId, char *data, uint16_t len, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 100);
p_cmd = esp8266_get_cmd_buf();
if (ucId < 5) {
sprintf(p_cmd, "AT+CIPSEND=%d,%d\r\n", ucId, len);
} else {
sprintf(p_cmd, "AT+CIPSEND=%d\r\n", len);
}
esp8266_send_cmd(p_cmd, NULL, NULL, wait_time);
return esp8266_send_cmd(data, NULL, NULL, wait_time);
}
/*************************************************ESP8266 客户端***************************************************/
/**
* @brief 设置传输模式
* AT+CIPMODE=
* @param en true: 透传模式;false 普通模式
* @note
* 1. 透传模式,仅⽀支持 TCP 单连接和 UDP 固定通信对端的情况
* 2. 本设置不不保存到 Flash。
* 3. 透传模式传输时,如果连接断开, ESP8266 会不不停尝试重连,此时单独输⼊入 +++ 退出透传,则停⽌止重连;
* 普通传输模式则不会重连,提示连接断开。
*
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
bool esp8266_transmission_mode_enter(bool en, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 500);
p_cmd = esp8266_get_cmd_buf();
sprintf(p_cmd, "AT+CIPMODE=%d\r\n", en);
if (esp8266_send_cmd(p_cmd, OK_MSG, NULL, wait_time)) {
return esp8266_send_cmd("AT+CIPSEND\r\n", "SEND OK", 0, wait_time);
}
return false;
}
/**
* @brief 配置WF-ESP8266模块关闭透传模式
* @param wait_time 等待响应的时间 (-1,默认为 500 )
* @return
*/
void esp8266_transmission_mode_exit(int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 500);
// 延迟
esp8266_send_cmd("+++", NULL, NULL, wait_time);
esp8266_asset_not_nul_run(esp8266_delay, wait_time * 2);
}
static volatile bool tcp_closed_flag;
void esp8266_tcp_update_closed_flag(bool close_status) {
tcp_closed_flag = close_status;
}
bool esp8266_tcp_read_closed_flag() {
return tcp_closed_flag;
}
/*************************************************API接口***************************************************/
bool esp8266_ip_ap_inquire(char *ret_ip, uint8_t len, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 500);
p_cmd = esp8266_get_cmd_buf();
char *msg = esp8266_send_cmd_msg("AT+CIFSR\r\n", OK_MSG, NULL, wait_time);
if (esp8266_is_null(msg)) {
return false;
}
char *pCh = strstr(msg, "APIP,\"");
if (pCh) {
pCh += 6;
} else {
return 0;
}
for (uint8_t uc = 0; uc < len; uc++) {
ret_ip[uc] = *(pCh + uc);
if (ret_ip[uc] == '\"') {
ret_ip[uc] = '\0';
break;
}
}
return true;
}
bool esp8266_send_str(esp8266_id_no ucId, bool already_tm_flag, char *str, uint32_t len, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 1000);
p_cmd = esp8266_get_cmd_buf();
bool bRet = false;
if (already_tm_flag) {
esp8266_send(str, len);
bRet = true;
} else {
if (ucId < 5)
sprintf(p_cmd, "AT+CIPSEND=%d,%d\r\n", ucId, len + 2);
else
sprintf(p_cmd, "AT+CIPSEND=%lu\r\n", len + 2);
bRet = esp8266_send_cmd(p_cmd, "SEND OK", 0, wait_time);
}
return bRet;
}
char *esp8266_transmission_mode_send(char *str, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, 100);
p_cmd = esp8266_get_cmd_buf();
/*清除上一次接收的缓存数据*/
esp8266_clear_buf();
return esp8266_send_and_rec(str, wait_time);
}
/*************************************************ESP 查询相关指令***************************************************/
/**
* @brief 查询本地 IP 地址
* @note
* 1. ESP8266 Station IP 需连上 AP 后,才可以查询。
* @param dstIp 保存查询结果
* @param len dstIp的长度
* @param wait_time
* @return
*/
bool esp8266_ip_sta_inquire(char *dstIp, uint8_t len, int wait_time) {
esp8266_assert_equal_set(wait_time, -1, LEVEL_DELAY);
char *result = esp8266_send_cmd_msg("AT+CIFSR\r\n", OK_MSG, NULL, wait_time);
esp8266_assert_log(esp8266_debug("esp8266_ip_sta_inquire: %s", result));
char *ptr = strstr(result, "STAIP,\"");
if (ptr == NULL) return false;
ptr += 7;
for (uint8_t i = 0; i < len; ++i) {
dstIp[i] = ptr[i];
if (ptr[i] == '\"') {
ptr[i] = '\0';
break;
}
}
return true;
}