sonicfirr 发表于 2022-3-13 14:30

七、USART1驱动ESP8266做TCP Client

<p>在下的GD32L233C-START专题测评:</p>

<p>一、开箱评测&nbsp;<a href="https://bbs.eeworld.com.cn/thread-1192788-1-1.html" target="_blank">https://bbs.eeworld.com.cn/thread-1192788-1-1.html</a></p>

<p>二、GD32L233C-START环境搭建<a href="https://bbs.eeworld.com.cn/thread-1193053-1-1.html" target="_blank">https://bbs.eeworld.com.cn/thread-1193053-1-1.html</a></p>

<p>三、点灯案例与扩展<a href="https://bbs.eeworld.com.cn/thread-1193183-1-1.html" target="_blank">https://bbs.eeworld.com.cn/thread-1193183-1-1.html</a></p>

<p>四、Demo工程的分析<a href="https://bbs.eeworld.com.cn/thread-1193279-1-1.html" target="_blank">https://bbs.eeworld.com.cn/thread-1193279-1-1.html</a></p>

<p>五、USART0的printf实现和DMA实现<a href="https://bbs.eeworld.com.cn/thread-1193517-1-1.html" target="_blank">https://bbs.eeworld.com.cn/thread-1193517-1-1.html</a></p>

<p>六、USART1发送和接收的DMA实现<a href="https://bbs.eeworld.com.cn/thread-1196550-1-1.html" target="_blank">https://bbs.eeworld.com.cn/thread-1196550-1-1.html</a></p>

<hr />
<p>&nbsp; &nbsp; &nbsp; &nbsp;本篇沿袭第六篇测评,在USART1口开启DMA收发的基础上驱动ESP8266&nbsp;AT模组,进行TCP&nbsp;Client测试,AP使用手机热点,并通过网络调试助手APP开启了TCP&nbsp;Server。ESP的代码是以前教学时,STM32案例中就开发过的。</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp;按照习惯,建立aita_esp.h和aita_esp.c。</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp;aita_esp.h是一些宏定义和函数说明,ESP8266模块Rx和Tx连接GD32L233的USART1(PA2、PA3),且RST脚连接PA4,已实现MCU重启,控制ESP模块一并重启的效果。其中的宏定义包括:ESP驱动时的错误码(自定义)、复位脚PA4的配置、AITA_ESP_ECHO_EN作为条件编译启用串口提示信息输出、发送和清空接收缓存用了宏以提高可移植性。</p>

<pre>
<code>#ifndef __AITA_ESP_H
#define __AITA_ESP_H


/* Includes ------------------------------------------------------- */
#include "gd32l23x.h"


/* Exported macro ------------------------------------------------- */
//错误码
#define AITA_ESP_REV_OK0//ESP接收完成标志
#define AITA_ESP_WAIT    1//ESP接收未完成标志
//ESP模块Reset管脚及初始化
#define AITA_ESP_RSTPINGPIO_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</code></pre>

<p>&nbsp;</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp;aita_esp.c的代码中预留了HTTP和MQTT(旧版)连接OneNet的接口(宏),这也是以前STM32案例中创建的,本例中没有使用到。</p>

<pre>
<code>/* 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_taita_esp_buf;
//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——&gt; 等待超时(乘以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——&gt; 发送的命令字串
*                char *res——&gt; 期待的回复字串
* 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——&gt; 发送的数据
*                uint16_t len——&gt; 数据串长度
* Returns      : void
*********************************************************************/
void aita_SendDatESP(uint8_t *data, uint16_t len) {
char atsendcmd;
AITA_ESP_CLEAR();
sprintf(atsendcmd, "AT+CIPSEND=%d\r\n", len);
if(!(aita_SendCmdESP(atsendcmd, "&gt;")))
    AITA_ESP_SEND(data, len);
}</code></pre>

<p>&nbsp;</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp;main.c中编写了一个测试函数,非常简单&mdash;&mdash;上电连接wifi、连接TCP&nbsp;Server、循环发送字串。</p>

<pre>
<code>//在main函数中调用
void aita_TestESP(void) {
char buf;
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);
}
}</code></pre>

<p>&nbsp;</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp;最后的效果如下,开了两个串口终端,一个连接USART0接收系统输出信息,一个连接到USART1(并联ESP8266&nbsp;Rx脚)查看ESP接收到的AT命令。</p>

<p class="imagemiddle" style="text-align: center;"></p>

<p style="text-align:justify">&nbsp;</p>

Jacktang 发表于 2022-3-14 08:24

<p>归纳总结的比较好</p>

阿斯顿v 发表于 2024-4-26 01:49

<p>楼主你好,最近在学GD32,按照您的代码复现有点问题,可以参考一下您的源码吗</p>

<p>&nbsp;</p>
页: [1]
查看完整版本: 七、USART1驱动ESP8266做TCP Client