Files
FreeRTOS_LoRa_Environment_A…/STM32/Gateway_Node/Drivers/ESP8266.c

425 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "esp8266.h"
volatile uint8_t ucTcpClosedFlag = 0;
char cStr [ 1500 ] = { 0 };
struct SerialFrame_t xSerialFrameRecord = { 0 };
/**
* @brief vEsp8266GpioConfig
* @note ESP8266模块连接引脚配置函数该函数被vEsp8266Init调用。
* @param 无
* @retval 无
*/
void vEsp8266GpioConfig ( void )
{
/* 定义一个GPIO_InitTypeDef类型的结构体 */
GPIO_InitTypeDef GPIO_InitStructure;
/* 配置 CH_PD 引脚*/
RCC_APB2PeriphClockCmd ( macESP8266_CH_PD_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = macESP8266_CH_PD_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init ( macESP8266_CH_PD_PORT, & GPIO_InitStructure );
/* 配置 RST 引脚*/
RCC_APB2PeriphClockCmd ( macESP8266_RST_CLK, ENABLE );
GPIO_InitStructure.GPIO_Pin = macESP8266_RST_PIN;
GPIO_Init ( macESP8266_RST_PORT, & GPIO_InitStructure );
}
/**
* @brief vEsp8266Rst
* @note 调用这个函数就可以重启ESP8266模块该函数被vEsp8266AtTest调用。
* @param 无
* @retval 无
*/
void vEsp8266Rst ( void )
{
#if 0
bEsp8266Command ( "AT+RST", "OK", "ready", 2500 );
#else
macESP8266_RST_LOW_LEVEL();
vDelayMs ( 500 );
macESP8266_RST_HIGH_LEVEL();
#endif
}
/**
* @brief bEsp8266Command
* @note 对ESP8266模块发送AT指令,并等待响应。该函数被外部调用。
* @param pcCmd待发送的指令
* @param pcReply1pcReply2期待的响应为NULL表不需响应两者为或逻辑关系。
* @param ulWaittime等待响应的时间
* @retval true指令发送成功
* @retval false指令发送失败
*/
bool bEsp8266Command ( char * pcCmd, char * pcAck1, char * pcAck2, uint32_t ulWaittime )
{
xSerialFrameRecord .Bits_t .usFrameLength = 0; //从新开始接收新的数据包
vUsartPrintf ( USART2, "%s\r\n", pcCmd );
if ( ( pcAck1 == 0 ) && ( pcAck2 == 0 ) ) //不需要接收数据
return true;
vDelayMs( ulWaittime ); //延时
xSerialFrameRecord .cSerialReceivedBuffer [ xSerialFrameRecord .Bits_t .usFrameLength ] = '\0';
if ( ( pcAck1 != 0 ) && ( pcAck2 != 0 ) )
return ( ( bool ) strstr ( xSerialFrameRecord .cSerialReceivedBuffer, pcAck1 ) ||
( bool ) strstr ( xSerialFrameRecord .cSerialReceivedBuffer, pcAck2 ) );
else if ( pcAck1 != 0 )
return ( ( bool ) strstr ( xSerialFrameRecord .cSerialReceivedBuffer, pcAck1 ) );
else
return ( ( bool ) strstr ( xSerialFrameRecord .cSerialReceivedBuffer, pcAck2 ) );
}
/**
* @brief vEsp8266AtTest
* @note 对ESP8266模块进行AT测试启动该函数被外部调用。
* @param 无
* @retval 无
*/
void vEsp8266AtTest ( void )
{
char count=0;
macESP8266_RST_HIGH_LEVEL();
vDelayMs( 1000 );
while ( count < 10 )
{
if( bEsp8266Command ( "AT", "OK", NULL, 500 ) ) return;
vEsp8266Rst();
++ count;
}
}
/**
* @brief bEsp8266NetModeChoose
* @note 选择ESP8266模块的工作模式,该函数被外部调用。
* @param xMode工作模式
* @retval 1选择成功
* @retval 0选择失败
*/
bool bEsp8266NetModeChoose ( eNetMode_t xMode )
{
switch ( xMode )
{
case STA:
return bEsp8266Command ( "AT+CWMODE=1", "OK", "no change", 2500 );
case AP:
return bEsp8266Command ( "AT+CWMODE=2", "OK", "no change", 2500 );
case STA_AP:
return bEsp8266Command ( "AT+CWMODE=3", "OK", "no change", 2500 );
default:
return false;
}
}
/**
* @brief bEsp8266JoinAp
* @note ESP8266模块连接外部WiFi该函数被外部调用。
* @param pcSsidWiFi名称字符串
* @param pcPassWordWiFi密码字符串
* @retval 1连接成功
* @retval 0连接失败
*/
bool bEsp8266JoinAp ( char * pcSsid, char * pcPassWord )
{
char cCmd [120];
sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pcSsid, pcPassWord );
return bEsp8266Command ( cCmd, "OK", NULL, 5000 );
}
/**
* @brief bEsp8266MqttInit
* @note ESP8266模块MQTT初始化该函数被外部调用。
* @param pcMqttUserNameMQTT用户名字符串
* @param pcMqttPasswordMQTT密码字符串
* @param pcMqttClientIdMQTT客户端ID字符串
* @param pcMqttServerIpMQTT服务器IP地址字符串
* @param usMqttServerPortMQTT服务器端口号
* @retval 1初始化成功
* @retval 0初始化失败
*/
bool bEsp8266MqttInit ( char * pcMqttUserName, char * pcMqttPassword, char * pcMqttClientId,
char * pcMqttServerIp, uint16_t usMqttServerPort,
char * pcMqttSubscribeTopic )
{
char cCmd[512] = {0};
/* 1. 配置MQTT用户信息 */
snprintf(cCmd, sizeof(cCmd), "AT+MQTTUSERCFG=0,1,\"NULL\",\"%s\",\"%s\",0,0,\"\"",
pcMqttUserName, pcMqttPassword);
if (!bEsp8266Command(cCmd, "OK", NULL, 2000))
return false;
/* 2. 设置客户端ID */
memset(cCmd, 0, sizeof(cCmd));
snprintf(cCmd, sizeof(cCmd), "AT+MQTTCLIENTID=0,\"%s\"", pcMqttClientId);
if (!bEsp8266Command(cCmd, "OK", NULL, 2000))
return false;
/* 3. 连接到MQTT服务器 */
memset(cCmd, 0, sizeof(cCmd));
snprintf(cCmd, sizeof(cCmd), "AT+MQTTCONN=0,\"%s\",%u,1",
pcMqttServerIp, usMqttServerPort);
if (!bEsp8266Command(cCmd, "OK", NULL, 5000) && !bEsp8266Command(cCmd, "+MQTTCONN", NULL, 5000))
return false;
/* 4. 订阅主题 */
memset(cCmd, 0, sizeof(cCmd));
snprintf(cCmd, sizeof(cCmd), "AT+MQTTSUB=0,\"%s\",1", pcMqttSubscribeTopic);
if (!bEsp8266Command(cCmd, "OK", NULL, 2000))
return false;
return true;
}
/**
* @brief bEsp8266BuildAp
* @note ESP8266模块创建AP热点该函数被外部调用。
* @param pcSsidAP名称字符串
* @param pcPassWordAP密码字符串
* @param xPsdModeAP加密方式
* @retval 1创建成功
* @retval 0创建失败
*/
bool bEsp8266BuildAp ( char * pcSsid, char * pcPassWord, eApPsdMode_t xPsdMode )
{
char cCmd [120];
sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pcSsid, pcPassWord, xPsdMode );
return bEsp8266Command ( cCmd, "OK", 0, 1000 );
}
/**
* @brief bEsp8266EnableMultipleId
* @note ESP8266模块使能/禁止多连接,该函数被外部调用。
* @param xEnumEnUnvarnishTxENABLE使能多连接DISABLE禁止多连接
* @retval 1操作成功
* @retval 0操作失败
*/
bool bEsp8266EnableMultipleId ( FunctionalState xEnumEnUnvarnishTx )
{
return bEsp8266Command ( "AT+CIPMUX=%d", "OK", 0, 500 );
}
/**
* @brief bEsp8266LinkServer
* @note ESP8266模块连接服务器该函数被外部调用。
* @param xNetProtocol连接协议类型
* @param pcIp服务器IP地址字符串
* @param pcComNum服务器端口号字符串
* @param xId连接ID号
* @retval 1连接成功
* @retval 0连接失败
*/
bool bEsp8266LinkServer ( eNetPro_t xNetProtocol, char * pcIp, char * pcComNum, eIdNo_t xId)
{
char cStr [100] = { 0 }, cCmd [120];
switch ( xNetProtocol )
{
case enumTCP:
sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", pcIp, pcComNum );
break;
case enumUDP:
sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", pcIp, pcComNum );
break;
default:
break;
}
if ( xId < 5 )
sprintf ( cCmd, "AT+CIPSTART=%d,%s", xId, cStr);
else
sprintf ( cCmd, "AT+CIPSTART=%s", cStr );
return bEsp8266Command ( cCmd, "OK", "ALREADY CONNECT", 4000 );
}
/**
* @brief bEsp8266StartOrShutServer
* @note ESP8266模块启动/关闭服务器,该函数被外部调用。
* @param xModeENABLE启动服务器DISABLE关闭服务器
* @param pcPortNum服务器端口号字符串
* @param pcTimeOver服务器超时时间字符串
* @retval 1操作成功
* @retval 0操作失败
*/
bool bEsp8266StartOrShutServer ( FunctionalState xMode, char * pcPortNum, char * pcTimeOver )
{
char cCmd1 [120], cCmd2 [120];
if ( xMode )
{
sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pcPortNum );
sprintf ( cCmd2, "AT+CIPSTO=%s", pcTimeOver );
return ( bEsp8266Command ( cCmd1, "OK", 0, 500 ) &&
bEsp8266Command ( cCmd2, "OK", 0, 500 ) );
}
else
{
sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pcPortNum );
return bEsp8266Command ( cCmd1, "OK", 0, 500 );
}
}
/**
* @brief ucEsp8266GetLinkStatus
* @note 获取ESP8266的连接状态该函数被外部调用。
* @param 无
* @retval 0未连接
* @retval 2已连接至AP但未连接服务器
* @retval 3已连接至AP且已连接服务器
* @retval 4连接断开
*/
uint8_t ucEsp8266GetLinkStatus ( void )
{
if ( bEsp8266Command ( "AT+CIPSTATUS", "OK", 0, 500 ) )
{
if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "STATUS:2\r\n" ) )
return 2;
else if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "STATUS:3\r\n" ) )
return 3;
else if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "STATUS:4\r\n" ) )
return 4;
}
return 0;
}
/**
* @brief ucEsp8266GetIdLinkStatus
* @note 获取ESP8266的各ID连接状态该函数被外部调用。
* @param 无
* @retval 各ID连接状态位0~4分别表示ID0~ID4的连接状态1表示已连接0表示未连接
*/
uint8_t ucEsp8266GetIdLinkStatus ( void )
{
uint8_t ucIdLinkStatus = 0x00;
if ( bEsp8266Command ( "AT+CIPSTATUS", "OK", 0, 500 ) )
{
if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "+CIPSTATUS:0," ) )
ucIdLinkStatus |= 0x01;
else
ucIdLinkStatus &= ~ 0x01;
if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "+CIPSTATUS:1," ) )
ucIdLinkStatus |= 0x02;
else
ucIdLinkStatus &= ~ 0x02;
if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "+CIPSTATUS:2," ) )
ucIdLinkStatus |= 0x04;
else
ucIdLinkStatus &= ~ 0x04;
if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "+CIPSTATUS:3," ) )
ucIdLinkStatus |= 0x08;
else
ucIdLinkStatus &= ~ 0x08;
if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "+CIPSTATUS:4," ) )
ucIdLinkStatus |= 0x10;
else
ucIdLinkStatus &= ~ 0x10;
}
return ucIdLinkStatus;
}
/**
* @brief ucEsp8266InquireApIp
* @note 获取ESP8266的AP IP该函数被外部调用。
* @param pcApIp存放 AP IP 的数组的首地址
* @param ucArrayLength存放 AP IP 的数组的长度
* @retval 0获取失败
* @retval 1获取成功
*/
uint8_t ucEsp8266InquireApIp ( char * pcApIp, uint8_t ucArrayLength )
{
char uc;
char * pCh;
bEsp8266Command ( "AT+CIFSR", "OK", 0, 500 );
pCh = strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "APIP,\"" );
if ( pCh )
pCh += 6;
else
return 0;
for ( uc = 0; uc < ucArrayLength; uc ++ )
{
pcApIp [ uc ] = * ( pCh + uc);
if ( pcApIp [ uc ] == '\"' )
{
pcApIp [ uc ] = '\0';
break;
}
}
return 1;
}
/**
* @brief bEsp8266UnvarnishSend
* @note 配置ESP8266模块进入透传模式该函数被外部调用。
* @param 无
* @retval 1配置成功
* @retval 0配置失败
*/
bool bEsp8266UnvarnishSend ( void )
{
return bEsp8266Command ( "AT+CIPMODE=1", "OK", 0, 500 );
}
/**
* @brief vEsp8266ExitUnvarnishSend
* @note 使ESP8266模块退出透传模式该函数被外部调用。
* @param 无
* @retval 无
*/
void vEsp8266ExitUnvarnishSend ( void )
{
vDelayMs( 1000 );
vUsartPrintf ( USART2, "+++" );
vDelayMs( 500 );
}
/**
* @brief bEsp8266SendString
* @note ESP8266模块发送字符串该函数被外部调用。
* @param xEnumEnUnvarnishTx声明是否已使能了透传模式
* @param pcStr待发送的字符串首地址
* @param ulStrLength待发送的字符串长度
* @param ucId连接ID号
* @retval 1发送成功
* @retval 0发送失败
*/
bool bEsp8266SendString ( FunctionalState xEnumEnUnvarnishTx, char * pcStr, uint32_t ulStrLength, eIdNo_t xId )
{
char cStr [20];
bool bRet = false;
if ( xEnumEnUnvarnishTx )
{
vUsartPrintf ( USART2, "%s", pcStr );
bRet = true;
}
else
{
if ( xId < 5 )
sprintf ( cStr, "AT+CIPSEND=%d,%d", xId, ulStrLength + 2 );
else
sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );
bEsp8266Command ( cStr, "> ", 0, 1000 );
bRet = bEsp8266Command ( pcStr, "SEND OK", 0, 1000 );
}
return bRet;
}
/**
* @brief pcEsp8266ReceiveString
* @note ESP8266模块接收字符串该函数被外部调用。
* @param xEnumEnUnvarnishTx声明是否已使能了透传模式
* @retval 接收到的字符串首地址未接收到返回0
*/
char * pcEsp8266ReceiveString ( FunctionalState xEnumEnUnvarnishTx )
{
char * pRecStr = 0;
xSerialFrameRecord .Bits_t .usFrameLength = 0;
xSerialFrameRecord .Bits_t .usFrameFinishFlag = 0;
while ( ! xSerialFrameRecord .Bits_t .usFrameFinishFlag );
xSerialFrameRecord .cSerialReceivedBuffer [ xSerialFrameRecord .Bits_t .usFrameLength ] = '\0';
if ( xEnumEnUnvarnishTx )
pRecStr = xSerialFrameRecord .cSerialReceivedBuffer;
else
{
if ( strstr ( xSerialFrameRecord .cSerialReceivedBuffer, "+IPD" ) )
pRecStr = xSerialFrameRecord .cSerialReceivedBuffer;
}
return pRecStr;
}