文章目录
- 一、Wifi模块简介
- 二、ESP8266功能介绍
- 1. 通用输入/输出接口(GPIO)
- 2. 使用UART与WIFI通讯
- 3. ESP8266工作模式介绍
- 三、AT指令
- 四、实验:STA模式测试
- 1. 文件结构
- 2. 宏定义函数
- 3. ESP8266-STA功能函数
- 4. 中断回调函数
- 5. hal_entry入口函数
一、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进行简单的配置。
二、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开发环境
1. 通用输入/输出接口(GPIO)
ESP8266总共有22个管脚,如下图所示,通过配置适当的寄存器可以给它们分配不同的功能。 每一个GPIO都可以单独配置,如上拉/下拉,或者设置为高阻态。 当被配置为输⼊时,可通过读取寄存器获取输⼊值。 输⼊也可以被设置为边缘触发或电平触发来产⽣CPU中断。 这些管脚可以与其它功能复用,例如I2C、I2S、SPI、ADC、UART、PWM、IR遥控等。
ESP8266管脚功能定义
ESP8266引脚功能介绍
2. 使用UART与WIFI通讯
ESP8266模组与MCU的连接如下表所示:
在下方开发板原理图中,可以看到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两个引脚建立通信。
3. ESP8266工作模式介绍
ESP8266总共有三种工作模式,分别是STA(Station)、AP(Wireless Access Point)、以及STA+AP模式。
STA 模式:在STA模式下,ESP8266就像一个接收设备,此时它可以接受来自其它无线路由器发射的信号,从而连接互联网,让搭载ESP8266的设备实现远程控制。
AP 模式:在AP模式下,ESP8266成为了发射设备,也就是成为了一个热点,手机和电脑等设备都可以连接到这个热点,从而使无线设备能够与ESP8266进行远程通信。
STA + TA 模式:两种模式共同使用,既可以作为客户端连接到别的网络,也可以作为Wifi热点使用,实现广域网与局域网的无缝切换。
三、AT指令
AT(Attention)指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter,TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的。
在ESP8266芯片出厂时,厂家已经在芯片内部烧写了固件,这使得能够通过一些常见的AT指令去控制它。 当然,也可以通过获取SDK的方式重新烧写固件,修改和添加想要的功能。
四、实验:STA模式测试
在这之前首先要了解一下透传模式,简单的讲就是ESP8266将通过串口接收到的数据, 直接进行转发到所设置的目标服务器的端口上,不需要关心WIFI协议是如何来实现数据的传输。只需要在ESP8266上设置好服务器地址即可。
1. 文件结构
└─ 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,也就是客户端模式,具体配置如下图所示。
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;
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(); //清除缓冲区数据
}
}
}
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;
}
}
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
}