目录
一、简单了解
1、模块简介
2、AT指令配置
AP模式
STA模式
AP+STA模式
二、上手测试
1、模块连接
2、编写代码
usart2.h
usart2.c
wifi.h
wifi.c
main.c
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个子模式(每个模式的功能在后文会详细介绍)。模块配置可以通过串口配置,这里我们通过开发板串口配置,并实现通信。
(该部分较为繁琐,简单使用的话稍微了解即可)
串口无线WIFI(COM-WIFI AP)模式,模块作为无线WIFI热点,允许其他WIFI设备连接到本模块,实现串口与其他设备之间的无线(WIFI)数据转换互传。该模式下,根据应用场景的不同,可以设置3个子模式:TCP服务器、TCP客户端,UDP。
配置准备:1,模块处于默认设置(即出厂设置);2,准备一个带WIFI功能的设备,如智能手机、笔记本电脑等。
串口无线STA(COM-WIFI STA)模式,模块作为无线WIFI STA,用于连接到无线网络,实现串口与其他设备之间的无线(WIFI)数据转换互传。该模式下,根据应用场景的不同,可以设置3个子模式:TCP服务器、TCP客户端,UDP。
配置准备:1,模块处于默认设置(即出厂设置);2,准备一个无线路由器,且路由器开启DHCP服务。
串口无线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的三种模式。
为方便测试,以下部分仅使用一个WIFI模块,配置完成后与上位机软件配置的服务器进行简单通信。
连接时通过串口连接:
本文使用正点原子战舰开发板的串口2进行测试。
上位机软件选择的是正点原子官方提供的网络调试助手,通过调整右方的选项即可配置相应的模式,这里选择:
TCP Server ,地址需查看本机IP,端口号8087(自选)
上位机配置完成后,开始编写代码并测试。
(该部分代码借鉴了正点原子官方提供的实例代码,但由于其示例代码包含很多显示屏和其他外设代码文件,不易于直接搬运过来直接使用,所以进行了适当的删减和修改,使更容易直接上手使用。)
注意:
该WIFI模块与LORA模块一样,每次上电后模块的配置会恢复默认,所以编写配置相关的代码在每次上电后都配置一遍,才能进行连接与通信。
#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
#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
#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地址、端口号的宏定义 。
#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();
}
}
测试时,将WIFI模块配置为STA的TCP客户端模式,初始化并连接(需要打开上位机软件串口):
usart2_Init(115200);
WIFI_STA_Init(); //WIFI初始化
WIFI_Connect();
然后就可以发送需要发送的数据:
WIFI_Send_Data(wbuf);//通过WIFI发送到服务器
通过合理的逻辑编写代码即可实现同一个局域网内,STM32通过WIFI模块与服务器进行通信。