编辑
2021-10-01
浅尝嵌入式开发
00
请注意,本文编写于 723 天前,最后修改于 39 天前,其中某些信息可能已经过时。

目录

AT测试+服务模式配置
调整波特率,与C51匹配
MCU与ESP8266接线
程序编写
最终效果
补充:MCU如何回发数据

前段时间学习了ESP8266的AT指令集,现在通过AT指令初始化ESP8266+串口通信的方式,完成WLAN下的信息交换,比如手机、PC、其他MCU与STC89 C51的通信等等。其中踩了不少的坑,特此记录一下。ESP8266小模块系列常见的就下面几种:ESP-01S比ESP-01多了两颗小料并增强了天线的强度,其他的是一样的,完全通用!

下面是其管脚图与外形尺寸图,如果PCB背板也有图的话那么直接根据背板的上的图也是OK的:

AT测试+服务模式配置

通过USB转TTL模块把ESP8266模块和电脑连接起来 ,下面是我是使用的USB转TTL,专门用于ESP8266 WIFI模块的调试工具,购买链接 https://detail.1688.com/offer/548614288547.html:

连接好后,就准备用电脑用串口调试助手向ESP8266发送AT指令即可,调试助手可使用XCOMV2,非常好用。 设置好串口调试助手的串口和波特率,ESP8266默认波特率为115200,把串口调试助手的波特率调为115200,并且 勾选左下角的发送新行。 在输入框中输入 AT 然后点击发送:

如果AT测试指令返回OK,就是没问题的,如果未返回,那么需要刷入官方原厂固件才可以继续使用。

由于ESP 8266这种小模块通常只是作为其他设备与MCU的沟通媒介,所以配置成服务器模式进行数据交互就OK了, 按照以下顺序向模块发送AT指令:

-> 下面的指令配置一次就够了,断电重连配置的信息也不会改变

1、AT+RST 复位命令,复位成功后ESP8266会返回一堆乱码,这时候就说明ESP8266配置成功了

2、AT+CWMODE=2 服务器/热点模式

3、AT+CWSAP="esp8266","0123456789",11,3 设置WIFI热点属性,名称,密码,通道号, 加密方式

4、AT+RST 配置完 AT+CWMODE要重启模块使配置生效

-> 下面的指令每次重启模块之后都要配置一遍

5、AT+CIPMUX=1 设置为多连接模式

6、AT+CIPSERVER=1,8080 其中1代表建立服务器,只能选1,端口号没有固定值,可随意修改。

按照上述顺序配置完之后就可以用手机进行连接,使用网络调试助手 https://img.zouchanglin.cn/com.network.debug.apk ,如果手机发现WIFI并且输入密码成功连接了,就证明上面的配置成功了。打开手机网络调试助手,把协议类型设置为"TCP Client", IP地址设置为用 AT+CIFSR 指令查询到的ESP8266的IP(一般为192.168.4.1),端口号就是前面设置的端口号。

手机要连接好ESP8266的WIFI,如果可以连接上,并且串口调试助手收到了手机端发来的数据,那么就说明配置都是OK的,现在基本的手机和ESP8266通信已经完成了。

调整波特率,与C51匹配

上面的配置只是电脑和ESP8266的连接,确保ESP8266运行正常,现在要进行单片机和ESP8266的连接了。因为51单片机通讯的波特率达不到115200,所以最好选择9600即可,所以ESP8266要与单片机进行连接通讯,就要先用电脑把ESP8266的波特率设置为9600;

AT+CIOBAUD=9600 该指令就可以设置ESP8266波特率为9600了,AT+RST重启一下ESP8266。

注意不要忘记把电脑串口调试助手的波特率也改为9600,不然电脑连接ESP8266就会出现错误。

AT+CIPMUX=1与AT+CIPSERVER=1,8080这两条指令每次重启模块之后都要配置一遍,因此,这两条指令让MCU去发送即可,每次MCU重启之后都会自动发动这两条指令进行ESP8266的初始化操作。

C51如何指定波特率呢?其实可以自己计算,也可以通过软件直接计算:

c
/** * @brief 串口初始化,9600bps@11.0592MHz * @param 无 * @retval 无 */ void UART_Init(void) //9600bps@11.0592MHz { PCON |= 0x80; //使能波特率倍速位SMOD SCON = 0x50; //8位数据,可变波特率 TMOD &= 0x0F; //清除定时器1模式位 TMOD |= 0x20; //设定定时器1为8位自动重装方式 TL1 = 0xFA; //设定定时初值 TH1 = 0xFA; //设定定时器重装值 ET1 = 0; //禁止定时器1中断 TR1 = 1; //启动定时器1 EA=1; ES=1; } /** * @brief 串口发送一个字节数据 * @param Byte 要发送的一个字节数据 * @retval 无 */ void UART_SendByte(unsigned char Byte) { SBUF=Byte; while(TI==0); TI=0; }

先测试发送一个字符或者字符串,如果成功,那就说明单片机设置的9600bps发送数据是没问题的。

其实这种思路很重要,每做一部,先看看这一步是否存在问题,这样能缩小问题的范围,不至于最终调试的时候才发现出了BUG,不知道从何找起,单元测试就是这个道理。

MCU与ESP8266接线

串口接线其实非常简单,ESP8266的VCC、GND、TXD、RXD接入C51的3.3V、GND、RXD(P30)、TXD(P31)即可。

需要注意的是,在C51的P31和P30口在接入ESP8266时,烧录程序会有问题,在烧录程序的时候应该将串口移除才可以。

另外ESP8266的CH_PD口应该也接3.3V:

程序编写

UART.h与UART.c

c
// -------------------------- UART.h -------------------------------- #ifndef __UART_H__ #define __UART_H__ void UART_Init(); void UART_SendByte(unsigned char Byte); void UART_SendString(unsigned char *str); #endif //!__UART_H__ // ---------------------------- UART.c ------------------------------ #include <REGX51.H> /** * @brief 串口初始化,4800bps@12.000MHz * @param 无 * @retval 无 */ void UART_Init(void) //9600bps@11.0592MHz { PCON |= 0x80; //使能波特率倍速位SMOD SCON = 0x50; //8位数据,可变波特率 TMOD &= 0x0F; //清除定时器1模式位 TMOD |= 0x20; //设定定时器1为8位自动重装方式 TL1 = 0xFA; //设定定时初值 TH1 = 0xFA; //设定定时器重装值 ET1 = 0; //禁止定时器1中断 TR1 = 1; //启动定时器1 EA=1; ES=1; } /** * @brief 串口发送一个字节数据 * @param Byte 要发送的一个字节数据 * @retval 无 */ void UART_SendByte(unsigned char Byte) { SBUF=Byte; while(TI==0); TI=0; } /** * @brief 串口发送一个字符串数据 * @param str 要发送的字符串指针 * @retval 无 */ void UART_SendString(unsigned char *str) { char *tmp = str; while(*tmp!='\0') { UART_SendByte(*tmp); tmp++; } } /*串口中断函数模板 void UART_Routine() interrupt 4 { if(RI==1) { RI=0; } } */

main.c

c
#include <REGX51.H> #include <INTRINS.H> #include <STRING.H> #include "UART.h" #include "LCD1602.h" unsigned char i = 0; unsigned char flag = 0; unsigned char receive[20] = {0}; void Delay500ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); _nop_(); i = 22; j = 3; k = 227; do { do { while (--k); } while (--j); } while (--i); } // 初始化ESP8266 void Connect_Init() { char *mux="AT+CIPMUX=1\r\n"; char *server="AT+CIPSERVER=1,8080\r\n"; Delay500ms(); UART_SendString(mux); Delay500ms(); UART_SendString(server); } // 收到数据触发中断 void UART_Routine() interrupt 4 { char res; res=SBUF; //取出接受到的数据 RI=0; //清除接受中断标志位 if(res==':'||i>0) //i是全局变量 { receive[i]=res; //receive数组也是全局变量 i++; if(res=='\n') { LCD_ShowNum(2,1,flag++,3); LCD_ShowString(2,5,receive); i=0; //添加对收到信息的处理代码 memset(receive,0,50); } } } void main() { LCD_Init(); UART_Init(); Connect_Init(); LCD_ShowString(1,1,"server ready"); while(1) { } }

其中LCD的代码和之前的LCD1602一模一样,接下来手机连接WIFI,打开网络调试助手,发送信息OK!

最终效果

整个过程中需要注意的点:

1、波特率一定要一致,不要超出MCU支持的最高波特率,一般为9600即可;

2、确保8266模块时正常工作的,接入MCU之前一定要通过USB转TTL在PC上测试;

3、确保MCU串口发送数据没有问题,通过串口调试助手验证;

4、某些开发板由于引脚冲突,可能导致程序异常,这个时候换个最小系统板试试;

5、8266接入MCU后,如果需要烧录MCU,先将8266连接线断开再烧录;

补充:MCU如何回发数据

其实,对于数据回发来说,只需要使用 AT+CIPSEND="0,30" 即可,其中0时客户端ID,30是数据长度,下面是我封装的ESP8266模块:

c
// ------------------------ ESP8266.h ------------------------------- #ifndef __ESP8266_H__ #define __ESP8266_H__ void ESP8266_Connect_Init(); void ESP8266_SendString(char *clientId, char *str, char *length); #endif //!__ESP8266_H__ // ------------------------ ESP8266.c ------------------------------- #include "Delay.h" #include "UART.h" #include "LCD1602.h" // 初始化ESP8266 void ESP8266_Connect_Init() { char *muxCmd="AT+CIPMUX=1\r\n"; char *serverCmd="AT+CIPSERVER=1,8080\r\n"; Delay(200); UART_SendString(muxCmd); Delay(200); UART_SendString(serverCmd); } // 发送到客户端,客户端ID,内容,内容长度 void ESP8266_SendString(char *clientId, char *str, char *length) { // 串口发送数据传出指令, 如AT+CIPSEND=0,10 UART_SendString("AT+CIPSEND="); UART_SendString(clientId); UART_SendString(","); UART_SendString(length); UART_SendString("\r\n"); Delay(100); UART_SendString(str); Delay(20); }

在main.c中直接调用即可:

c
#include <REGX51.H> #include <INTRINS.H> #include <STRING.H> #include "UART.h" #include "LCD1602.h" #include "Delay.h" #include "ESP8266.h" unsigned char i = 0; unsigned char flag = 0; unsigned char receive[50] = {'\0'}; // 收到数据触发中断 void UART_Routine() interrupt 4 { char res; res=SBUF; RI=0; if(res=='+'||i>0) { receive[i]=res; i++; if(res=='\n') { LCD_ShowNum(2,1,flag++,3); LCD_ShowString(2,4,receive); // 收到后做出响应【可选】,参数为客户端ID、内容、长度,注意都是字符串表示形式 ESP8266_SendString("0", "ABC12345678", "11"); i=0; //添加对收到信息的处理代码 memset(receive,0,50); } } } void main() { LCD_Init(); UART_Init(); ESP8266_Connect_Init(); LCD_ShowString(1,1,"success"); while(1) { } }

完整工程代码见 : Wifi模块 -- ESP8266

本文作者:Tim

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!