七、USART1驱动ESP8266做TCP Client
[复制链接]
在下的GD32L233C-START专题测评:
一、开箱评测 https://bbs.eeworld.com.cn/thread-1192788-1-1.html
二、GD32L233C-START环境搭建https://bbs.eeworld.com.cn/thread-1193053-1-1.html
三、点灯案例与扩展https://bbs.eeworld.com.cn/thread-1193183-1-1.html
四、Demo工程的分析https://bbs.eeworld.com.cn/thread-1193279-1-1.html
五、USART0的printf实现和DMA实现https://bbs.eeworld.com.cn/thread-1193517-1-1.html
六、USART1发送和接收的DMA实现https://bbs.eeworld.com.cn/thread-1196550-1-1.html
本篇沿袭第六篇测评,在USART1口开启DMA收发的基础上驱动ESP8266 AT模组,进行TCP Client测试,AP使用手机热点,并通过网络调试助手APP开启了TCP Server。ESP的代码是以前教学时,STM32案例中就开发过的。
按照习惯,建立aita_esp.h和aita_esp.c。
aita_esp.h是一些宏定义和函数说明,ESP8266模块Rx和Tx连接GD32L233的USART1(PA2、PA3),且RST脚连接PA4,已实现MCU重启,控制ESP模块一并重启的效果。其中的宏定义包括:ESP驱动时的错误码(自定义)、复位脚PA4的配置、AITA_ESP_ECHO_EN作为条件编译启用串口提示信息输出、发送和清空接收缓存用了宏以提高可移植性。
#ifndef __AITA_ESP_H
#define __AITA_ESP_H
/* Includes ------------------------------------------------------- */
#include "gd32l23x.h"
/* Exported macro ------------------------------------------------- */
//错误码
#define AITA_ESP_REV_OK 0//ESP接收完成标志
#define AITA_ESP_WAIT 1//ESP接收未完成标志
//ESP模块Reset管脚及初始化
#define AITA_ESP_RSTPIN GPIO_PIN_4
#define AITA_ESP_RSTPORT GPIOA
//#define AITA_ESP_RST PAout(4) //GD MCU中无效
#define AITA_ESP_RST_SET \
gpio_bit_set(AITA_ESP_RSTPORT, AITA_ESP_RSTPIN)
#define AITA_ESP_RST_CLR \
gpio_bit_reset(AITA_ESP_RSTPORT, AITA_ESP_RSTPIN)
#define AITA_ESP_RSTPIN_INIT \
rcu_periph_clock_enable(RCU_GPIOA); \
gpio_mode_set(AITA_ESP_RSTPORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, AITA_ESP_RSTPIN); \
gpio_output_options_set(AITA_ESP_RSTPORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, AITA_ESP_RSTPIN);
//ESP模块操作printf输出提示使能
#define AITA_ESP_ECHO_EN 1
//ESP模块接口API
#define AITA_ESP_SEND aita_U1SendStr
#define AITA_ESP_CLEAR aita_ClearU1RxBuffer
/* Exported function prototypes ----------------------------------- */
void aita_InitESP(void);
uint16_t aita_WaitRecvESP(void);
uint16_t aita_SendCmdESP(char *cmd, char *res);
void aita_SendDatESP(uint8_t *data, uint16_t len);
uint8_t* aita_GetIPDESP(uint16_t timeout);
#endif
aita_esp.c的代码中预留了HTTP和MQTT(旧版)连接OneNet的接口(宏),这也是以前STM32案例中创建的,本例中没有使用到。
/* Includes ------------------------------------------------------- */
#include "aita_sys.h"
/* Private macro -------------------------------------------------- */
//延时API
#define AITA_ESP_DELAYMS delay_1ms
//联网命令
#define AITA_ESP_WIFI_INFO "AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n"
//测试TCP接口
#define AITA_ESP_TCP_SERVER_SOCKET \
"AT+CIPSTART=\"TCP\",\"192.168.43.1\",1234\r\n"
//OneNet HTTP接口
#define AITA_ESP_ONENET_HTTP_SOCKET \
"AT+CIPSTART=\"TCP\",\"183.230.40.33\",80\r\n"
//OneNet MQTT接口
#define AITA_ESP_ONENET_MQTT_SOCKET \
"AT+CIPSTART=\"TCP\",\"183.230.40.39\",6002\r\n"
//主要AT命令及返回
#define AITA_ESP_AT_CMD "AT\r\n"
#define AITA_ESP_AT_OK "OK"
#define AITA_ESP_AT_STA "AT+CWMODE=1\r\n"
#define AITA_ESP_AT_AP "AT+CWMODE=2\r\n"
#define AITA_ESP_AT_STA_AP "AT+CWMODE=3\r\n"
#define AITA_ESP_AT_JAP AITA_ESP_WIFI_INFO
#define AITA_ESP_AT_JAP_OK "GOT IP"
//请根据接入方式设置宏定义
//AITA_ESP_ONENET_HTTP_SOCKET HTTP接入
//AITA_ESP_ONENET_MQTT_SOCKET MQTT接入
#define AITA_ESP_AT_CIP AITA_ESP_TCP_SERVER_SOCKET
#define AITA_ESP_AT_CIP_OK "CONNECT"
//ESP接收缓存
#define AITA_ESP_BUF u1rxbuffer
#define AITA_ESP_BUF_LEN USART1_BUF_LENGTH
//ESP接收计数
#define AITA_ESP_CNT u1rxindex
/* Private variables ---------------------------------------------- */
//uint8_t aita_esp_buf[AITA_ESP_BUF_LEN];
//uint16_t aita_esp_cntnow = 0;
uint16_t aita_esp_cntpre = 0;
/* Exported functions --------------------------------------------- */
/*********************************************************************
* FunctionName : aita_InitESP()
* Description : ESP模块初始化,使用串口需单独初始化
* Parameters : void
* Returns : void
*********************************************************************/
void aita_InitESP(void) {
AITA_ESP_RSTPIN_INIT;
AITA_ESP_RST_CLR;
AITA_ESP_DELAYMS(250);
AITA_ESP_RST_SET;
AITA_ESP_DELAYMS(500);
AITA_ESP_CLEAR();
#if AITA_ESP_ECHO_EN
printf("1. ESP AT\r\n");
while(aita_SendCmdESP(AITA_ESP_AT_CMD, AITA_ESP_AT_OK))
AITA_ESP_DELAYMS(500);
#endif
#if AITA_ESP_ECHO_EN
printf("2. ESP STA MODE\r\n");
while(aita_SendCmdESP(AITA_ESP_AT_STA, AITA_ESP_AT_OK))
AITA_ESP_DELAYMS(500);
#endif
#if AITA_ESP_ECHO_EN
printf("3. ESP Join AP\r\n");
while(aita_SendCmdESP(AITA_ESP_AT_JAP, AITA_ESP_AT_JAP_OK))
AITA_ESP_DELAYMS(500);
#endif
#if AITA_ESP_ECHO_EN
printf("4. ESP START CIPSEND\r\n");
while(aita_SendCmdESP(AITA_ESP_AT_CIP, AITA_ESP_AT_CIP_OK))
AITA_ESP_DELAYMS(500);
#endif
#if AITA_ESP_ECHO_EN
printf("5. ESP Inialization Done!\r\n");
#endif
}
/*********************************************************************
* FunctionName : aita_GetIPDESP()
* Description : 获取平台返回的数据
* Parameters : uint16_t timeout ——> 等待超时(乘以10ms)
* Returns : 平台返回的原始数据
*********************************************************************/
uint8_t* aita_GetIPDESP(uint16_t timeout) {
char *pIPD = 0;
do {
if(aita_WaitRecvESP() == AITA_ESP_REV_OK) {
pIPD = strstr((char *)AITA_ESP_BUF, "IPD,");
if(pIPD == 0) {}
else {
pIPD = strchr(pIPD, ':');
if(pIPD != 0) {
pIPD++;
return (uint8_t *)pIPD;
} else {
return 0;
}
}
}
AITA_ESP_DELAYMS(10);
} while(timeout--);
return 0;
}
//void aita_ClearESPBuf(void) {
// memset(AITA_ESP_BUF, 0, AITA_ESP_BUF_LEN);
// AITA_ESP_CNT = 0;
//}
/*********************************************************************
* FunctionName : aita_WaitRecvESP()
* Description : 判断ESP接收状态
* Parameters : void
* Returns : AITA_ESP_REV_OK-接收完成,AITA_ESP_WAIT-接收未完成
*********************************************************************/
uint16_t aita_WaitRecvESP(void) {
//接收0字节,说明还要等待接收完毕
if(AITA_ESP_CNT == 0) return AITA_ESP_WAIT;
//上次和本次字节数一致,说明接收完毕
if(aita_esp_cntpre == AITA_ESP_CNT) {
return AITA_ESP_REV_OK;
}
aita_esp_cntpre = AITA_ESP_CNT;
return AITA_ESP_WAIT;
}
/*********************************************************************
* FunctionName : aita_SendCmdESP()
* Description : 向ESP发送AT命令
* Parameters : char *cmd ——> 发送的命令字串
* char *res ——> 期待的回复字串
* Returns : 0-成功;1-失败
*********************************************************************/
uint16_t aita_SendCmdESP(char *cmd, char *res) {
uint16_t timeout = 200;
AITA_ESP_SEND((uint8_t *)cmd, strlen(cmd));
while(timeout--) {
if(aita_WaitRecvESP() == AITA_ESP_REV_OK) {
if(strstr((const char *)AITA_ESP_BUF, res) != 0) {
AITA_ESP_CLEAR();
return 0;
}
}
AITA_ESP_DELAYMS(10);
}
return 1;
}
/*********************************************************************
* FunctionName : aita_SendDatESP()
* Description : 利用AT+SEND命令发送数据
* Parameters : uint8_t *data ——> 发送的数据
* uint16_t len ——> 数据串长度
* Returns : void
*********************************************************************/
void aita_SendDatESP(uint8_t *data, uint16_t len) {
char atsendcmd[32];
AITA_ESP_CLEAR();
sprintf(atsendcmd, "AT+CIPSEND=%d\r\n", len);
if(!(aita_SendCmdESP(atsendcmd, ">")))
AITA_ESP_SEND(data, len);
}
main.c中编写了一个测试函数,非常简单——上电连接wifi、连接TCP Server、循环发送字串。
//在main函数中调用
void aita_TestESP(void) {
char buf[32];
uint16_t i = 0;
while(1) {
memset(buf, 0, 32);
sprintf(buf, "Times %d\r\n", i++);
aita_SendDatESP((uint8_t *)buf, sizeof(buf));
delay_1ms(5000);
}
}
最后的效果如下,开了两个串口终端,一个连接USART0接收系统输出信息,一个连接到USART1(并联ESP8266 Rx脚)查看ESP接收到的AT命令。
|