云计算百科
云计算领域专业知识百科平台

stm32实现esp8266连接到TCP服务器(二)

1.2 连接到TCP Server

                1.2.1 使用网络助手,设立TCP服务器

ffeb445201fa4e8e90e47bb5983b9e21.png

25e56e8e7a3441ddaa4389aaa537ae58.png编辑

                1.2.2 连接服务器

AT+CIPSTART="TCP","192.168.1.18",8080 //指令,注意双引号逗号都要半角(英文)输入 CONNECT //结果:成功 OK //结果:成功 OK

                1.2.3 发送数据

AT+CIPSEND=4 //设置即将发送数据的长度

>abcd        //看到大于号后,输入消息,abcd,不要带回车

Response :SEND OK //结果:成功

//注意,这种情况下,每次发送前都要线发送AT+CIPSEND=长度,的指令,在发数据!

1.3 透传

用AT + CIPSEND = 4,每次发送数据都要进行字符长度设定

今天透传模式

AT+CIPMODE=1 //开启透传模式

Response :OK

AT+CIPSEND //带回车

Response: > //这个时候随意发送接收数据咯

退出透传模式

 在透传发送数据过程中,若识别到单独的⼀包数据 “+++”,则退出透传发送

 

 

头文件

#include "sys.h"
#include "esp8266.h"
#include "string.h"
#include "delay.h"
#include "stdarg.h"
uint8_t esp8266_tx_buf[ESP8266_TX_BUF_SIZE];
uint8_t esp8266_rx_buf[ESP8266_RX_BUF_SIZE];

uint16_t esp8266_cnt = 0 ,esp8266_cntPre = 0; /* esp8266接收缓冲区 */

UART_HandleTypeDef esp8266_handle; /* esp8266句柄 */

esp8266模块串口配置初始化

//正常会有启动的流程只是作为一个串口的初始化
void esp8266_uart_init(uint16_t baudrate)
{
esp8266_handle.Instance = USART2; /* USART1 */
esp8266_handle.Init.Baudrate = baudrate; /*波特率*/
esp8266_handle.Init.WordLength= UART_WORDLENGTH_8B;/*字长为8位的数据格式传输*/
esp8266_handle.Init.StopBits = UART_STOPBITS_1; /*一个停止位*/
esp8266_handle.Init.Parity = UART_PARITY_NONE; /*无奇偶校验位*/
esp8266_handle.Init.HwFlowCtl = UART_HWCONTRL_NONE;/*无硬件流控制*/
esp8266_handle.Init.Mode = UART_MODE_TX_RX; /*收发模式*/
HAL_UART_Init(esp8266_handle);
}

清除接收缓存

void esp8266_rx_clear(void)
{
memset(esp8266_rx_buf,0,sizeof(esp8266_rx_buf));
esp8266_cnt = 0;
}

中断服务函数

void USART2_IRQHandler(void)
{
uint8_t receive_data = 0;
/* 获取接收RXNE标志位是否被置位 */
if(__HAL_UART_GET_FLAG(&esp8266_handle,UART_FLAG_RXNE) !=RESET)
{
/* 则将接收计数器清零 */
if(esp8266_cnt >=sizeof(esp8266_rx_buf))
esp8266_cnt = 0;
/* 接收一个字符 */
HAL_UART_Receive(&esp8266_handle,&receive_data, 1,1000);
/* 将接收到的字符保存在接收缓冲区 */
esp8266_rx_buf[esp8266_cnt++] = receive_data;
}
/* 获取接收空闲中断标志位是否被置位 */
if(__HAL_UART_GET_FLAG(&esp8266_handle,UART_FLAG_IDLE) != RESET)
{
/* 将接收到的数据打印出来 */
printf("recv: %s\\r\\n", esp8266_rx_buf);
esp8266_rx_clear(); /* 清除UART总线空闲中断 */
__HAL_UART_CLEAR_IDLEFLAG(&esp8266_handle)
}
}

接收等待

uint8_t esp8266_wait_receive(void)
{
if(esp8266_cnt == 0)
return ESP8266_ERROR;
if(esp8266_cnt == esp8266_cntPre)
{
esp8266_cnt = 0;
return ESP8266_EOK;
}
esp8266_cntPre = esp8266_cnt;
return ESP8266_ERROR;
}

发送命令与期待回复函数

uint8_t esp8266_send_command(char *cmd,cahr *res)
{
uint8_t timeout_out = 250;

esp8266_rx_clear();//防止缓冲区内的数据影响
HAL__UART_Tramsmit(&esp8266_handle,(uint8_t *)cmd,strlen(cmd),100);

while(timeout_out–)//不停的等待
{
if(esp8266_wait_receive() == ESP8266_EOK)
{
if(strstr(const char *)esp8266_rx_buf, res) != NULL)//判断是否又有期待的字符串
return ESP8266_EOK
}
return ESP8266_ERROR;
}
}

接收数据

void esp8266_receiv_data(void)
{
if(esp8266_wait_receive() = ESP8266_EOK)
{
printf("esp8266 recv: %s\\r\\n",esp8266_rx_buf);
esp8266_rx_clear();
}
}

发送不定长数据

void esp8266_send_data(char *fmt, …)
{
va_list ap;
uint16_len;

va_start(ap,fmt);
vsprintf((char *)esp8266_tx_buf,fmt,ap);
va_end(ap);

len = strlen((const char*)esp8266_tx_buf);
HAL__UART_Transmit(&esp8266_handle,esp8266_tx_buf,len,100);// 发送
}

at测试指令

uint8_t esp8266_at_test(void)
{
return esp8266_send_command("AT\\r\\n", "OK");//记得加回车
}

模式设置函数封装

uint8_t esp8266_set_mode(uint8_t mode)
{
switch(mode)
{
case ESP8266_STA_MODE:
return esp8266_send_command("AT+CWMODE=1\\r\\n");
case ESP8266_AP_MODE:
return esp8266_send_command("AT+CWMODE=2\\r\\n");
case ESP8266_STA_AP_MODE:
return esp8266_send_command("AT+CWMODE=3\\r\\n");
default:
return esp8266_EINVL;
}
}

加入服务器输入账号密码

uint8_t esp8266_join_ap(char *ssid,char *pwd)
{
char cmd[64];
sprintf(cmd, "AT+CWJAP=\\"%s\\",\\"%s\\"\\r\\n",ssid,pwd);//作为模式传输进入
return esp8266_send_command(cmd."OK");
}

设置单路连接的esp8266连接模式

/*设置单路连接的模式(透传只能用此模式)*/
uint8_t esp8266_connect_mode(uint8_t mode)
{
char cmd[64];
sprintf(cmd,"AT+CIPMUX=%d\\r\\n",mode);
return esp8266_send_command(cmd,"OK");//发送cmd指令期待回复OK
}

连接tcp服务器

uint8_t esp8266_connect_tcp_sever(char *server_ip,char *server port)
{
char cmd[64];
sprintf(cmd,"AT+CIPSTART=\\"TCP\\",\\"%s\\",%s\\r\\n",server_ip,server_port);
return esp8266_send_command,"CONNECT");
}

进入透传模式

uint8_t esp8266_enter_unvarnished(void)//进入透传模式
{
uint8_t ret;

ret = esp8266_send_command("AT+CIPMODE=1\\r\\n","OK");
ret += esp8266_send_command("AT+CIPSEND\\r\\n",">");//调用指令函数
if(ret == ESP8266_EOK)
return ESP8266_EOK;
else
return ESP8266_ERROR;
}

esp8266初始化

uint8_t esp8266_init(uint32_t baudrate)
{
printf("esp8266初始化开始…\\r\\n");
esp8266_init_uart(baudrate);

printf("1. 测试esp8266是否存在\\r\\n")
while(esp8266_at_test())
delay_ms(500);

printf("2. 设置工作模式为STA…\\r\\n");
while(esp8266_set_mode(ESP8266_STA_MODE)
delay_ms(500);

printf("3. 设置单路链接模式\\r\\n");
while(esp8266_connect_mode(ESP8266_SINGLE_CONNECTION))
delay_ms(500);

printf("4. 连接wifi,SSID: %s ,PWD:%s\\r\\n",WIFI_SSID,WIFI_PWD);
while(esp8266_join_ap(WIFI_SSID,WIFI,PWD))
delay_ms(1500);//时间长一些

printf("6. 进入透传模式…\\r\\n");
while(esp8266_enter_unvarnished())
delay_ms(500);

print("esp8266已经连接上tcp服务器并进入透传模式")
}

测试函数

void esp8266_test(void)
{
esp8266_send_data("this is from esp8266\\r\\n");
esp8266_receiv_data();
}

main函数

#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "esp8266.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init();/* LED初始化 */

uart1_init(115200);
esp8266_init(115200);
printf("helloworld!\\r\\n");
while(1)
{
esp8266_test();
delay_ms(500);
}
}

2. ESP8266作为服务器

USB转TTL插入电脑,TX–RX RX-TX VCC-3.3V GND-GND

查询IP地址:AT+CIFSR

//1 配置成AP模式

AT+CWMODE=2

Response :OK

//2 使能多链接

AT+CIPMUX=1 Response :OK

//3 建立TCPServer

AT+CIPSERVER=1 // default port = 333 Response :OK

//4 发送数据

AT+CIPSEND=0,4      // 发送4个字节在连接0通道上 >abcd//输入数据,

Response :SEND OK //不带回车

//5 接收数据

+IPD, 0, n: xxxxxxxxxx //+IPD是固定字符串 0是通道,n是数据长度,xxx是数据

//断开连接

AT+CIPCLOSE=0

Response :0, CLOSED OK

 头文件

#include "sys.h"
#include "esp8266.h"
#include "string.h"
#include "delay.h"
#include "stdarg.h"

uint8_t esp8266_tx_buf[ESP8266_TX_BUF_SIZE];
uint8_t esp8266_rx_buf[ESP8266_RX_BUF_SIZE];

uint16_t esp8266_cnt = 0 ,esp8266_cntPre = 0; /* esp8266接收缓冲区 */

UART_HandleTypeDef esp8266_handle; /* esp8266句柄 */

esp8266串口初始化配置

void esp8266_uart_init(uint32_t baudrate)//正常会有启动的流程只是作为一个串口的初始化
{
/*esp8266 初始化设置*/
esp8266_handle.Instance = USART2; /* USART1 */
esp8266_handle.Init.BaudRate = baudrate; /* 波特率 */
esp8266_handle.Init.WordLength = UART_WORDLENGTH_8B; /* 字长为8位数据格式*/
esp8266_handle.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
esp8266_handle.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
esp8266_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
esp8266_handle.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&esp8266_handle); /*会使能esp8266 */
}

接收缓冲区配置

void esp8266_rx_clear(void)
{
memset(esp8266_rx_buf, 0, sizeof(esp8266_rx_buf)); /* 清空接收缓冲区 */
esp8266_cnt = 0; /* 接收计数器清零 */
}

中断服务函数

void USART2_IRQHandler(void)
{
uint8_t receive_data = 0;
if(__HAL_UART_GET_FLAG(&esp8266_handle, UART_FLAG_RXNE) != RESET){/* 获取接收RXNE标志位是否被置位 */
if(esp8266_cnt >= sizeof(esp8266_rx_buf)) /* 如果接收的字符数大于接收缓冲区大小, */
esp8266_cnt = 0; /* 则将接收计数器清零 */
HAL_UART_Receive(&esp8266_handle, &receive_data, 1, 1000); /* 接收一个字符 */
esp8266_rx_buf[esp8266_cnt++] = receive_data; /* 将接收到的字符保存在接收缓冲区 */
}

if (__HAL_UART_GET_FLAG(&esp8266_handle, UART_FLAG_IDLE) != RESET) /* 获取接收空闲中断标志位是否被置位 */
{
printf("recv: %s\\r\\n", esp8266_rx_buf); /* 将接收到的数据打印出来 */
esp8266_rx_clear();
__HAL_UART_CLEAR_IDLEFLAG(&esp8266_handle); /* 清除UART总线空闲中断 */
}
}

等待接收函数

uint8_t esp8266_wait_receive(void)
{
if(esp8266_cnt == 0)
return ESP8266_ERROR;
if(esp8266_cnt == esp8266_cntPre)
{
esp8266_cnt = 0;
return ESP8266_EOK;
}
esp8266_cntPre = esp8266_cnt;
return ESP8266_ERROR;
}

发送指令并期待返回值

uint8_t esp8266_send_command(char *cmd,char *res)//发送一个指令去 在指定时间内返回回来 否则没有接收到一个返回值
{
uint8_t timeout_out = 250;

esp8266_rx_clear(); //防止忍心内的数据影响
HAL_UART_Transmit(&esp8266_handle,(uint8_t *)cmd,strlen(cmd),100);//发送命令 cmd在这里是一个uint8_t的数据 长度 阻塞的值
//等待
while(timeout_out–)//不停的等待
{
if(esp8266_wait_receive() == ESP8266_EOK)
{
if(strstr((const char*)esp8266_rx_buf, res) != NULL)//判断是否又有期待的字符串
return ESP8266_EOK;
}
delay_ms(10);
}
return ESP8266_ERROR;//否则接收错误

}

接收数据

//接收的函数
void esp8266_receiv_data(void)
{
if(esp8266_wait_receive() == ESP8266_EOK)
{
printf("esp8266 recv: %s\\r\\n", esp8266_rx_buf);
esp8266_rx_clear();
}
}

发送不定长数据

//发送的函数 不定长数据 参数不固定
void esp8266_send_data(char *fmt, …)
{
va_list ap;
uint16_t len;

va_start(ap,fmt);
vsprintf((char *)esp8266_tx_buf,fmt, ap);
va_end(ap);

len = strlen((const char*)esp8266_tx_buf);
HAL_UART_Transmit(&esp8266_handle, esp8266_tx_buf, len,100);//发送
}

设置a模块是否存在测试

uint8_t esp8266_at_test(void)
{
return esp8266_send_command("AT\\r\\n", "OK");//记得加回车换行才能作为指令发送期待返回值为OK 直接作为返回值发送

}

设置模式

uint8_t esp8266_set_mode(uint8_t mode)//s四个函数
{
switch(mode)
{
case ESP8266_STA_MODE:
return esp8266_send_command("AT+CWMODE=1\\r\\n","OK");

case ESP8266_AP_MODE:
return esp8266_send_command("AT+CWMODE=2\\r\\n","OK");

case ESP8266_STA_AP_MODE:
return esp8266_send_command("AT+CWMODE=3\\r\\n","OK");

default:
return ESP8266_EINVAL;//如果指令不存在
}
}

加入AP

uint8_t esp8266_join_ap(char *ssid,char *pwd)//账号密码
{
char cmd[64];
sprintf(cmd, "AT+CWJAP=\\"%s\\",\\"%s\\"\\r\\n",ssid,pwd);//\\"HUAWEIAP-1\\",=\\"%s\\ 就指令带引号直接写不行,我们需要如此就不会将“”认为是配对的
return esp8266_send_command(cmd,"WIFI GOT IP");;//调用指令函数
}

连接模式

uint8_t esp8266_connect_mode(uint8_t mode)//设置单路连接的模式(透传只能用此模式)
{
char cmd[64];
sprintf(cmd, "AT+CIPMUX=%d\\r\\n",mode);//作为模式传输进入
return esp8266_send_command(cmd,"OK");;//调用指令函数
}
//连接TCP服务器

esp8266_连接模式

uint8_t esp8266_connect_mode(uint8_t mode)//设置单路连接的模式(透传只能用此模式)
{
char cmd[64];
sprintf(cmd, "AT+CIPMUX=%d\\r\\n",mode);//作为模式传输进入
return esp8266_send_command(cmd,"OK");;//调用指令函数
}

 esp8266连接tpc服务器ip和端口

uint8_t esp8266_connect_tcp_server(char *server_ip,char*server_port)
{
char cmd[64];
sprintf(cmd, "AT+CIPSTART=\\"TCP\\",\\"%s\\",%s\\r\\n",server_ip,server_port);//作为模式传输进入
return esp8266_send_command(cmd,"CONNECT");;//调用指令函数
}

进入透传模式

uint8_t esp8266_enter_unvarnished(void)//发送的模式
{
uint8_t ret;//取巧的方式定义一个返回值
//两次返回值都等于0,如果有一个不为0就为不为零的情况
ret = esp8266_send_command("AT+CIPMODE=1\\r\\n","OK");;//调用指令函数
ret += esp8266_send_command("AT+CIPSEND\\r\\n",">");;//调用指令函数
if(ret == ESP8266_EOK)
return ESP8266_EOK;
else
return ESP8266_ERROR;
}

建立tcp服务器

uint8_t esp8266_build_tcp_server(void)
{
return esp8266_send_command("AT+CIPSERVER=1\\r\\n","OK");//发送AT+CIPSEVER=1,期待回复OK
}

初始化esp8266

void esp8266_init(uint32_t baudrate)//所以增加新添加一个
{
printf("esp8266初始化开始…\\r\\n");
esp8266_uart_init(baudrate);

printf("1. 测试esp8266是否存在\\r\\n");
while(esp8266_at_test())//esp8266_at_test();也是可以的不过一直不成功那就一直等待更为保险
delay_ms(500);

printf("2. 设置工作模式为AP…\\r\\n");
while(esp8266_set_mode(ESP8266_AP_MODE))
delay_ms(500);

printf("3. 设置多路链接模式\\r\\n");
while(esp8266_connect_mode(ESP8266_MULTI_CONNECTION))
delay_ms(500);
printf("4. 建立TCP服务器…\\r\\n");
while(esp8266_build_tcp_server())
delay_ms(500);

printf("esp8266初始化完成…\\r\\n");

//esp8266的其他初始化
}

esp8266初始化测试

//测试函数
void esp8266_test(void)
{
esp8266_send_data("this is from esp8266\\r\\n");
esp8266_receiv_data();
}

 

 

 

赞(0)
未经允许不得转载:网硕互联帮助中心 » stm32实现esp8266连接到TCP服务器(二)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!