36. WiFi——ESP8266模块通讯¶
36.1. Wifi模块简介¶
ESP8266-12F是启明6M5开发板板载的一个WiFi模块。 该模块核心处理器ESP8266在较小尺寸封装中集成了业界领先的Tensilica L106超低功耗32位微型MCU。 带有16位精简模式,主频支持80MHz和160MHz。 支持RTOS,集成Wi-Fi MAC/BB/RF/PA/LNA,板载天线。 支持标准的IEEE802.11 b/g/n协议,完整的TCP/IP协议栈。 用户可以使用该模块为现有的设备添加联网功能,也可以构建独立的网络控制器。 尤其是有过物联网开发经验的人,必然绕不过ESP8266,其低廉的价格、超高的性能和便利的开发环境,毫无疑问是业界中里程碑一样的存在。 而在启明6M5开发板中只需要通过SCI9 UART串口和AT指令就可以对ESP8266进行简单的配置。
36.2. ESP8266功能介绍¶
ESP8266整体架构如下图所示。
ESP8266强大的片上处理和存储能力,使其可通过GPIO口集成传感器及其他应用的特定设备,大大地降低了前期开发的成本。 以下为ESP8266的整体特性。
完整的802.11b/g/n Wi-Fi SoC模块
内置Tensilica L106超低功耗32位微型MCU,主频支持80MHz和160MHz,支持RTOS
内置1路10位高精度ADC
支持UART/GPIO/ADC/PWM/SPI/I2C接口
采用SMD-22封装
集成Wi-Fi MAC/BB/RF/PA/LNA
支持多种休眠模式,深度睡眠电流低至20uA
串口速率最高可达4Mbps
内嵌Lwip协议栈
支持STA/AP/STA+AP工作模式
支持安卓、IOS的Smart Config(APP)/AirKiss(微信)一键配网
支持串口本地升级和远程固件升级(FOTA)
通用AT指令,可快速上手
支持二次开发,集成了Windows、Linux开发环境
36.2.1. 通用输入/输出接口(GPIO)¶
ESP8266总共有22个管脚,如下图所示,通过配置适当的寄存器可以给它们分配不同的功能。 每一个GPIO都可以单独配置,如上拉/下拉,或者设置为高阻态。 当被配置为输⼊时,可通过读取寄存器获取输⼊值。 输⼊也可以被设置为边缘触发或电平触发来产⽣CPU中断。 这些管脚可以与其它功能复用,例如I2C、I2S、SPI、ADC、UART、PWM、IR遥控等。
下表为管脚的功能介绍。
管脚 |
名称 |
功能 |
---|---|---|
1 |
RST |
复位 |
2 |
ADC |
A/D转换,输入电压范围0~1V,取值范围:0~1024 |
3 |
EN |
芯片使能端,高电平有效 |
4 |
IO16 |
GPIO16/接到RST管脚时可做deep sleep的唤醒 |
5 |
IO14 |
GPIO14/HSPI_CLK |
6 |
IO12 |
GPIO12/HSPI_MISO |
7 |
IO13 |
GPIO13/HSPI_MOSI/UART0_CTS |
8 |
VCC |
3.3V供电(VDD);外部供电电源输出电流建议在500mA以上 |
9 |
CS0 |
片选信号 |
10 |
MISO |
多输入单输出 |
11 |
IO9 |
GPIO9 |
12 |
IO10 |
GPIO10 |
13 |
MOSI |
单输入多输出 |
14 |
SCLK |
时钟 |
15 |
GND |
接地 |
16 |
IO15 |
GPIO15/MTDO/HSPICS/UART0_RTS |
17 |
IO2 |
GPIO2/UART1_TXD |
18 |
IO0 |
GPIO0;下载模式:外部拉低,运行模式:悬空或者外部拉高 |
19 |
IO4 |
GPIO4 |
20 |
IO5 |
GPIO5/IR_R |
21 |
RXD |
UART0_RXD/GPIO3 |
22 |
TXD |
UART0_TXD/GPIO1 |
功能 |
引脚 |
作用 |
---|---|---|
PWM |
GPIO12(R)、GIPIO15(G)、GPIO13(B) |
可以对PWM接口进行控制,以达到控制单片机外设的目的 |
IR Remote control |
GPIO(IR_T)、GPIO5(IR_R) |
红外遥控接口的功能,可以通过软件编程实现 |
HSPI: |
GPIO12(MISO)、GPIO13(MOSI)、GPIO14(CLK)、GPIO15(CS) |
以使用HSPI接口连接SPI Flash、显示屏和MCU |
ADC |
ADC |
10位高精度模拟ADC |
I2C |
GPIO5(SCL)、GPIO4(SDA) |
用于连接外部传感器或屏幕等 |
UART |
UARTO:GPIO1(TX)、PIO3(RX),UART1:GPIO2(TX)、GPIO8(RX) |
用于打印信息,进行调试,也可以进行数据的发送与接收 |
提示
GPIO6~GPIO11被用于连接开发板的闪存(Flash Memory),因此图中红框内的引脚不可用。
36.2.2. 使用UART与WIFI通讯¶
ESP8266模组与MCU的连接如下表所示:
8266模块引脚 |
MCU引脚 |
MCU外设 |
---|---|---|
WIFI_TXD |
P601 |
SCI9 UART RXD9 |
WIFI_RXD |
P602 |
SCI9 UART TXD9 |
在下方开发板原理图中,可以看到J34的1,2引脚代表着开发板的SCI9 UART串口中的TX、RX接口。 而3,4引脚是ESP8266的SCI9 UART中的RX、TX接口,在实际的开发板中,J34的1,3引脚和2,4引脚一般是通过跳帽连接的,这代表了开发板可以通过SCI9 UART与WIFI模块进行通讯。 也就是说,想要配置ESP8266,就需要与SCI9 UART中的P601与P602两个引脚建立通信。
36.2.3. ESP8266工作模式介绍¶
ESP8266总共有三种工作模式,分别是STA(Station)、AP(Wireless Access Point)、以及STA+AP模式。
STA 模式:在STA模式下,ESP8266就像一个接收设备,此时它可以接受来自其它无线路由器发射的信号,从而连接互联网,让搭载ESP8266的设备实现远程控制。
AP 模式:在AP模式下,ESP8266成为了发射设备,也就是成为了一个热点,手机和电脑等设备都可以连接到这个热点,从而使无线设备能够与ESP8266进行远程通信。
STA + TA 模式:两种模式共同使用,既可以作为客户端连接到别的网络,也可以作为Wifi热点使用,实现广域网与局域网的无缝切换。
关于SCI UART的部分介绍可以去看本教程第19章 SCI UART——串口通信。
36.3. AT指令¶
AT(Attention)指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter,TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的。
在ESP8266芯片出厂时,厂家已经在芯片内部烧写了固件,这使得我们能够通过一些常见的AT指令去控制它。 当然,也可以通过获取SDK的方式重新烧写固件,修改和添加我们想要的功能,在本章节的 “实验四” 中会有涉及。
36.4. 实验一:AT指令接收测试¶
36.4.1. 硬件设计:¶
36.4.2. 软件设计¶
因为要通过UART进行通讯,所以可以直接在第19章工程代码的基础上继续配置。 当我们配置好之后,就可以向ESP8266发送AT指令,控制ESP8266根据AT指令做出进一步的动作。 关于AT指令可以查看AT指令集资料 AT指令集。
36.4.2.1. 新建工程¶
- 对于 e2 studio 开发环境:
拷贝一份我们之前的 e2s 工程 “19_UART_Receive_Send”, 然后将工程文件夹重命名为 35_Wifi_ESP8266_AT,最后再将它导入到我们的 e2 studio 工作空间中。
- 对于 Keil 开发环境:
拷贝一份我们之前的 e2s 工程 “19_UART_Receive_Send”, 然后将工程文件夹重命名为 35_Wifi_ESP8266_AT,并进入该文件夹里面双击 Keil 工程文件,打开该工程。
工程新建好之后,在工程根目录的 “src” 文件夹下面新建 bsp_esp8266 文件夹, 再进入 “bsp_esp8266” 文件夹里面新建源文件和头文件:“bsp_wifi_esp8266.c” 和 “bsp_wifi_esp8266.h”。 工程文件结构如下。
35_Wifi_ESP8266_AT
├─ ......
└─ src
├─ led
│ ├─ bsp_led.c
│ └─ bsp_led.h
├─ debug_uart
│ ├─ bsp_debug_uart.c
│ └─ bsp_debug_uart.h
├─ bsp_esp8266
│ ├─ bsp_wifi_esp8266.c
│ └─ bsp_wifi_esp8266.h
└─ hal_entry.c
36.4.2.2. FSP配置¶
拷贝完成后,先打开 “35_Wifi_ESP8266_AT” 项目的FSP配置界面进行配置。
在 FSP 配置界面里面点开 “Pins”-> “Peripherals”-> “Connectivity:SCI”-> “SCI9” 来配置SCI模块, 配置为“Asynchronous UART”模式,并选择开发板使用串口引脚,如下图所示。
图35-6 配置引脚
在配置界面底部点击 “Stack”,如下图所示步骤加入串口UART:
图35-7 加入串口
点击刚刚加入的窗口,在左下角的“属性”窗口中配置 名字(name)、通道(Channel)、回调函数(Callback)名字即可, 引脚(Pins)、波特率(Baud Rate)等其他的属性按照默认的配置即可。
图35-8 配置串口属性
属性 |
描述 |
---|---|
Name |
名字,根据读者需求设置即可 |
Channel |
通道,根据SCI号设置即可,例如实验使用SCI9,则这里配置为通道9 |
Data Bits |
每个字(word)的比特(bit)数,默认为8bits |
Parity |
校验模式,可选择“Odd”奇校验,“Even”偶校验或“None”无校验 |
Stop Bits |
停止位,可选1或2bit |
Baud Rate |
波特率 |
Baud Rate Modulation |
波特率调制,通过调整时钟周期,以减少申请波特率与实际波特率之间的误差 |
Max Error(%) |
计算波特率时允许的最大百分比误差 |
Callback |
回调函数的名字,根据读者需求设置即可 |
Receive Interrupt Priority |
接收中断优先级 |
Transmit Data Empty Interrupt Priority |
发送数据空中断优先级 |
Transmit End Interrupt Priority |
发送完成中断优先级 |
Error Interrupt Priority |
错误中断优先级 |
最后点右上角的 “Generate Project Content” 按钮,让软件自动生成配置代码。
36.4.2.3. 串口初始化函数¶
FSP配置并生成代码之后,我们就可以开始封装函数了
/* Wifi (UART9) 串口初始化*/
void ESP8266_UART9_Init(void)
{
fsp_err_t err = FSP_SUCCESS;
R_SCI_UART_Open(g_uart9_esp8266.p_ctrl, g_uart9_esp8266.p_cfg);
assert(FSP_SUCCESS == err);
}
36.4.2.4. 串口中断回调函数¶
由于还需要调试串口来帮助打印调试信息,还需要在工程中的的 bsp_debug_uart.c 文件中对UART4写入的字符串首地址修改为ESP8266所在地址:
做好这些工作之后,就可以使用刚才在FSP配置时设置的串口中断回调函数: esp8266_uart9_callback。 设置本函数的意义在于,给ESP8266发送AT指令之后,就可以得到它的回显,从而确定ESP8266的工作状态。 该函数代码如下所示:
/*串口中断回调函数*/
void esp8266_uart9_callback(uart_callback_args_t * p_args)
{
switch(p_args->event)
{
case UART_EVENT_RX_CHAR:
//收到发送的的AT指令后,将ESP8266的回显内容利用调试串口进行打印
R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)&(p_args->data), 1);
break;
default:
break;
}
}
36.4.2.5. hal_entry入口函数¶
最后在hal_entry函数中编写需要的代码。
void hal_entry(void)
{
/* TODO: add your own code here */
Debug_UART4_Init(); // SCI4 UART 调试串口初始化
ESP8266_UART9_Init(); // WIFI (SCI9 UART) 串口初始化
printf("欢迎使用野火启明6M5开发板\n\n");
printf("这是一个ESP8266AT指令测试实验\n\n");
printf("请使用串口调试助手发送\"AT+换行回车\"测试ESP8266是否准备好\n\n");
printf("更多AT指令请参考上文中的AT指令集资料\n\n");
while(1){}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
将调试串口与Wifi(UART9)串口初始化后,在while循环中,可以什么都不做,让单片机等待AT指令。
36.4.2.6. 下载验证¶
保证开发板相关硬件连接正确,用Type-C USB线连接开发板 “USB TO UART” 接口跟电脑。 本次实验需要使用到串口调试助手, 配置好串口参数并打开串口后,在调试助手的发送区域输入AT指令,即可在接收区看见ESP8266的回显内容。
重要
每条AT指令的最后必须是以换行符结束再发送!
36.5. 实验二:STA模式测试¶
由于本实验的目标是测试ESP8266的STA模式,因此我们在上一个实验的基础上修改程序。
在这之前首先要了解一下透传模式,简单的讲就是ESP8266将通过串口接收到的数据, 直接进行转发到所设置的目标服务器的端口上,不需要关心WIFI协议是如何来实现数据的传输。只需要在ESP8266上设置好服务器地址即可。
36.5.1. 软件设计¶
36.5.1.1. 新建工程¶
- 对于 e2 studio 开发环境:
拷贝一份我们之前的 e2s 工程 35_Wifi_ESP8266_AT, 然后将工程文件夹重命名为 35_Wifi_ESP8266_STA,最后再将它导入到我们的 e2 studio 工作空间中。
- 对于 Keil 开发环境:
拷贝一份我们之前的 e2s 工程 35_Wifi_ESP8266_AT, 然后将工程文件夹重命名为 35_Wifi_ESP8266_STA,并进入该文件夹里面双击 Keil 工程文件,打开该工程。
工程文件结构如下。
35_Wifi_ESP8266_STA
├─ ......
└─ src
├─ led
│ ├─ bsp_led.c
│ └─ bsp_led.h
├─ debug_uart
│ ├─ bsp_debug_uart.c
│ └─ bsp_debug_uart.h
├─ bsp_esp8266
│ ├─ bsp_wifi_esp8266.c
│ └─ bsp_wifi_esp8266.h
└─ hal_entry.c
首先,打开网络调试助手,选择协议类型为TCP Server,也就是客户端模式,具体配置如下图所示。
配置好之后,选择启动监听。
36.5.1.2. 宏定义函数¶
首先在bsp_wifi_esp8266.h文件中将我们所需要的数据以及指令用宏定义封装起来。 后续需要更改配置信息只需要在宏定义中稍加修改就可以。
/*宏定义调试信息*/
#define ESP8266_DEBUG 1
#if (ESP8266_DEBUG == 1)
#define ESP8266_DEBUG_MSG(fmt, ... ) printf ( fmt, ##__VA_ARGS__ )
#else
#define ESP8266_DEBUG_MSG(fmt, ... )
#endif
#define ID "AP_DEVICE" //要连接的热点的名称
#define PASSWORD "123456789" //要连接的热点的密钥
#define SeverIP "192.168.103.166" //要连接的服务器IP
#define SeverPort "8000" //要连接的服务器端口
#define ESP8266_MODULE_ENABLE R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_15, BSP_IO_LEVEL_HIGH); //使能ESP8266模块
#define ESP8266_MODULE_DISABLE R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_15, BSP_IO_LEVEL_LOW); //关闭ESP8266模块
/*红灯闪烁*/
#define ESP8266_ERROR_Alarm() R_PORT4->PODR ^= 1<<(BSP_IO_PORT_04_PIN_00 & 0xFF); \
R_BSP_SoftwareDelay(500, BSP_DELAY_UNITS_MILLISECONDS);
/*清除UART9数据缓冲区函数*/
#define Clear_Buff() memset( At_Rx_Buff , 0 , sizeof(At_Rx_Buff) ); \
Uart9_Num = 0;
36.5.1.3. ESP8266-STA功能函数¶
随后在bsp_wifi_esp8266.c文件中添加配置ESP8266所需要的函数。
_Bool Uart9_Receive_Flag = false; //用来判断UART9接收以及发送数据是否完成
_Bool Uart9_Show_Flag = false; //控制UART9收发数据显示标志
/*用来接收UART9数据的缓冲区*/
char At_Rx_Buff[256];
uint8_t Uart9_Num = 0;
/*自动配置ESP8266函数*/
void ESP8266_STA_Test(void)
{
ESP8266_DEBUG_MSG("\r\n正在初始化ESP8266...\r\n");
ESP8266_UART9_Init();
ESP8266_DEBUG_MSG("\r\n设置STA模式中...\r\n");
ESP8266_STA();
ESP8266_DEBUG_MSG("\r\n正在连接WIFI中...\r\n");
ESP8266_STA_JoinAP( ID , PASSWORD , 20 );
Link_Mode( 0 );
ESP8266_DEBUG_MSG("\r\n正在连接服务器中...\r\n");
ESP8266_STA_JoinServer( SeverIP , SeverPort , 20 );
ESP8266_DEBUG_MSG("\r\n正在配置为透传发送模式...\r\n");
ESP8266_STA_Transmission();
ESP8266_Send_Data();
}
/*ESP8266 (SPI9 UART) 初始化函数*/
void ESP8266_UART9_Init(void)
{
fsp_err_t err = FSP_SUCCESS;
err = R_SCI_UART_Open(g_uart9_esp8266.p_ctrl, g_uart9_esp8266.p_cfg);
assert(FSP_SUCCESS == err);
}
/*向ESP8266发送AT指令函数*/
void ESP8266_AT_Send(char * cmd )
{
/*向ESP8266(UART9)发送指令*/
R_SCI_UART_Write(&g_uart9_esp8266_ctrl, (uint8_t *)cmd, strlen(cmd));
/*AT指令发送完成标志*/
Uart9_Receive_Flag = false;
}
/*设置ESP8266为 STA 模式*/
void ESP8266_STA ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=1\r\n" );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为STA模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置ESP8266为 AP 模式*/
void ESP8266_AP ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=2\r\n" );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为AP模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置ESP8266为 STA + AP 模式*/
void ESP8266_STA_AP ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=3\r\n" );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为STA+AP模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*ESP8266连接WiFi函数*/
void ESP8266_STA_JoinAP( char * id , char * password , uint8_t timeout ) //timeout:期望连接时间,单位为秒
{
char JoinAP_AT[256];
uint8_t i;
sprintf( JoinAP_AT , "AT+CWJAP=\"%s\",\"%s\"\r\n" , id , password);
ESP8266_AT_Send( JoinAP_AT );
/*判断Wifi连接是否成功*/
for(i = 0; i <= timeout; i++)
{
if ( strstr( At_Rx_Buff , "OK\r\n" ) )
{
ESP8266_DEBUG_MSG("\r\nWifi连接成功\r\n");
Clear_Buff(); //清除缓冲区数据
break;
}
if ( strstr( At_Rx_Buff , "ERROR\r\n" ) ) //根据ESP8266的固件版本不同有不同的响应,一般为“FAIL”或“ERROR”
{
if( strstr( At_Rx_Buff , "+CWJAP:1\r\n" ))
ESP8266_DEBUG_MSG("\r\nWifi连接超时,请检查各项配置是否正确\r\n");
if( strstr( At_Rx_Buff , "+CWJAP:2\r\n" ))
ESP8266_DEBUG_MSG("\r\nWifi密码错误,请检查Wifi密码是否正确\r\n");
if( strstr( At_Rx_Buff , "+CWJAP:3\r\n" ))
ESP8266_DEBUG_MSG("\r\n无法找到目标Wifi,请检查Wifi是否打开或Wifi名称是否正确\r\n");
if( strstr( At_Rx_Buff , "+CWJAP:4\r\n" ))
ESP8266_DEBUG_MSG("\r\nWifi连接失败,请检查各项配置是否正确\r\n");
while(1)
{
ESP8266_ERROR_Alarm();
} //LED灯警告错误,红灯闪烁
}
if ( i == timeout )
{
ESP8266_DEBUG_MSG("\r\nWifi连接超出期望时间,请检查各项配置是否正确\r\n");
while(1)
{
ESP8266_ERROR_Alarm();
} //LED灯警告错误,红灯闪烁
}
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
}
}
/*设置连接模式为单连接或者多连接*/
void Link_Mode( uint8_t mode )
{
switch ( mode ){
case 0 :
ESP8266_AT_Send("AT+CIPMUX=0\r\n"); //设置为单连接模式,透传只有在单连接模式下才能进行
break;
case 1 :
ESP8266_AT_Send("AT+CIPMUX=1\r\n"); //设置为多连接模式,服务器只有在多连接模式下才能打开
break;
}
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
if( mode )
ESP8266_DEBUG_MSG("\r\nESP8266已切换为多连接模式\r\n");
else
ESP8266_DEBUG_MSG("\r\nESP8266已切换为单连接模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*ESP8266连接服务器函数*/
void ESP8266_STA_JoinServer( char * server_id , char * port , uint8_t timeout ) //timeout:期望连接时间,单位为秒
{
char JoinServer_AT[256];
uint8_t i;
sprintf( JoinServer_AT , "AT+CIPSTART=\"TCP\",\"%s\",%s\r\n" , server_id , port );
ESP8266_AT_Send( JoinServer_AT );
/*判断服务器连接是否设置成功*/
while ( !Uart9_Receive_Flag )
{
/*超时判断,timeout:期望最长等待时间*/
for(i = 0; i <= timeout; i++)
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\n服务器连接成功\r\n");
Clear_Buff(); //清除缓冲区数据
break;
}
if (strstr( At_Rx_Buff , "ERROR\r\n" ))
{
ESP8266_DEBUG_MSG("\r\n服务器连接失败,请检查服务器是否打开以及参数是否正确\r\n");
while(1)
{
ESP8266_ERROR_Alarm();
} //LED灯警告错误,红灯闪烁
}
if ( i == timeout )
{
ESP8266_DEBUG_MSG("\r\n服务器连接超出期望时间,请检查各项配置是否正确\r\n");
while(1)
{
ESP8266_ERROR_Alarm();
} //LED灯警告错误,红灯循环闪烁
}
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
}
}
}
/*设置ESP8266为透传模式*/
void ESP8266_STA_Transmission( void )
{
ESP8266_AT_Send ( "AT+CIPMODE=1\r\n" );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为透传模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置ESP8266为发送数据模式*/
void ESP8266_Send_Data( void )
{
ESP8266_AT_Send ( "AT+CIPSEND\r\n" );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已进入透传发送模式\r\n\r\n>");
Uart9_Show_Flag = true;
Clear_Buff(); //清除缓冲区数据
}
}
}
36.5.1.4. 中断回调函数¶
/*Wifi串口回调函数*/
void esp8266_uart9_callback(uart_callback_args_t * p_args)
{
switch(p_args->event)
{
case UART_EVENT_RX_CHAR:
At_Rx_Buff[Uart9_Num++] = ( char ) p_args->data; //将UART9收到的数据放到Buff缓冲区中
/*进入透传模式后打开串口调试助手收发数据显示*/
if( Uart9_Show_Flag )
R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)&(p_args->data), 1);
break;
case UART_EVENT_TX_COMPLETE:
{
Uart9_Receive_Flag = true; //ESP8266回应完成标志
break;
}
default:
break;
}
}
36.5.1.5. hal_entry入口函数¶
void hal_entry(void)
{
/* TODO: add your own code here */
Debug_UART4_Init(); // SCI4 UART 调试串口初始化
ESP8266_STA_Test(); // ESP8266 自动配置函数
while(1){}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
以下实验的hal_entry函数均与本实验大致相同,不再过多展示。
36.5.1.6. 下载验证¶
首先使用电脑或手机设备打开热点,并将热点名称和密码设置完成。 编译并下载程序后,可以得到程序的提示信息。
此时就代表ESP8266已经配置完成,其中包括AP以及服务器的连接。 这时就可以打开网络调试助手发送信息,可以看到串口能够接收到发送的信息。
同样的,在串口调试助手中发送信息,网络调试助手同样可以收到。
提示
透传模式的结束指令为“+++”,在不使用透传模式时要记得发送指令结束该模式。 如果不发送结束指令,下一次重新上电时ESP8266将仍处于透传模式。 如果不想因为忘记关闭透传指令而带来问题的话,可以先发送 “+++” 关闭透传模式,随后发送 “AT+SAVETRANSLINK=0” 这一指令, 这可以让下一次重新上电后不自动进入透传模式。 同样的,如果需要每一次上电都位于透传模式下,也只需要发送 “AT+SAVETRANSLINK=1” 这一指令即可。
36.6. 实验三:AP模式测试¶
由于本实验的目标是测试ESP8266的AP模式,在上一个实验中我们已经封装了一些函数,因此我们可以在上一个实验的基础上继续修改程序。
36.6.1. 软件设计¶
36.6.1.1. 新建工程¶
- 对于 e2 studio 开发环境:
拷贝一份我们之前的 e2s 工程 35_Wifi_ESP8266_STA, 然后将工程文件夹重命名为 35_Wifi_ESP8266_AP,最后再将它导入到我们的 e2 studio 工作空间中。
- 对于 Keil 开发环境:
拷贝一份我们之前的 e2s 工程 35_Wifi_ESP8266_STA, 然后将工程文件夹重命名为 35_Wifi_ESP8266_AP,并进入该文件夹里面双击 Keil 工程文件,打开该工程。
工程文件结构如下。
35_Wifi_ESP8266_AP
├─ ......
└─ src
├─ led
│ ├─ bsp_led.c
│ └─ bsp_led.h
├─ debug_uart
│ ├─ bsp_debug_uart.c
│ └─ bsp_debug_uart.h
├─ bsp_esp8266
│ ├─ bsp_wifi_esp8266.c
│ └─ bsp_wifi_esp8266.h
└─ hal_entry.c
36.6.1.2. 宏定义函数¶
在上一个实验的基础上,只需要添加和更改文件bsp_wifi_esp8266.h中的几个宏定义就可以了。 同样,我们在后续想要修改配置信息时也只需要稍加修改即可。
#define ID "ESP8266" //要设置的热点的名称
#define PASSWORD "123456789" //要设置的热点的密钥
#define CHANNEL "1" //要设置的通道号
#define ENCRY_MODE "3" //要设置的加密方式
#define SERVER_MODE "1" //建立/关闭 服务器,1为建立,0为关闭
#define SERVER_PORT "8080" //设置服务器端口号
其中AP配置指令各参数为: “AT+CWSAP=”热点名称”,”热点密码”,通道号,加密方式” 。 其中加密方式分为:
0 : OPEN
1 : WEP
2 : WPA_PSK
3 : WPA2_PSK
4 : WPA_WPA2_PSK
36.6.1.3. ESP8266-AP功能函数¶
在文件bsp_wifi_esp8266.c中,添加所需要的函数功能。
_Bool Uart9_Receive_Flag = false; //用来判断UART9接收以及发送数据是否完成
_Bool Uart9_Show_Flag = false; //控制UART9收发数据显示标志
/*用来当作接收UART9数据的缓冲区*/
char At_Rx_Buff[256];
uint8_t Uart9_Num = 0;
/*自动配置ESP8266函数*/
void ESP8266_AP_Test(void)
{
ESP8266_DEBUG_MSG("\r\n正在初始化ESP8266...\r\n");
ESP8266_UART9_Init();
ESP8266_DEBUG_MSG("\r\n设置AP模式中...\r\n");
ESP8266_AP();
ESP8266_Rst(); //重启ESP8266模块
ESP8266_DEBUG_MSG("\r\n正在配置Wifi中...\r\n");
ESP8266_AP_SetAP( ID , PASSWORD , CHANNEL , ENCRY_MODE );
Link_Mode( 1 );
ESP8266_DEBUG_MSG("\r\n正在建立服务器中...\r\n");
ESP8266_AP_SetServer( SERVER_MODE , SERVER_PORT );
ESP8266_DEBUG_MSG("\r\n等待连接...\r\n");
Query_Address(); //提示配置信息
}
/*ESP8266 (SPI9 UART) 初始化*/
void ESP8266_UART9_Init(void)
{
fsp_err_t err = FSP_SUCCESS;
err = R_SCI_UART_Open(g_uart9_esp8266.p_ctrl, g_uart9_esp8266.p_cfg);
assert(FSP_SUCCESS == err);
}
/*向ESP8266发送AT指令函数*/
void ESP8266_AT_Send(char * cmd )
{
/*向ESP8266(UART9)发送指令*/
R_SCI_UART_Write(&g_uart9_esp8266_ctrl, (uint8_t *)cmd, strlen(cmd));
/*AT指令发送完成标志*/
Uart9_Receive_Flag = false;
}
/*重启ESP8266函数*/
void ESP8266_Rst(void)
{
ESP8266_AT_Send ( "AT+RST\r\n" );
/*判断是否设置成功*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "ready\r\n" ))
{
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //等待重启完成
ESP8266_DEBUG_MSG("\r\nESP8266已重启\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置ESP8266为 STA 模式*/
void ESP8266_STA ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=1\r\n" );
/*判断是否设置成功*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为STA模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置ESP8266为 AP 模式*/
void ESP8266_AP ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=2\r\n" );
/*判断是否设置成功*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为AP模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置ESP8266为 STA + AP 模式*/
void ESP8266_STA_AP ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=3\r\n" );
/*判断是否设置成功*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为STA+AP模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*ESP8266配置热点信息函数*/
void ESP8266_AP_SetAP( char * id , char * password , char * channel_num , char * encry_mode )
{
char SetAP_AT[256];
sprintf( SetAP_AT , "AT+CWSAP=\"%s\",\"%s\",%s,%s\r\n" , id , password , channel_num , encry_mode );
ESP8266_AT_Send( SetAP_AT );
/*判断是否设置成功*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已配置好Wifi\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置连接模式为单连接或者多连接*/
void Link_Mode( uint8_t mode )
{
switch ( mode ){
case 0 :
ESP8266_AT_Send("AT+CIPMUX=0\r\n"); //设置为单连接模式,透传只有在单连接模式下才能进行
break;
case 1 :
ESP8266_AT_Send("AT+CIPMUX=1\r\n"); //设置为多连接模式,服务器只有在多连接模式下才能打开
break;
}
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
if( mode )
ESP8266_DEBUG_MSG("\r\nESP8266已切换为多连接模式\r\n");
else
ESP8266_DEBUG_MSG("\r\nESP8266已切换为单连接模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*建立/关闭 TCP 或 SSL 服务器*/
void ESP8266_AP_SetServer( char * mode , char * port )
{
char SetServer_AT[256];
sprintf( SetServer_AT , "AT+CIPSERVER=%s,%s\r\n" , mode , port );
ESP8266_AT_Send( SetServer_AT );
/*判断是否设置成功*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已配置好服务器信息\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*获取打印ESP8266的AP配置信息*/
void Query_Address(void)
{
/*获取IP/MAC地址*/
ESP8266_AT_Send ( "AT+CIFSR\r\n" );
const char s[1] = "\"";
char * AP_ID;
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
AP_ID = strtok( At_Rx_Buff , s ); //获取IP地址
AP_ID = strtok( NULL , s );
}
}
ESP8266_DEBUG_MSG("\nWifi名称为 '%s'\n",ID);
ESP8266_DEBUG_MSG("Wifi密码为 '%s'\n",PASSWORD);
ESP8266_DEBUG_MSG("\nIP地址为 '%s'\n",AP_ID);
ESP8266_DEBUG_MSG("服务器端口号为 '%s'\n", SERVER_PORT);
Clear_Buff(); //清除缓冲区数据
Uart9_Show_Flag = true; //开启回显
}
36.6.1.4. 中断回调函数¶
/*Wifi串口回调函数*/
void esp8266_uart9_callback(uart_callback_args_t * p_args)
{
switch(p_args->event)
{
case UART_EVENT_RX_CHAR:
At_Rx_Buff[Uart9_Num++] = ( char ) p_args->data; //将UART9收到的数据放到Buff缓冲区中
/*普通传输模式时打开串口调试助手收发数据显示*/
if( Uart9_Show_Flag )
R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)&(p_args->data), 1);
break;
case UART_EVENT_TX_COMPLETE:
{
Uart9_Receive_Flag = true; //ESP8266回应完成标志
break;
}
default:
break;
}
}
36.6.1.5. 下载验证¶
编译并下载程序后,可以得到程序的反馈信息。 这里使用手机,根据提示信息连接ESP8266所建立的热点,并打开网络调试助手连接ESP8266建立的TCP网络。
随后用手机发送数据,可以看到ESP8266能够接受到数据,同样,我们也可以用AT+CIPSEND等AT指令来让ESP8266发送数据,具体用法请参考 AT指令集。
36.7. 实验四:MQTT测试¶
由于本实验的目标是测试ESP8266的MQTT模式,需要在STA模式下进行,因此我们在STA模式实验的基础上修改程序。
MQTT,翻译过来就是消息队列遥测传输,是在ISO标准(ISO/IEC PRF 20922)下基于 发布/订阅 范式的消息协议。 它工作在TCP/IP协议族上,是专门为硬件性能低下的远程设备以及网络不好的情况下而设计的,为此,它需要一个消息中间件。
MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。 在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。 其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。
在实验开始之前,通常还需要进行ESP8266固件的更新。 首先可以通过 “AT+GMR” 指令来查询ESP8266的固件版本。 关于如何更新固件大家可以自行去网上搜索具体教程,这里不再赘述,只告诉大家更新固件的引脚接法以及固件包的选择。
36.7.1. 更新固件¶
固件更新流程:
断电
断开J32中1,2脚的连接,并将2,3脚连接在一起
断开J34中1,3和2,4引脚连接,并连接3 ,5和4,6引脚
断开J35的连接
打开电源,更新固件
36.7.1.1. 硬件说明¶
在ESP8266-12F的产品规格书上面可以看到,当IO0引脚拉低时为下载模式,拉高(或外部悬空)时为运行模式。 所以想要更新固件,就要把ESP8266首先设置为下载模式,根据开发板原理图来看,也就是断开J32中1,2脚的连接,并将2,3脚连接在一起。
想要下载固件,自然就要让USB串口与ESP8266进行连接,所以根据原理图可以看到,断开J34中1,3和2,4引脚连接,并连接3 ,5和4,6引脚,并断开J35的连接,不然USB传输的数据会被传输到SPI4 UART串口。
36.7.2. 创建MQTT服务器¶
关于创建 MQTT 服务器的教程大家可以去网上搜索教程,自行创建远程或本地服务器,这里同样不过多赘述。
36.7.3. 软件设计¶
关于MQTT的指令部分功能可以去 MQTT AT 命令集 进行查阅。
36.7.3.1. 新建工程¶
- 对于 e2 studio 开发环境:
拷贝一份我们之前的 e2s 工程 35_Wifi_ESP8266_STA, 然后将工程文件夹重命名为 35_Wifi_ESP8266_MQTT,最后再将它导入到我们的 e2 studio 工作空间中。
- 对于 Keil 开发环境:
拷贝一份我们之前的 e2s 工程 35_Wifi_ESP8266_STA, 然后将工程文件夹重命名为 35_Wifi_ESP8266_MQTT,并进入该文件夹里面双击 Keil 工程文件,打开该工程。
工程文件结构如下。
35_Wifi_ESP8266_MQTT
├─ ......
└─ src
├─ led
│ ├─ bsp_led.c
│ └─ bsp_led.h
├─ debug_uart
│ ├─ bsp_debug_uart.c
│ └─ bsp_debug_uart.h
├─ bsp_esp8266
│ ├─ bsp_wifi_esp8266.c
│ └─ bsp_wifi_esp8266.h
└─ hal_entry.c
36.7.3.2. 宏定义函数¶
在STA实验的基础上,同样要对bsp_wifi_esp8266.h中的几个宏定义进行修改。
#define ID "AP_DEVICE" //要连接的热点的名称
#define PASSWORD "123456789" //要连接的热点的密钥
#define CLIENT_ID "QiMing" //MQTT用户ID
#define USER_NAME "ESP8266" //MQTT用户名称
#define USER_PASSWORD "1234567" //MQTT用户密码
#define MQTT_IP "121.40.133.245" //要连接的MQTT服务器IP
#define MQTT_Port "1883" //要连接的MQTT服务器端口
#define MQTT_TOPICS "ESP8266_Test" //要订阅的主题名
#define TOPICS_DATA "Hello_I'm_ESP8266" //要发送的数据
36.7.3.3. MQTT功能函数¶
在文件bsp_wifi_esp8266.c中,添加所需要的函数功能。
_Bool Uart9_Receive_Flag = false; //用来判断UART9接收以及发送数据是否完成
_Bool Uart9_Show_Flag = false; //控制UART9收发数据显示标志
/*用来接收UART9数据的缓冲区*/
char At_Rx_Buff[256];
uint8_t Uart9_Num = 0;
/*自动配置ESP8266函数*/
void ESP8266_MQTT_Test(void)
{
ESP8266_DEBUG_MSG("\r\n正在初始化ESP8266...\r\n");
ESP8266_UART9_Init();
ESP8266_DEBUG_MSG("\r\n设置STA模式中...\r\n");
ESP8266_STA();
ESP8266_Rst();
ESP8266_DEBUG_MSG("\r\n正在连接WIFI中...\r\n");
ESP8266_STA_JoinAP( ID , PASSWORD , 20 );
ESP8266_DEBUG_MSG("\r\n正在配置MQTT用户信息...\r\n");
MQTT_SetUserProperty( CLIENT_ID , USER_NAME, USER_PASSWORD );
ESP8266_DEBUG_MSG("\r\n正在连接MQTT服务器...\r\n");
Connect_MQTT( MQTT_IP , MQTT_Port , 10 );
ESP8266_DEBUG_MSG("\r\n正在订阅主题...\r\n");
Subscribes_Topics( MQTT_TOPICS );
ESP8266_DEBUG_MSG("\r\n正在发布消息...\r\n");
Send_Data( MQTT_TOPICS , TOPICS_DATA );
}
/*ESP8266 (SPI9 UART) 初始化函数*/
void ESP8266_UART9_Init(void)
{
fsp_err_t err = FSP_SUCCESS;
err = R_SCI_UART_Open(g_uart9_esp8266.p_ctrl, g_uart9_esp8266.p_cfg);
assert(FSP_SUCCESS == err);
}
/*向ESP8266发送AT指令函数*/
void ESP8266_AT_Send(char * cmd )
{
/*向ESP8266(UART9)发送指令*/
R_SCI_UART_Write(&g_uart9_esp8266_ctrl, (uint8_t *)cmd, strlen(cmd));
/*AT指令发送完成标志*/
Uart9_Receive_Flag = false;
}
/*设置ESP8266为 STA 模式*/
void ESP8266_STA ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=1\r\n" );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为STA模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置ESP8266为 AP 模式*/
void ESP8266_AP ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=2\r\n" );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为AP模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*设置ESP8266为 STA + AP 模式*/
void ESP8266_STA_AP ( void )
{
ESP8266_AT_Send ( "AT+CWMODE=3\r\n" );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nESP8266已切换为STA+AP模式\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*重启ESP8266函数*/
void ESP8266_Rst(void)
{
ESP8266_AT_Send ( "AT+RST\r\n" );
/*判断是否设置成功*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "ready\r\n" ))
{
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //等待重启完成
ESP8266_DEBUG_MSG("\r\nESP8266已重启\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*ESP8266连接WiFi函数,timeout:期望最大连接时间*/
void ESP8266_STA_JoinAP( char * id , char * password , uint8_t timeout )
{
char JoinAP_AT[256];
uint8_t i;
sprintf( JoinAP_AT , "AT+CWJAP=\"%s\",\"%s\"\r\n" , id , password);
ESP8266_AT_Send( JoinAP_AT );
/*判断连接是否设置成功,失败则打印错误信息*/
while ( !Uart9_Receive_Flag )
{
for(i = 0; i <= timeout; i++)
{
if ( strstr( At_Rx_Buff , "OK\r\n" ) )
{
ESP8266_DEBUG_MSG("\r\nWifi连接成功\r\n");
Clear_Buff(); //清除缓冲区数据
break;
}
if ( strstr( At_Rx_Buff , "ERROR\r\n" ) )
{
if( strstr( At_Rx_Buff , "+CWJAP:1\r\n" ))
ESP8266_DEBUG_MSG("\r\nWifi连接超时,请检查各项配置是否正确\r\n");
if( strstr( At_Rx_Buff , "+CWJAP:2\r\n" ))
ESP8266_DEBUG_MSG("\r\nWifi密码错误,请检查Wifi密码是否正确\r\n");
if( strstr( At_Rx_Buff , "+CWJAP:3\r\n" ))
ESP8266_DEBUG_MSG("\r\n无法找到目标Wifi,请检查Wifi是否打开或Wifi名称是否正确\r\n");
if( strstr( At_Rx_Buff , "+CWJAP:4\r\n" ))
ESP8266_DEBUG_MSG("\r\nWifi连接失败,请检查各项配置是否正确\r\n");
while(1)
{
ESP8266_ERROR_Alarm();
} //LED灯警告错误,红灯闪烁
}
if ( i == timeout )
{
ESP8266_DEBUG_MSG("\r\nWifi连接超出期望时间,请检查各项配置是否正确\r\n");
while(1)
{
ESP8266_ERROR_Alarm();
} //LED灯警告错误,红灯闪烁
}
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
}
}
}
/*设置 MQTT 用户属性*/
void MQTT_SetUserProperty( char * client_id , char * user_name, char * user_password )
{
char SetUserProperty_AT[256];
sprintf( SetUserProperty_AT , "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n" , client_id , user_name , user_password);
ESP8266_AT_Send ( SetUserProperty_AT );
/*等待设置完成*/
while ( !Uart9_Receive_Flag )
{
if (strstr( At_Rx_Buff , "OK\r\n" ))
{
ESP8266_DEBUG_MSG("\r\nMQTT用户属性已设置完成\r\n");
Clear_Buff(); //清除缓冲区数据
}
}
}
/*连接MQTT服务器函数*/
void Connect_MQTT( char * mqtt_ip , char * mqtt_port , uint8_t timeout )
{
char Connect_MQTT_AT[256];
uint8_t i;
sprintf( Connect_MQTT_AT , "AT+MQTTCONN=0,\"%s\",%s,0\r\n" , mqtt_ip , mqtt_port);
ESP8266_AT_Send( Connect_MQTT_AT );
/*判断连接是否设置成功,失败则打印错误信息*/
while ( !Uart9_Receive_Flag )
{
for(i = 0; i <= timeout; i++)
{
if ( strstr( At_Rx_Buff , "OK\r\n" ) )
{
ESP8266_DEBUG_MSG("\r\nMQTT服务器连接成功\r\n");
Clear_Buff(); //清除缓冲区数据
break;
}
if ( strstr( At_Rx_Buff , "ERROR\r\n" ) )
{
ESP8266_DEBUG_MSG("\r\nMQTT服务器连接失败,请检查各项配置是否正确\r\n");
while(1)
{
ESP8266_ERROR_Alarm();
} //LED灯警告错误,红灯闪烁
}
if ( i == timeout )
{
ESP8266_DEBUG_MSG("\r\nMQTT服务器连接超出期望时间,请检查各项配置是否正确\r\n");
while(1)
{
ESP8266_ERROR_Alarm();
} //LED灯警告错误,红灯闪烁
}
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
}
}
}
/*订阅主题函数*/
void Subscribes_Topics( char * topics )
{
char Sub_Topics_AT[256];
sprintf( Sub_Topics_AT , "AT+MQTTSUB=0,\"%s\",1\r\n" , topics);
ESP8266_AT_Send( Sub_Topics_AT );
while ( !Uart9_Receive_Flag )
{
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //订阅等待时间
if ( strstr( At_Rx_Buff , "OK" ) )
{
ESP8266_DEBUG_MSG("\r\n主题订阅成功\r\n");
Clear_Buff(); //清除缓冲区数据
break;
}
if ( strstr( At_Rx_Buff , "ALREADY\r\n" ) )
{
ESP8266_DEBUG_MSG("\r\n已经订阅过该主题\r\n");
Clear_Buff(); //清除缓冲区数据
break;
}
}
}
/*发布MQTT消息函数*/
void Send_Data( char * topics , char * data )
{
char Send_Data[256];
sprintf( Send_Data , "AT+MQTTPUB=0,\"%s\",\"%s\",1,0\r\n" , topics , data );
ESP8266_AT_Send( Send_Data );
while ( !Uart9_Receive_Flag )
{
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //发布等待时间
if ( strstr( At_Rx_Buff , "OK\r\n" ) )
{
ESP8266_DEBUG_MSG("\r\n消息发布成功\r\n");
Uart9_Show_Flag = true; //打开串口回显
Clear_Buff(); //清除缓冲区数据
break;
}
if ( strstr( At_Rx_Buff , "ALREADY" ) )
{
ESP8266_DEBUG_MSG("\r\n消息发布失败,请检查消息格式等信息是否正确\r\n");
Clear_Buff(); //清除缓冲区数据
break;
}
}
}
36.7.3.4. 中断回调函数¶
/*Wifi串口回调函数*/
void esp8266_uart9_callback(uart_callback_args_t * p_args)
{
switch(p_args->event)
{
case UART_EVENT_RX_CHAR:
At_Rx_Buff[Uart9_Num++] = ( char ) p_args->data; //将UART9收到的数据放到Buff缓冲区中
/*进入透传模式后打开串口调试助手收发数据显示*/
if( Uart9_Show_Flag )
R_SCI_UART_Write(&g_uart4_ctrl, (uint8_t *)&(p_args->data), 1);
break;
case UART_EVENT_TX_COMPLETE:
{
Uart9_Receive_Flag = true; //ESP8266回应完成标志
break;
}
default:
break;
}
}
36.7.3.5. 下载验证¶
由于本实验还要测试ESP8266的主题信息发布功能,所以在编译之前还需要其它的 MQTT 客户端测试工具验证,在本实验中使用的是 MQTTX 软件。 使用 MQTT 客户端测试工具连接创建好的服务器,并订阅与程序中配置相同的主题。 随后使用电脑或手机等设备打开热点,并将热点名称和密码设置完成。 编译并下载程序后,可以得到程序的提示信息。
打开 MQTT 客户端测试工具,可以看到ESP8266发送的信息。
同样,我们在 MQTT 客户端测试工具中发送消息,ESP8266同样也可以收到。