STM32使用ATK-ESP8266 WIFI模块与服务器通信

目录

一、简单了解

1、模块简介

2、AT指令配置

AP模式

 STA模式

AP+STA模式 

 二、上手测试

1、模块连接

2、编写代码

usart2.h

usart2.c

wifi.h

wifi.c

main.c


一、简单了解

1、模块简介

ATK-ESP8266是ALIENTEK推出的一款高性能的UART-WiFi(串口-无线)模块,ATK-ESP8266板载正点原子团队自主开发的ATK-ESP-01模块。

        ATK-ESP8266模块采用串(LVTTL)与MCU(或其他串口设备)通信,内置TCP/IP协议栈,能够实现串口与WIFI之间的转换。 通过ATK-ESP8266模块,传统的串口设备只是需要简单的串口配置,即可通过网络(WIFI)传输自己的数据。

ATK-ESP8266模块支持LVTTL串口,兼容3.3V和5V单片机系统,可以很方便的与你的产品进行连接。模块支持串口转WIFI STA、串口转AP和WIFI STA+WIFI AP的模式,从而快速构建串口-WIFI数据传输方案,方便你的设备使用互联网传输数据。 ATK-ESP8266模块非常小巧(29mm*19mm),模块通过6个2.54mm间距的排针与外部连接,模块外观如图所示:

各引脚描述如下表:

 ATK-ESP8266 WIFI模块共有3个模式:

        串口无线AP(COM-WIFI AP)

        串口无线STA(COM-WIFI STA)

        串口无线AP+STA(COM-WIFI AP+STA)

        其中,每个模式又包含TCP服务器、TCP客户端和UDP这3个子模式(每个模式的功能在后文会详细介绍)。模块配置可以通过串口配置,这里我们通过开发板串口配置,并实现通信。

2、AT指令配置

(该部分较为繁琐,简单使用的话稍微了解即可)

AP模式

        串口无线WIFI(COM-WIFI AP)模式,模块作为无线WIFI热点,允许其他WIFI设备连接到本模块,实现串口与其他设备之间的无线(WIFI)数据转换互传。该模式下,根据应用场景的不同,可以设置3个子模式:TCP服务器、TCP客户端,UDP。

配置准备:1,模块处于默认设置(即出厂设置);2,准备一个带WIFI功能的设备,如智能手机、笔记本电脑等。

  • TCP服务器配置:

  • TCP客户端配置:

  • UDP配置:

 STA模式

        串口无线STA(COM-WIFI STA)模式,模块作为无线WIFI STA,用于连接到无线网络,实现串口与其他设备之间的无线(WIFI)数据转换互传。该模式下,根据应用场景的不同,可以设置3个子模式:TCP服务器、TCP客户端,UDP。

配置准备:1,模块处于默认设置(即出厂设置);2,准备一个无线路由器,且路由器开启DHCP服务。

  • TCP服务器配置:

  • TCP客户端配置:

  • UDP配置:

AP+STA模式 

        串口无线AP+STA(COM-WIFI AP+STA)模式,模块既作无线WIFI AP,又作无线STA,其他WIFI设备可以连接到该模块,模块也可以连接到其他无线网络,实现串口与其他设备之间的无线(WIFI)数据转换互传。该模式下,根据应用场景的不同,可以设置9个子模式:(TCP服务器、TCP客户端,UDP)||(TCP服务器、TCP客户端,UDP)。

配置准备:1,模块处于默认设置(即出厂设置);2,准备一个带WIFI功能的设备,如智能手机、PAD、笔记本电脑等;3,准备一个无线路由器,且路由器开启DHCP服务。

下面仅介绍3种模式。AP下作服务器,STA的三种模式。 

  • AP作TCP服务器,STA做TCP服务器的配置:

  • AP作TCP服务器,STA作TCP客户端的配置:

 

  • AP作TCP服务器,STA作UDP的配置:

 二、上手测试

1、模块连接

        为方便测试,以下部分仅使用一个WIFI模块,配置完成后与上位机软件配置的服务器进行简单通信。

连接时通过串口连接:

 

本文使用正点原子战舰开发板的串口2进行测试。

上位机软件选择的是正点原子官方提供的网络调试助手,通过调整右方的选项即可配置相应的模式,这里选择:

TCP Server ,地址需查看本机IP,端口号8087(自选)

 上位机配置完成后,开始编写代码并测试。

2、编写代码

(该部分代码借鉴了正点原子官方提供的实例代码,但由于其示例代码包含很多显示屏和其他外设代码文件,不易于直接搬运过来直接使用,所以进行了适当的删减和修改,使更容易直接上手使用。)

注意:

        该WIFI模块与LORA模块一样,每次上电后模块的配置会恢复默认,所以编写配置相关的代码在每次上电后都配置一遍,才能进行连接与通信。

usart2.h

#ifndef __USART2_H
#define __USART2_H	 
#include "sys.h"  

#define USART2_MAX_RECV_LEN		600					//最大接收缓存字节数
#define USART2_MAX_SEND_LEN		600					//最大发送缓存字节数
#define USART2_RX_EN 			1					//0,不接收;1,接收.

extern u8  USART2_RX_BUF[USART2_MAX_RECV_LEN]; 		//接收缓冲,最大USART3_MAX_RECV_LEN字节
extern u8  USART2_TX_BUF[USART2_MAX_SEND_LEN]; 		//发送缓冲,最大USART3_MAX_SEND_LEN字节
extern vu16 USART2_RX_STA;   						//接收数据状态

void usart2_Init(u32 bound);				//串口2初始化 
void USART2_Printf(char* fmt,...);

#endif

usart2.c


#include "delay.h"
#include "usart2.h"
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
#include "timer.h"

/*接收缓冲区,最大USART2_MAX_RECV_LEN个字节*/
u8 USART2_RX_BUF[USART2_MAX_RECV_LEN];

/*发送缓冲区,最大USART2_MAX_SEND_LEN个字节*/
u8 USART2_TX_BUF[USART2_MAX_SEND_LEN];


vu16 USART2_RX_STA=0;

/*串口3中断服务函数*/
void USART2_IRQHandler(void)
{
	u8 res;
	if( USART_GetITStatus(USART2, USART_IT_RXNE) != RESET ) //接收到数据
	{
		res =USART_ReceiveData(USART2);
		if((USART2_RX_STA&(1<<15))==0)                      //接收完的一批数据,还没有被处理,则不再接收其他数据
		{
            if(USART2_RX_STA<USART2_MAX_RECV_LEN)	        //还可以接收数据
			{
				TIM_SetCounter(TIM6,0);                     //计数器清空
				if(USART2_RX_STA==0) 				        //使能定时器7的中断
				{
					TIM_Cmd(TIM6,ENABLE);                   //使能定时器7
				}
				USART2_RX_BUF[USART2_RX_STA++]=res;	        //记录接收到的值
			}
			else
			{
				USART2_RX_STA|=1<<15;				        //强制标记接收完成
			} 
		}
	}  				 											 
}   

/**
 *  @函数作用:初始化USART2
 *  @函数参数:【bound】波特率
 */	
void usart2_Init(u32 bound)
{
    //创建结构体变量
	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
    //使能USART2、GPIOB端口时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
    //复位USART2
 	USART_DeInit(USART2);
	//初始化USART2_TX的GPIO端口
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                      //端口:PA_2
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;               //速度:50MHz
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         	    //模式:复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);                          //根据设定参数初始化USART2_TX
    //初始化USART2_RX的GPIO端口
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                      //端口:PA_3
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;           //模式:浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);                          //根据设定参数初始化USART2_RX
	//初始化USART3 NVIC中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;         //抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		        //子优先级2
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			        //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	                                //根据指定的参数初始化NVIC寄存器
    //初始化USART2
	USART_InitStructure.USART_BaudRate = bound;                     //串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;     //字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;          //一位停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;             //无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

	USART_Init(USART2, &USART_InitStructure); 		                //初始化串口3
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);                  //开启串口3接收中断
	USART_Cmd(USART2, ENABLE);                    	                //使能串口3
	//初始化定时器
	TIM6_Init(499,7199);		                                    //初始化通用定时器7
	USART2_RX_STA=0;			                                    //清零串口3接收状态标志
	TIM_Cmd(TIM6,DISABLE);		                                    //关闭定时器7
}

/**
 *  @函数作用:给USART2发送消息
 *  @函数参数:需发送的数据(一次发送数据不超过USART2_MAX_SEND_LEN字节)
 */
void USART2_Printf(char* fmt,...)
{
	u16 buf_len,i;
	va_list ap; 
	va_start(ap,fmt);
	vsprintf((char*)USART2_TX_BUF,fmt,ap);
	va_end(ap);
	buf_len = strlen( (const char*) USART2_TX_BUF );		        //此次发送数据的长度
	for( i = 0 ; i < buf_len ; i++ )							    //循环发送数据
	{
	  	while( USART_GetFlagStatus(USART2,USART_FLAG_TC) == RESET );//循环发送,直到发送完毕
		USART_SendData(USART2, USART2_TX_BUF[i]);
	}
}


wifi.h

#ifndef __WIFI_H__
#define __WIFI_H__

#include "sys.h"

#define WIFI_STA_SSID       "226"
#define WIFI_STA_PASSWORD   "226226226"
#define WIFI_SERVER_IP      "192.168.124.31"
#define WIFI_SERVER_PORT    "8087"

//用户配置参数
//extern const u8* portnum;			//连接端口
//extern u8* kbd_fn_tbl[2];

//extern const u8* wifiap_ssid;		//WIFI AP SSID
//extern const u8* wifiap_encryption;	//WIFI AP 加密方式
//extern const u8* wifiap_password; 	//WIFI AP 密码

u8* atk_8266_check_cmd(u8 *str);
void atk_8266_response(u8 mode);
u8 atk_8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime);
u8 atk_8266_quit_trans(void);
u8 atk_8266_consta_check(void);
void atk_8266_get_wanip(u8* ipbuf);


void Reconnect_Wifi(void);
void WIFI_Send_Data(u8 *data);
u8* WIFI_Rece_Data(void);
void WIFI_STA_Init(void);
void WIFI_AP_Init(void);
void WIFI_Connect(void);
	


#endif

使用时需要修改上述WIFI名、密码(需要上位机连上同一个WIFI)、IP地址、端口号的宏定义 。

wifi.c

#include "wifi.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"	 	 	 	 	 
#include "lcd.h"
#include "string.h"
#include "usart2.h"


//ATK-ESP8266发送命令后,检测接收到的应答
//str:期待的应答结果
//返回值:0,没有得到期待的应答结果
//    其他,期待应答结果的位置(str的位置)
u8* atk_8266_check_cmd(u8 *str)
{
	char *strx=0;
	if(USART2_RX_STA&0X8000)		//接收到一次数据了
	{ 
		USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;//添加结束符
		strx=strstr((const char*)USART2_RX_BUF,(const char*)str);
	} 
	return (u8*)strx;
}

//usmart支持部分
//将收到的AT指令应答数据返回给电脑串口
//mode:0,不清零USART2_RX_STA;
//     1,清零USART2_RX_STA;
void atk_8266_response(u8 mode)
{
	if(USART2_RX_STA&0X8000)		//接收到一次数据了
	{ 
		USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;//添加结束符
		printf("%s",USART2_RX_BUF);	//发送到串口
		if(mode)USART2_RX_STA=0;
	}
}



//向ATK-ESP8266发送命令
//cmd:发送的命令字符串
//ack:期待的应答结果,如果为空,则表示不需要等待应答
//waittime:等待时间(单位:10ms)
//返回值:0,发送成功(得到了期待的应答结果)
//       1,发送失败
u8 atk_8266_send_cmd(u8 *cmd,u8 *ack,u16 waittime)
{
	u8 ret=0;
	USART2_RX_STA=0;
	USART2_Printf("%s\r\n",cmd);	//发送命令
    if( ack && waittime )		//需要等待应答
	{
		while(--waittime)	//等待倒计时
		{
			delay_ms(10);
			if( USART2_RX_STA & 0X8000 )//接收到期待的应答结果
			{
				if( atk_8266_check_cmd(ack) )
				{
					printf("ack:%s\r\n",(u8*)ack);
					break;//得到有效数据 
				}
                USART2_RX_STA=0;
			} 
		}
		if( waittime == 0 ) ret=1; 
	}
	return ret;
}

//ATK-ESP8266退出透传模式
//返回值:0,退出成功;
//       1,退出失败
u8 atk_8266_quit_trans(void)
{
	while((USART2->SR&0X40)==0);	//等待发送空
	USART2->DR='+';      
	delay_ms(15);					//大于串口组帧时间(10ms)
	while((USART2->SR&0X40)==0);	//等待发送空
	USART2->DR='+';
	delay_ms(15);					//大于串口组帧时间(10ms)
	while((USART2->SR&0X40)==0);	//等待发送空
	USART2->DR='+';      
	delay_ms(500);					//等待500ms
	return atk_8266_send_cmd("AT","OK",20);//退出透传判断
}

//获取ATK-ESP8266模块的连接状态
//返回值:4,未连接;3,连接成功
u8 atk_8266_consta_check(void)
{
	u8 *p;
	u8 res;
    USART2_RX_STA=0;
    if(atk_8266_quit_trans()) return 0;			//退出透传

	atk_8266_send_cmd("AT+CIPSTATUS",":",50);	//发送AT+CIPSTATUS指令,查询连接状态

	p=atk_8266_check_cmd("STATUS:"); 
	res=p[7];									//得到连接状态
    atk_8266_send_cmd((u8 *)"AT+CIPMODE=1",(u8 *)"OK",20);      //开始透传模式
    atk_8266_send_cmd((u8 *)"AT+CIPSEND",(u8 *)"OK",20);        //开始透传
    USART2_RX_STA=0;
	return res;
}


//获取Client ip地址
//ipbuf:ip地址输出缓存区
void atk_8266_get_wanip(u8* ipbuf)
{
	u8 *p,*p1;
    if(atk_8266_send_cmd("AT+CIFSR","OK",50))//获取WAN IP地址失败
    {
        ipbuf[0]=0;
        return;
    }
    p=atk_8266_check_cmd("\"");
    p1=(u8*)strstr((const char*)(p+1),"\"");
    *p1=0;
    sprintf((char*)ipbuf,"%s",p+1);
}

//向ATK-ESP8266发送指定数据
void WIFI_Send_Data(u8 *data)
{
	USART2_RX_STA=0;
	USART2_Printf((char *)data);	//发送命令
}

u8* WIFI_Rece_Data(void)
{
	u16 len=0;
	if( USART2_RX_STA & 0X8000 )
	{
		memset((char*)USART2_RX_BUF,0x00,len);//串口接收缓冲区清0
		len = USART2_RX_STA & 0X7FFF;
		USART2_RX_BUF[len]=0;//添加结束符
		USART2_RX_STA=0;
	}
	return USART2_RX_BUF;
}

void Reconnect_Wifi(void)
{
    char p[100]={0};
    USART2_RX_STA=0;
    //退出透传
    if(atk_8266_quit_trans()) return;
    //关闭透传模式
    //连接TCP服务器
	sprintf(p,"AT+CIPSTART=\"TCP\",\"%s\",%s",WIFI_SERVER_IP,WIFI_SERVER_PORT);
    if(atk_8266_send_cmd((u8 *)p,(u8 *)"OK",50))   return;
    //设置透传模式
    atk_8266_send_cmd((u8 *)"AT+CIPMODE=1",(u8 *)"OK",50);
    //开始透传
    atk_8266_send_cmd((u8 *)"AT+CIPSEND",(u8 *)"OK",20);
    USART2_RX_STA=0;
}

void WIFI_STA_Init(void)
{
    char p[100]={0};
    
    //检查WIFI模块是否在线
	while(atk_8266_send_cmd((u8 *)"AT",(u8 *)"OK",20))
	{
        //退出透传
		atk_8266_quit_trans();
        //关闭透传模式
		atk_8266_send_cmd((u8 *)"AT+CIPMODE=0",(u8 *)"OK",200);
		delay_ms(800);

	}

    //关闭回显
    while(atk_8266_send_cmd((u8 *)"ATE0",(u8 *)"OK",20));

    //检查ATK-ESP8266模块发送过来的数据,及时上传给电脑
    atk_8266_response(1);
    
    //设置WIFI STA模式
	atk_8266_send_cmd((u8 *)"AT+CWMODE=1",(u8 *)"OK",50);
    //DHCP服务器关闭(仅AP模式有效)
	atk_8266_send_cmd((u8 *)"AT+RST",(u8 *)"OK",20);
	delay_ms(1000);         //延时2S等待重启成功
	delay_ms(1000);
	
    //设置无线热点参数:[ssid] [密码]
	sprintf(p,"AT+CWJAP=\"%s\",\"%s\"",WIFI_STA_SSID,WIFI_STA_PASSWORD);
	while(atk_8266_send_cmd((u8 *)p,"WIFI GOT IP",300));

    //设置TCP连接为单连接 [0]单连接 [1]多连接
    atk_8266_send_cmd((u8 *)"AT+CIPMUX=0",(u8 *)"OK",20);
	delay_ms(1000);

    //连接TCP服务器
	sprintf(p,"AT+CIPSTART=\"TCP\",\"%s\",%s",WIFI_SERVER_IP,WIFI_SERVER_PORT);
    while(atk_8266_send_cmd((u8 *)p,(u8 *)"OK",200));
    
    //设置透传模式
    atk_8266_send_cmd((u8 *)"AT+CIPMODE=1",(u8 *)"OK",200);
    //开始透传
    atk_8266_send_cmd((u8 *)"AT+CIPSEND",(u8 *)"OK",20);

    USART2_RX_STA=0;
	
	
}

//ATK-ESP8266模块测试主函数
void WIFI_AP_Init(void)
{
    u8 str_ip[16]={0}; 	//IP缓存
    
	while(atk_8266_send_cmd((u8 *)"AT",(u8 *)"OK",20))//检查WIFI模块是否在线
	{
		atk_8266_quit_trans();//退出透传
		atk_8266_send_cmd((u8 *)"AT+CIPMODE=0",(u8 *)"OK",200);  //关闭透传模式  
		delay_ms(800);
	}
    while(atk_8266_send_cmd((u8 *)"ATE0",(u8 *)"OK",20));//关闭回显
    atk_8266_response(1); //检查ATK-ESP8266模块发送过来的数据,及时上传给电脑  
	

    atk_8266_send_cmd((u8 *)"AT+CIPMUX=0",(u8 *)"OK",20);   //0:单连接,1:多连接

    while(atk_8266_send_cmd((u8 *)"AT+CIPSTART=\"TCP\",\"192.168.4.3\",8087",(u8 *)"OK",200))
    {
   
    }
    atk_8266_get_wanip(str_ip);//服务器模式,获取WAN IP

    LED1 = 0;
    delay_ms(5000);
    atk_8266_send_cmd((u8 *)"AT+CIPMODE=1",(u8 *)"OK",200);     //开始透传模式
    atk_8266_send_cmd((u8 *)"AT+CIPSEND",(u8 *)"OK",20);        //开始透传
    USART2_Printf("%s","STM32");

    USART2_RX_STA=0;
}

void WIFI_Connect(void)
{
	u8 flag = atk_8266_consta_check();//得到连接状态,  3:成功  4:失败
	
	while(flag == 4)
	{
		flag = atk_8266_consta_check();
		Reconnect_Wifi();
	}
}


main.c

测试时,将WIFI模块配置为STATCP客户端模式,初始化并连接(需要打开上位机软件串口):

usart2_Init(115200);
WIFI_STA_Init(); //WIFI初始化
WIFI_Connect();

然后就可以发送需要发送的数据:

WIFI_Send_Data(wbuf);//通过WIFI发送到服务器

通过合理的逻辑编写代码即可实现同一个局域网内,STM32通过WIFI模块与服务器进行通信。

  • 13
    点赞
  • 150
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十九-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值