usb转ttl适配器、esp8266-01s、单片机C51、电脑、安信可串口调试助手、STC-ISP、TCP网络调试助手之间的关系。
用wifi模块esp8266-01s固件完成以下几种操作时,用到的东西和它们之间的关系,每一步形成的意义如下。
AT指令
AT指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)(电脑、手机平板等)向终端适配器(Terminal Adapter,TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)(这里用串口通信适配器usb转ttl适配器)发送的。
其对所传输的数据包大小有定义:即对于AT指令的发送,除AT两个字符外,最多可以接收1056个 字符的长度(包括最后的空字符)。
每个AT命令行中只能包含一条AT指令;对于由终端设备主动向PC端报告的URC指示或者response 响应,也要求一行最多有一个,不允许上报的一行中有多条指示或者响应。AT指令以回车作为结 尾,响应或上报以回车换行为结尾。
一、初始的AT指令的发送-手动
1.1 目的
在电脑上使用串口调试助手,输入AT指令,使esp8266-01s可以联网
1.2 使用的东西
电脑、安信可串口调试助手、usb转ttl适配器、esp8266-01s、TCP网络调试助手
1.3 接线及预备
usb转ttl适配器接电脑,电脑打开安信可串口调试助手,打开TCP网络调试助手,esp8266-01s接usb转ttl适配器
1.4 代码执行
- AT+RST开机信息,以收到ready为准(41页)
- 上电后发送AT指令测试通信及模块功能是否正常(发送AT指令要勾选新行,发送数据不用勾选新行)
AT
OK
- 通过一下命令配置成9600波特率
AT+UART=9600,8,1,0,0
入网设置
- 设置工作模式
AT+CWMODE=3 //1. 是station(设备)模式 2.是AP(路由)模式 3.是双模
OK
- 设置工作模式
AT+CWMODE=3 //1. 是station(设备)模式 2.是AP(路由)模式 3.是双模
OK
- 以设备模式接入家中路由器配置(这是配置过一次出现的结果,第一次直接执行应该是OK)
AT+CWJAP="wifi名称","WiFi密码" //指令
WIFI CONNECTED //结果-连接断开
WIFI GOT IP //结果-wifi连接
- 查询IP地址
AT+CIFSR //指令
+CIFSR:APIP,"192.168.4.1"
+CIFSR:APMAC,"4e:75:25:0d:ae:2f"
+CIFSR:STAIP,"192.168.0.148" //这个IP地址是连接的wifi的局域地址,跟当前电脑连接的是同一个局域的WiFi
+CIFSR:STAMAC,"4c:75:25:0d:ae:2f"
OK
连接到 TCP server
- 打开网络助手,设立TCP服务器
esp模块是通过TCP协议跟电脑连接,虽然电脑上插着usb接口可以用串口通信,我们也可以通过wifi的形式,esp把数据发给路由器,路由器中转把数据给电脑,然后电脑这边设置一个服务器(网络调试助手)用于接收来自路由器传递的信息。
- 连接服务器(这里的AT+CIPSTART中的信息都是上面的配置网络适配器的信息)
AT+CIPSTART="TCP","192.168.0.113",8888 //指令,注意双引号逗号都要半角(英文)输入 CONNECT //结果:成功
OK //结果:成功
- 发送数据
在串口调试助手中发送AT指令,最终发送出来的数据在网络调试助手中可以看到。
AT+CIPSEND=4 // 设置即将发送数据的长度 (这里是4个字节)
>CLCA // 看到大于号后,输入消息,CLCA,不要带回车 (注意:在发送数据的时候,要把“发送新行”这个选项去掉)
Response :SEND OK //结果:成功
//注意,这种情况下,每次发送前都要先发送AT+CIPSEND=长度 的指令,再发数据!
透传
因为上面的方式太蠢了,使用透传,像蓝牙一样好的,直接在上述发送数据那里开始更改操纵
在透传模式下,电脑,和服务器可以双向通信,随意通信
AT+CIPMODE=1 //开启透传模式
Response :OK
AT+CIPSEND //带回车
Response: > //这个时候随意发送接收数据咯
退出透传模式
两次+++ //在透传发送数据过程中,若识别到单独的⼀包数据 “+++”,则退出透传发送
1.5 关系
usb转ttl适配器,在连接电脑之后,会出现一个串口名称,安信可串口助手的串口号选择这个适配器的串口名称,选择对应的波特率9600(后配置的)、115200(出厂设置),这样串口助手和串口适配器就连接了,这个时候的串口助手叫ttl的串口助手。
数据传出来的流程是:电脑使用串口调试助手,写入AT指令,点击发送,会把数据发送(--->)给通过连接电脑的TTL-(杜邦线)-ESP,最终传给ESP,ESP 接收到AT指令,执行AT指令,(此时的指令是连接服务器)-ESP跟路由器通信,路由器将ESP发送的"TCP","192.168.0.113",8888 信息传递给服务端,连接服务器(信息输入正确,连接成功,否则失败)--服务器连接成功,等待数据从串口发送给ESP,ESP接收到数据,将数据通过TCP协议传给服务器,所以在服务器上可以看到串口助手发送的数据。
通过串口助手完成ttl串口的信息传输。通过网络可以将电脑上的服务器与ESP进行信息传输,首先要保证电脑的服务器(网络调试助手)、esp都在同一局域网下。
二、初始的AT指令的配置-单片机来完成
2.1 目的
手动发送AT指令需要一条一条的发送,太过于蠢,使用单片机来替我们完成这个操作,所以需要写好代码之后,将代码烧写进单片机中,然后通过代码一条一条的执行,开完成AT指令初始的配置操作,并且用ESP的TX线通过TTL在串口助手中显示,代码执行的信息,如果不想看到代码执行的信息,就不用把ESP的TX线连接TTL的RX线,联回单片机可以控制灯的开关。
2.2 使用的东西
C51、ESP、TTL、网络调试助手、串口调试助手
2.3 接线及预备
ESP的3V3、RX、GND与C51相连,ESP的TX与TTL的RX相连,TTL与电脑相连,C51烧录完代码进去之后,就可以外接电源供电,串口助手和网络调试助手(TCP服务端,使用本地IP地址,端口号8880)都打开,
2.4 代码执行
烧录进C51的代码,可以通过在服务端输入信息,改变灯的亮灭。
#include "reg52.h"
#include "intrins.h"
#include "string.h"
#define SIZE 12//宏定义指令
sfr AUXR = 0X8E;
sbit D5 = P3^7;
char cmd[SIZE];//数组
//这里的\是转义(保留内容原来的意义),定义一个连接网络的数组,用于接收网络名称和密码。
//\r\n表示发送新行
code char LJWL[] = "AT+CWJAP=\"ChinaUnicom-FXL6NZ\",\"13555305181ljf\"\r\n";
code char LJFWQ[] = "AT+CIPSTART=\"TCP\",\"192.168.101.26\",8880\r\n";
char TCMS[] = "AT+CIPMODE=1\r\n";
char SJCS[] = "AT+CIPSEND\r\n"; //char类型的变量存放数据少,code char类型会比char型多
UartInit(void){
AUXR = 0X8E;
SCON = 0X50;
EA = 1;
ES = 1;
TMOD &= 0X0F;
TMOD |= 0X20;
TH1 = 0XFD;
TL1 = 0XFD;
TR1 = 1;
}
void Delay800ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 34;
j = 159;
k = 59;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void sendByte(char data_msg){
SBUF = data_msg;
while(!TI);
TI = 0;
}
void sendString(char* str){
while(*str != '\0'){
sendByte(*str);
str++;
}
}
void main()
{
D5 = 1;
UartInit();
while(1){
Delay800ms();//延时发送,因为数据传送的太快了
sendString("lijinshuang\r\n");//往缓冲区写入数据,完成数据的发送
sendString(LJWL);//数据名相当于整个字符串的地址
Delay800ms();
sendString(LJFWQ);
Delay800ms();
sendString(TCMS);
Delay800ms();
sendString(SJCS);
Delay800ms();
}
}
void Uart_Handler() interrupt 4 //中断
{
static int i=0;
if(RI){
RI=0;
cmd[i] = SBUF;
i++;
if(i == SIZE){
i=0;
}
if(strstr(cmd,"en")){//1,亮灯
D5 = 0;
i = 0;
memset(cmd,'\0',SIZE);
}
if(strstr(cmd,"se")){//0,灭灯
D5 = 1;
i = 0;
memset(cmd,'\0',SIZE);
}
}
}
1.5 关系
方式一:用电脑可以看到单片机给ESP传入的代码后 ESP的反应信息
单片机在烧录完代码之后,就可以不用插在电脑上了,用其他电源给其供电即可,在单片机给ESP传入代码信息时,可以把ESP的TX-TTL的RX中,这样可以看见传入代码信息时,ESP的反应情况是否有错误,在哪一步错了(相当于白盒测试),在网络调节助手中,可以看到当ESP成功连上网络之后,通过网络传给电脑上服务器的信息。
方式二:不需要看到ESP的反应信息时,在联网成功后,直接通过网络调试助手(服务器)控制灯的开关
当ESP网络连接成功之后,不需要在观察代码信息时,可以将ESP上的TX-单片机的RX线接上,因为这时已经完成了网络的连接,通过TX和RX两个针脚,完成对单片机的传入信息和接受信息(ESP的TX阵脚用于ESP传出信息给单片机,RX阵脚用于ESP接收来自单片机的信息),如果从一开始就把TX针脚连接到单片机的RX上,这时候看不到代码信息,相当于黑盒测试。
三、通过TCP通信点灯
3.1 使用的东西和接线
C51烧写代码,ESP连接C51,通过网络调试助手(TCP服务端,使用本地IP地址,端口号8880)是否接收到来自ESP8266的信息和C51灯光的闪烁情况.观看结果
C51的D4灯常亮表示正常接入电源,D3灯在闪烁证明在往ESP中烧写代码,当D5灯亮代表网络连接成功,D6灯亮表示连接服务器并打卡透传模式成功,D5灯闪5下,表示连接失败,重新启动,输入L1表示点亮D5,输入L0表示熄灭D5,可以通过在服务端输入信息,改变灯的亮灭。
3.2 代码
#include "reg52.h"
#include "intrins.h"
#include <string.h>
#define SIZE 12
sfr AUXR = 0x8E;
sbit D5 = P3^7;
sbit D6 = P3^6;
char buffer[SIZE];
code char LJWL[] = "AT+CWJAP=\"ChinaUnicom-FXL6NZ\",\"13555305181ljf\"\r\n";
code char LJFWQ[] = "AT+CIPSTART=\"TCP\",\"192.168.101.26\",8880\r\n";
char TCMS[] = "AT+CIPMODE=1\r\n";
char SJCS[] = "AT+CIPSEND\r\n";
char RESET[] ="AT+RST\r\n";//重启
char AT_OK_Flag = 0;//定义标志位,初始为0,成功执行置1,通过while1、0判断是否陷入循环
char AT_Connect_Net_Flag = 0;
void UartInit(void) //9600bps@11.0592MHz
{
AUXR = 0x01;
SCON = 0x50; //配置串口工作方式1,REN使能接收
TMOD &= 0x0F;
TMOD |= 0x20;//定时器1工作方式位8位自动重装
TH1 = 0xFD;
TL1 = 0xFD;//9600波特率的初值
TR1 = 1;//启动定时器
EA = 1;//开启总中断
ES = 1;//开启串口中断
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void sendByte(char data_msg)
{
SBUF = data_msg;
while(!TI);//这里的TI就是一个中断标志位。
//TI请求中断的时候为1,取反等于0,不满足while条件,跳出循环向下执行
//若TI没有被接收到中断消息值依旧0,取反变成了1,满足while条件,进入死循环,不在向下执行
TI = 0;
}
void sendString(char* str)
{
while( *str != '\0'){
sendByte(*str);
str++;
}
}
void main()
{
int mark = 0;
D5=D6 = 1;
//配置C51串口的通信方式
UartInit();
Delay1000ms();//给espwifi模块上电时间
//连接网络只执行一次,不用放在while循环里面
sendString(LJWL);//连接网络
while(!AT_Connect_Net_Flag);//判断标志位是否为0,为0证明没有正确连接网络,陷入while1循环
while(!AT_OK_Flag);
AT_OK_Flag=0;
sendString(LJFWQ);//连接服务器
while(!AT_OK_Flag);
AT_OK_Flag=0;
sendString(TCMS);//透传模式
while(!AT_OK_Flag);
AT_OK_Flag=0;
sendString(SJCS);//数据传输
while(!AT_OK_Flag);
if(AT_Connect_Net_Flag){
D5 = 0;//点亮D5,代表入网成功
}
if(AT_OK_Flag){
D6 = 0; //点亮D6,代表连接服务器并打开透传模式成功
}
while(1){
Delay1000ms();
//往发送缓冲区写入数据,就完成数据的发送
sendString("lijinshuang\r\n");
}
}
void Uart_Handler() interrupt 4 //中断处理函数
{
static int i = 0;//静态变量,被初始化一次
char tmp;//定义一个临时的字符变量,用于接收信息
if(RI)//中断处理函数中,对于接收中断的响应
{
RI = 0;//清除接收中断标志位
tmp = SBUF; //让字符变量接收寄存器传递出来的信息(它是一个字节寻址的寄存器,字节地址为99H,通常用于存储一个字符的数据大小)
//tmp只能接收一个字母,SBUF也是一个字节一个字节的输出数据和接收数据
if(tmp == 'W' || tmp == 'O' || tmp == 'L' || tmp == 'F')//首先通过串口接收一个字节的数据到变量tmp中。
//然后,使用if语句检查这个字节是否等于'W'、'O'、'L'或'F'。如果条件满足,就把它强制变成buffer数组的第一个元素
//W: WIFI GOT IP
//O : OK
//L: L0/L1
//F: FALL 报错信息,没有连接上网络
{
i = 0; //每次接收到信息都让i等于0,用于表示数组的第一位
}
buffer[i++] = tmp; //给buffer数组赋值,接下来把temp接收的数据都存到buffer数组中
//下面就通过buffer数组来解决问题
if(buffer[0] == 'W' && buffer[5] == 'G'){//代表入网成功
AT_Connect_Net_Flag=1;//标志位置1
memset(buffer,'\0',SIZE);
}
if(buffer[0] == 'O' && buffer[1] == 'K'){
AT_OK_Flag=1;
memset(buffer,'\0',SIZE);
}
if(buffer[0] == 'F' && buffer[1] == 'A'){//发生错误
for(i=0;i<5;i++){//让灯闪烁五次
D5 = 0 ;
Delay1000ms();
D5 = 1;
Delay1000ms();
}
sendString(RESET);//重启
memset(buffer,'\0',SIZE);//清空内容
}
if(buffer[0] == 'L' && buffer[1] == '1'){//L1开灯
D5 = 0;//点亮D5
memset(buffer,'\0',SIZE);//清空内容
}
if(buffer[0] == 'L'&& buffer[1] == '0'){//L0闭灯
D5 = 1;//熄灭D5
memset(buffer,'\0',SIZE);//清空内容
}
if(i==12) i=0;//判断i是否有了12个数据了,是,把i重新制0
}
if(TI);
}
四、ESP8266工作为AP路由模式并当成服务器
在前面,ESP8266的工作模式是客户端(设备模式),可以通过C51烧录的代码对esp传递信息,通过tcp传递给服务端,服务端可以通过tcp发送信息给esp,esp接收信息传递给C51,现在要把esp当作服务端,由esp发送信息给客户端,这个时候,电脑使用的网络调试助手,首先要连接esp的网络,在配置下面图中的协议类型,本地主机地址,远程主机地址。
这里的协议类型是客户端,本地主机地址是当前电脑的ipconfig(已连接esp网络时的ipconfig),远程主机地址是,通过串口助手,使用AT指令,查询当前esp作为路由器时的IP地址。
AT+CIFSR //在串口助手中查到当前ESP作为路由器时的IP地址。这里查到是“192.168.4.1”
客户端可以发送数据给服务端,服务端也可以发送数据给客户端
发送AT指令勾选新行,发送数据,不用勾选新行
记得重启AT+RES//1 配置成双模AT + CWMODE = 2Response : OK//2.查询IP地址AT+CIFSR//3 使能多链接 AT + CIPMUX = 1Response : OK//4 建立 TCPServerAT + CIPSERVER = 1 // default port = 333Response : OK//5 发送数据AT + CIPSEND = 0 , 4 // 发送 4 个字节在连接 0 通道上> abcd // 输入数据,不带回车Response : SEND OK//• 接收数据+ IPD , 0 , n : xxxxxxxxxx //+IPD 是固定字符串 0 是通道, n 是数据长度, xxx 是数据// 断开连接AT + CIPCLOSE = 0Response : 0 , CLOSED OK
单片机代码完成AT指令的输入
//ESP-01s工作在路由模式,课程查询路由器IP地址192.168.4.1,使用的服务器默认端口号333
//ESP-01s收到收到数据op/cl给上官一号,实现D6led的亮/灭
#include "reg52.h"
#include "intrins.h"
#include <string.h>
#define SIZE 12
sfr AUXR = 0x8E;
sbit D5 = P3^7;
sbit D6 = P3^6;
char buffer[SIZE];
//1 工作在路由模式
char LYMO[] = "AT+CWMODE=2\r\n";
//2 使能多链接
char DLJ[] = "AT+CIPMUX=1\r\n";
//3 建立TCPServer
char JLFW[] = "AT+CIPSERVER=1\r\n"; // default port = 333
//发送数据
char FSSJ[] = "AT+CIPSEND=0,5\r\n";
char AT_OK_Flag = 0; //OK返回值的标志位
char AT_Connect_Net_Flag = 0; //WIFI GOT IP返回值的标志位
char Client_Connect_Flag = 0;
void UartInit(void) //9600bps@11.0592MHz
{
AUXR = 0x01;
SCON = 0x50; //配置串口工作方式1,REN使能接收
TMOD &= 0xF0;
TMOD |= 0x20;//定时器1工作方式位8位自动重装
TH1 = 0xFD;
TL1 = 0xFD;//9600波特率的初值
TR1 = 1;//启动定时器
EA = 1;//开启总中断
ES = 1;//开启串口中断
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void sendByte(char data_msg)
{
SBUF = data_msg;
while(!TI);
TI = 0;
}
void sendString(char* str)
{
while( *str != '\0'){
sendByte(*str);
str++;
}
}
void main()
{
int mark = 0;
D5 = D6 = 1;//灭状态灯
//配置C51串口的通信方式
UartInit();
Delay1000ms();//给espwifi模块上电时间
sendString(LYMO);
while(!AT_OK_Flag);
AT_OK_Flag = 0;
sendString(DLJ);
while(!AT_OK_Flag);
AT_OK_Flag = 0;
sendString(JLFW);
while(!Client_Connect_Flag);
AT_OK_Flag = 0;
if(Client_Connect_Flag){
D5 = 0;//点亮D5,代表有客户端接入
D6 = 0;
}
while(1){
//4 发送数据
sendString(FSSJ);
Delay1000ms();
Delay1000ms();
sendString("Hello");
Delay1000ms();
Delay1000ms();
}
}
void Uart_Handler() interrupt 4
{
static int i = 0;//静态变量,被初始化一次
char tmp;
if(RI)//中断处理函数中,对于接收中断的响应
{
RI = 0;//清除接收中断标志位
tmp = SBUF;
if(tmp == 'W' || tmp == 'O' || tmp == 'L' || tmp == '0' || tmp ==
':'){
i = 0;
}
buffer[i++] = tmp;
//入网成功的判断依据WIFI GOT IP
if(buffer[0] == 'W' && buffer[5] == 'G'){
AT_Connect_Net_Flag = 1;
memset(buffer, '\0', SIZE);
}
//连接服务器等OK返回值指令的判断
if(buffer[0] == 'O' && buffer[1] == 'K'){
AT_OK_Flag = 1;
memset(buffer, '\0', SIZE);
}
if(buffer[0] == '0' && buffer[2] == 'C'){
Client_Connect_Flag = 1;
memset(buffer, '\0', SIZE);
}
//灯控指令
if(buffer[0] == ':' && buffer[1] == 'o' && buffer[2] == 'p'){
D5 = 0;//点亮D5
memset(buffer, '\0', SIZE);
}
if(buffer[0] == ':' && buffer[1] == 'c' && buffer[2] == 'l'){
D5 = 1;//熄灭D5
memset(buffer, '\0', SIZE);
}
if(i == 12) i = 0;
}
}