#include "esp8266.h" #include "usart.h" #include "delay.h" #include #include "usart.h" struct STRUCT_USART_Fram ESP8266_Fram_Record_Struct = { 0 }; //定义了一个数据帧结构体 void ESP8266_Init(u32 bound) { USART4_Configuration(bound); } //对ESP8266模块发送AT指令 // cmd 待发送的指令 // ack1,ack2;期待的响应,为NULL表不需响应,两者为或逻辑关系 // time 等待响应时间 //返回1发送成功, 0失败 bool ESP8266_Send_AT_Cmd(char *cmd,char *ack1,char *ack2,u32 time) { //ESP8266_Send_AT_Cmd ( cStr, "> ", 0, 1000 ); u8 i=0; Usart4_ReceiveBuff_Clear(); if(strstr(ack2,"1")) u4_printf("%s",cmd); else u4_printf("%s\r\n",cmd); //UART_PutStr(UART4,cmd); //UART_PutStr(UART4,"\r\n"); if(ack1==0&&ack2==0) //不需要接收数据 { return true; } delay_ms(time); //延时 delay_ms(10); ESP8266_Fram_Record_Struct.Data_RX_BUF[ESP8266_Fram_Record_Struct.InfBit.FramLength ] = '\0'; if(ack1!=0&&ack2!=0) { i= ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack1 ) || ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack2 ) ); return i; } else if( ack1 != 0 ) //strstr(s1,s2);检测s2是否为s1的一部分,是返回该位置,否则返回false,它强制转换为bool类型了 { i= ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack1 ) || ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack2 ) ); return i; } else i= ( ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack1 ) || ( bool ) strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, ack2 ) ); return i; } //发送恢复出厂默认设置指令将模块恢复成出厂设置 void ESP8266_AT_Test(void) { u16 count=0; while(count < 100) { if(ESP8266_Send_AT_Cmd("AT+RESTORE","OK",NULL,500)) { return; } ++ count; delay_ms(100); } } //选择ESP8266的工作模式 // enumMode 模式类型 //成功返回true,失败返回false bool ESP8266_Net_Mode_Choose(ENUM_Net_ModeTypeDef enumMode) { switch ( enumMode ) { case STA: return ESP8266_Send_AT_Cmd ( "AT+CWMODE=1", "OK", "NULL", 2500 ); case AP: return ESP8266_Send_AT_Cmd ( "AT+CWMODE=2", "OK", "NULL", 2500 ); case STA_AP: return ESP8266_Send_AT_Cmd ( "AT+CWMODE=3", "OK", "NULL", 2500 ); default: return false; } } //ESP8266连接外部的WIFI //pSSID WiFi帐号 //pPassWord WiFi密码 //设置成功返回true 反之false bool ESP8266_JoinAP( char * pSSID, char * pPassWord) { char cCmd [120]; sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord ); return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 5000 ); } //ESP8266 透传使能 //enumEnUnvarnishTx 是否多连接,bool类型 //设置成功返回true,反之false bool ESP8266_Enable_MultipleId (FunctionalState enumEnUnvarnishTx ) { char cStr [20]; sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) ); return ESP8266_Send_AT_Cmd ( cStr, "OK", 0, 500 ); } //ESP8266 连接服务器 //enumE 网络类型 //ip ,服务器IP //ComNum 服务器端口 //id,连接号,确保通信不受外界干扰 //设置成功返回true,反之fasle bool ESP8266_Link_Server(ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum) { char cStr [100] = { 0 }; //cCmd [120]; switch ( enumE ) { case enumTCP: sprintf ( cStr, "\"%s\",\"%s\",%s", "TCP", ip, ComNum ); break; case enumUDP: sprintf ( cStr, "\"%s\",\"%s\",%s", "UDP", ip, ComNum ); break; default: break; } // if ( id < 5 ) // sprintf ( cCmd, "AT+CIPSTART=%d,%s", id, cStr); // else // sprintf ( cCmd, "AT+CIPSTART=%s", cStr ); return ESP8266_Send_AT_Cmd ( cStr, "OK", "NULL", 10000 ); } //配置AP参数 //设置成功返回true, 反之false //SSID:WiFi名称 PWD:密码 CHL:信道 ECN:加密方式 一般选择3 WPA2_PSK bool ESP8266_CWSAP_Set ( char * SSID, char * PWD,char CHL, char ECN ) { char cStr [100] = { 0 },cStr0 [100] = { 0 }; sprintf(cStr0,"\"%s\",\"%s\",%d,%d",SSID,PWD,CHL,ECN); sprintf ( cStr, "%s%s", "AT+CWSAP_DEF=", cStr0); if (!ESP8266_Send_AT_Cmd ( cStr, "OK", 0, 5000 )) return false; else return true; } //创建tcp服务器 //设置成功返回true, 反之false bool ESP8266_Server_Create ( char * Port, FunctionalState Dis_En ) { char cStr [100] = { 0 },cStr0 [100] = { 0 }; sprintf(cStr0,"%d,%s",Dis_En,Port); sprintf ( cStr, "%s%s", "AT+CIPSERVER=", cStr0); if (!ESP8266_Send_AT_Cmd ( cStr, "OK", 0, 5000 )) return false; else return true; } ////服务端向客户端发送数据 //void ESP8266_AP_TCPServer_SendData(char ID,char *data,u16 len) //{ // char cStr [100] = { 0 },cStr0 [100] = { 0 }; // // sprintf(cStr,"%s%d,%d","AT+CIPSEND=",ID,len); // ESP8266_Send_AT_Cmd ( cStr, 0, 0, 200 ); // UART_PutStr(USART1,data); //} //透传使能 //设置成功返回true, 反之false bool ESP8266_UnvarnishSend ( void ) { if (!ESP8266_Send_AT_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 )) return false; return ESP8266_Send_AT_Cmd( "AT+CIPSEND", "OK", ">", 500 ); } //ESP8266发送字符串 //enumEnUnvarnishTx是否使能透传模式 //pStr字符串 //ulStrLength字符串长度 //ucId 连接号 //设置成功返回true, 反之false bool ESP8266_SendString(FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, char ucId ) { char cStr [20]; bool bRet = false; if ( enumEnUnvarnishTx ) { u4_printf ( "%s", pStr ); bRet = true; } else { if ( ucId < 5 ) sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength ); else sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 ); ESP8266_Send_AT_Cmd ( cStr, "> ", 0, 200 ); bRet = ESP8266_Send_AT_Cmd ( pStr, "SEND OK", "1", 200 ); } return bRet; } //ESP8266退出透传模式 void ESP8266_ExitUnvarnishSend ( void ) { delay_ms(1000); u5_printf( "+++" ); delay_ms( 500 ); } //ESP8266 检测连接状态 //返回0:获取状态失败 //返回2:获得ip 连接了服务器 //返回3:建立连接 //返回4:失去连接 u8 ESP8266_Get_LinkStatus ( void ) { if (ESP8266_Send_AT_Cmd( "AT+CIPSTATUS", "+CIPSTATUS:0", 0, 500 ) ) { /* if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "TCP" ) ) return 2; else if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "STATUS:3\r\n" ) ) return 3; else if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "STATUS:4\r\n" ) ) return 4; 该部分用于判断WiFi是否有连接, */ if ( strstr ( ESP8266_Fram_Record_Struct .Data_RX_BUF, "+CIPSTATUS:0" ) ) return 2;//WIFI是否有连接客户端连接 } return 0; } static char *itoa( int value, char *string, int radix ) { int i, d; int flag = 0; char *ptr = string; /* This implementation only works for decimal numbers. */ if (radix != 10) { *ptr = 0; return string; } if (!value) { *ptr++ = 0x30; *ptr = 0; return string; } /* if this is a negative value insert the minus sign. */ if (value < 0) { *ptr++ = '-'; /* Make the value positive. */ value *= -1; } for (i = 10000; i > 0; i /= 10) { d = value / i; if (d || flag) { *ptr++ = (char)(d + 0x30); value -= (d * i); flag = 1; } } /* Null terminate the string. */ *ptr = 0; return string; } /* NCL_Itoa */ void USART_printf ( USART_TypeDef * USARTx, char * Data, ... ) { const char *s; int d; char buf[16]; va_list ap; va_start(ap, Data); while ( * Data != 0 ) // 判断数据是否到达结束符 { if ( * Data == 0x5c ) //'\' { switch ( *++Data ) { case 'r': //回车符 USART_SendData(USARTx, 0x0d); Data ++; break; case 'n': //换行符 USART_SendData(USARTx, 0x0a); Data ++; break; default: Data ++; break; } } else if ( * Data == '%') { switch ( *++Data ) { case 's': //字符串 s = va_arg(ap, const char *); for ( ; *s; s++) { USART_SendData(USARTx,*s); while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET ); } Data++; break; case 'd': //十进制 d = va_arg(ap, int); itoa(d, buf, 10); for (s = buf; *s; s++) { USART_SendData(USARTx,*s); while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET ); } Data++; break; default: Data++; break; } } else USART_SendData(USARTx, *Data++); while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET ); } } //下面为ESP8266MQTT功能指令 /* *MQTT配置用户属性 *LinkID 连接ID,目前只支持0 *scheme 连接方式,这里选择MQTT over TCP,这里设置为1 *client_id MQTTclientID 用于标志client身份 *username 用于登录 MQTT 服务器 的 username *password 用于登录 MQTT 服务器 的 password *cert_key_ID 证书 ID, 目前支持一套 cert 证书, 参数为 0 *CA_ID 目前支持一套 CA 证书, 参数为 0 *path 资源路径,这里设置为"" *设置成功返回true 反之false */ bool ESP8266_MQTTUSERCFG( char * pClient_Id, char * pUserName,char * PassWord) { char cCmd [120]; sprintf ( cCmd, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"", pClient_Id,pUserName,PassWord ); return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 500 ); } /* *连接指定的MQTT服务器 *LinkID 连接ID,目前只支持0 *IP:MQTT服务器上对应的IP地址 *ComNum MQTT服务器上对应的端口号,一般为1883 *设置成功返回true 反之false */ bool ESP8266_MQTTCONN( char * Ip, int Num) { char cCmd [120]; sprintf ( cCmd,"AT+MQTTCONN=0,\"%s\",%d,0", Ip,Num); return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 500 ); } /* *订阅指定连接的 MQTT 主题, 可重复多次订阅不同 topic *LinkID 连接ID,目前只支持0 *Topic 订阅的主题名字,这里设置为Topic *Qos值:一般为0,这里设置为1 *设置成功返回true 反之false */ bool ESP8266_MQTTSUB(char * Topic) { char cCmd [120]; sprintf ( cCmd, "AT+MQTTSUB=0,\"%s\",1",Topic ); return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 500 ); } /* *在LinkID上通过 topic 发布数据 data, 其中 data 为字符串消息 *LinkID 连接ID,目前只支持0 *Topic 订阅的主题名字,这里设置为Topic *data:字符串信息 *设置成功返回true 反之false */ bool ESP8266_MQTTPUB( char * Topic,char *temp) { char cCmd [120]; sprintf (cCmd, "AT+MQTTPUB=0,\"%s\",\"%s\",1,0", Topic ,temp); return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 1000 ); } /* *关闭 MQTT Client 为 LinkID 的连接, 并释放内部占用的资源 *LinkID 连接ID,目前只支持0 *Topic 订阅的主题名字,这里设置为Topic *data:字符串信息 *设置成功返回true 反之false */ bool ESP8266_MQTTCLEAN(void) { char cCmd [120]; sprintf ( cCmd, "AT+MQTTCLEAN=0"); return ESP8266_Send_AT_Cmd( cCmd, "OK", NULL, 500 ); } //ESP8266发送字符串 //enumEnUnvarnishTx是否使能透传模式 //pStr字符串 //ulStrLength字符串长度 //ucId 连接号 //设置成功返回true, 反之false bool MQTT_SendString(char * pTopic,char *temp2) { bool bRet = false; ESP8266_MQTTPUB(pTopic,temp2); delay_ms(1000); bRet = true; return bRet; } void ESP8266_Fram_Record_Struct_Clear(void) { memset(ESP8266_Fram_Record_Struct.Data_RX_BUF,0,RX_BUF_MAX_LEN); ESP8266_Fram_Record_Struct.InfBit.FramFinishFlag=0; ESP8266_Fram_Record_Struct.InfBit.FramLength=0; }