#include "bsp_esp8266.h"
#include "common.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include "usart.h"
//#include "bsp_SysTick.h"
#include "sys.h"
#include "delay.h"
unsigned char usart2_rcv_buf[1024];
//static void ESP8266_GPIO_Config ( void );
//static void ESP8266_USART_Config ( void );
//static void ESP8266_USART_NVIC_Configuration ( void );
#define LED PBout(9)
struct STRUCT_USARTx_Fram strEsp8266_Fram_Record = { 0 };
/** ESP8266連接電腦wifi發(fā)數據
*
*
*
*/
void ESP8266Mode_inti(void)
{
SendCmd(AT, "OK", 10000); //模塊有效性檢查
SendCmd(CWMODE, "OK", 10000); //模塊工作模式
SendCmd(wifi_RST, "OK", 10000); //模塊重置
SendCmd(CIFSR, "OK", 10000); //查詢網絡信息
SendCmd(CWJAP, "OK", 10000); //配置需要連接的WIFI熱點SSID和密碼
SendCmd(CIPSTART, "OK", 10000); //TCP連接
SendCmd(CIPMODE1, "OK", 10000); //配置透傳模式
SendCmd(CIPSEND, ">", 10000); //進入透傳模式
}
/** 發(fā)送Cmd命令的函數
*
*
*
*/
void SendCmd(char* cmd, char* result, int timeOut)
{
while(1)
{
// memset(usart2_rcv_buf, 0, sizeof(usart2_rcv_buf)); //將數組所有數據清0
USART_Write((unsigned char *)cmd,strlen((const char *)cmd)); //用串口把cmd命令寫給ESP8266
delay_ms(timeOut); //延遲等待
LED=~LED;
if(ok_flag==1) //比較兩個指針里面的數據是否一樣,判斷是否有預期的結果 和預期結果相同,表示指令設置成功,跳出
{
ok_flag=0; //清空標志
break;
}
else
{
delay_ms(100);
}
}
}
/** 串口發(fā)送函數
*
*
*
*/
void USART_Write(unsigned char *cmd, int len)
{
int i;
USART_ClearFlag(USART1,USART_FLAG_TC);
for(i=0;i<len;i++)
{
USART_SendData(USART1,*cmd);
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);
cmd++;
}
}
/**
* @brief 組HTTP POST報文
* @param pkt 報文緩存指針
* @param key API_KEY定義在Main.c文件中,需要根據自己的設備修改
* @param devid 設備ID,定義在main.c文件中,需要根據自己的設備修改
* @param dsid 數據流ID
* @param val 字符串形式的數據點的值
* @retval 整個包的長度
*///組成HTTP協(xié)議數據的格式
uint32_t HTTP_PostPkt(char *pkt, char *key, char *devid, char *dsid, char *val)
{
char dataBuf[100] = {0};
char lenBuf[10] = {0};
*pkt = 0;
sprintf(dataBuf, ",;%s,%s", dsid, val); //采用分割字符串格式:type = 5
sprintf(lenBuf, "%d", strlen(dataBuf));
strcat(pkt, "POST /devices/");
strcat(pkt, devid);
strcat(pkt, "/datapoints?type=5 HTTP/1.1\r\n");
strcat(pkt, "api-key:");
strcat(pkt, key);
strcat(pkt, "\r\n");
strcat(pkt, "Host:api.heclouds.com\r\n");
strcat(pkt, "Content-Length:");
strcat(pkt, lenBuf);
strcat(pkt, "\r\n\r\n");
strcat(pkt, dataBuf);
return strlen(pkt);
}
/**
* @brief 初始化ESP8266用到的GPIO引腳
* @param 無
* @retval 無
*/
void ESP8266_GPIO_Init(void)
{
/*定義一個GPIO_InitTypeDef類型的結構體*/
GPIO_InitTypeDef GPIO_InitStructure;
/* 配置 CH_PD 引腳*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //設置推挽輸出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14; //初始化CH-DP引腳 拉高
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //設置時鐘
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_14);
}
/**
* @brief ESP8266初始化函數
* @param 無
* @retval 無
*/
void ESP8266_Init ( void )
{
ESP8266_GPIO_Init();
//SP8266_USART_Config();
macESP8266_RST_HIGH_LEVEL();
macESP8266_CH_ENABLE();
}
/**
* @brief 初始化ESP8266用到的 USART
* @param 無
* @retval 無
*/
void ESP8266_USART_Config( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* config USART clock */
macESP8266_USART_APBxClock_FUN ( macESP8266_USART_CLK, ENABLE );
macESP8266_USART_GPIO_APBxClock_FUN ( macESP8266_USART_GPIO_CLK, ENABLE );
/* USART GPIO config */
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = macESP8266_USART_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(macESP8266_USART_TX_PORT, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Pin = macESP8266_USART_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(macESP8266_USART_RX_PORT, &GPIO_InitStructure);
/* USART1 mode config */
USART_InitStructure.USART_BaudRate = macESP8266_USART_BAUD_RATE;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(macESP8266_USARTx, &USART_InitStructure);
/* 中斷配置 */
USART_ITConfig ( macESP8266_USARTx, USART_IT_RXNE, ENABLE ); //使能串口接收中斷
USART_ITConfig ( macESP8266_USARTx, USART_IT_IDLE, ENABLE ); //使能串口總線空閑中斷
ESP8266_USART_NVIC_Configuration ();
USART_Cmd(macESP8266_USARTx, ENABLE);
}
/**
* @brief 配置 ESP8266 USART 的 NVIC 中斷
* @param 無
* @retval 無
*/
void ESP8266_USART_NVIC_Configuration ( void )
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig ( macNVIC_PriorityGroup_x );
/* Enable the USART2 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = macESP8266_USART_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*
* 函數名:ESP8266_Rst
* 描述 :重啟WF-ESP8266模塊
* 輸入 :無
* 返回 : 無
* 調用 :被 ESP8266_AT_Test 調用
*/
void ESP8266_Rst ( void )
{
#if 0
ESP8266_Cmd ( "AT+RST", "OK", "ready", 2500 );
#else
macESP8266_RST_LOW_LEVEL();
delay_ms ( 500 );
macESP8266_RST_HIGH_LEVEL();
#endif
}
/*
* 函數名:ESP8266_Cmd
* 描述 :對WF-ESP8266模塊發(fā)送AT指令
* 輸入 :cmd,待發(fā)送的指令
* reply1,reply2,期待的響應,為NULL表不需響應,兩者為或邏輯關系
* waittime,等待響應的時間
* 返回 : 1,指令發(fā)送成功
* 0,指令發(fā)送失敗
* 調用 :被外部調用
*/
bool ESP8266_Cmd ( char * cmd, char * reply1, char * reply2, u32 waittime )
{
strEsp8266_Fram_Record .InfBit .FramLength = 0; //從新開始接收新的數據包
macESP8266_Usart ( "%s\r\n", cmd );
if ( ( reply1 == 0 ) && ( reply2 == 0 ) ) //不需要接收數據
return true;
delay_ms ( waittime ); //延時
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
macPC_Usart ( "%s", strEsp8266_Fram_Record .Data_RX_BUF );
if ( ( reply1 != 0 ) && ( reply2 != 0 ) )
return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) ||
( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
else if ( reply1 != 0 )
return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply1 ) );
else
return ( ( bool ) strstr ( strEsp8266_Fram_Record .Data_RX_BUF, reply2 ) );
}
/*
* 函數名:ESP8266_AT_Test
* 描述 :對WF-ESP8266模塊進行AT測試啟動
* 輸入 :無
* 返回 : 無
* 調用 :被外部調用
*/
//void ESP8266_AT_Test ( void )
//{
// macESP8266_RST_HIGH_LEVEL();
//
// Delay_ms ( 1000 );
//
// while ( ! ESP8266_Cmd ( "AT", "OK", NULL, 200 ) ) ESP8266_Rst ();
//}
void ESP8266_AT_Test ( void )
{
char count=0;
macESP8266_RST_HIGH_LEVEL();
delay_ms ( 1000 );
while ( count < 10 )
{
if( ESP8266_Cmd ( "AT", "OK", NULL, 500 ) ) return;
ESP8266_Rst();
++ count;
}
}
/*
* 函數名:ESP8266_Net_Mode_Choose
* 描述 :選擇WF-ESP8266模塊的工作模式
* 輸入 :enumMode,工作模式
* 返回 : 1,選擇成功
* 0,選擇失敗
* 調用 :被外部調用
*/
bool ESP8266_Net_Mode_Choose ( ENUM_Net_ModeTypeDef enumMode )
{
switch ( enumMode )
{
case STA:
return ESP8266_Cmd ( "AT+CWMODE=1", "OK", "no change", 2500 );
case AP:
return ESP8266_Cmd ( "AT+CWMODE=2", "OK", "no change", 2500 );
case STA_AP:
return ESP8266_Cmd ( "AT+CWMODE=3", "OK", "no change", 2500 );
default:
return false;
}
}
/*
* 函數名:ESP8266_JoinAP
* 描述 :WF-ESP8266模塊連接外部WiFi
* 輸入 :pSSID,WiFi名稱字符串
* :pPassWord,WiFi密碼字符串
* 返回 : 1,連接成功
* 0,連接失敗
* 調用 :被外部調用
*/
bool ESP8266_JoinAP ( char * pSSID, char * pPassWord )
{
char cCmd [120];
sprintf ( cCmd, "AT+CWJAP=\"%s\",\"%s\"", pSSID, pPassWord );
return ESP8266_Cmd ( cCmd, "OK", NULL, 5000 );
}
/*
* 函數名:ESP8266_BuildAP
* 描述 :WF-ESP8266模塊創(chuàng)建WiFi熱點
* 輸入 :pSSID,WiFi名稱字符串
* :pPassWord,WiFi密碼字符串
* :enunPsdMode,WiFi加密方式代號字符串
* 返回 : 1,創(chuàng)建成功
* 0,創(chuàng)建失敗
* 調用 :被外部調用
*/
bool ESP8266_BuildAP ( char * pSSID, char * pPassWord, ENUM_AP_PsdMode_TypeDef enunPsdMode )
{
char cCmd [120];
sprintf ( cCmd, "AT+CWSAP=\"%s\",\"%s\",1,%d", pSSID, pPassWord, enunPsdMode );
return ESP8266_Cmd ( cCmd, "OK", 0, 1000 );
}
/*
* 函數名:ESP8266_Enable_MultipleId
* 描述 :WF-ESP8266模塊啟動多連接
* 輸入 :enumEnUnvarnishTx,配置是否多連接
* 返回 : 1,配置成功
* 0,配置失敗
* 調用 :被外部調用
*/
bool ESP8266_Enable_MultipleId ( FunctionalState enumEnUnvarnishTx )
{
char cStr [20];
sprintf ( cStr, "AT+CIPMUX=%d", ( enumEnUnvarnishTx ? 1 : 0 ) );
return ESP8266_Cmd ( cStr, "OK", 0, 500 );
}
/*
* 函數名:ESP8266_Link_Server
* 描述 :WF-ESP8266模塊連接外部服務器
* 輸入 :enumE,網絡協(xié)議
* :ip,服務器IP字符串
* :ComNum,服務器端口字符串
* :id,模塊連接服務器的ID
* 返回 : 1,連接成功
* 0,連接失敗
* 調用 :被外部調用
*/
bool ESP8266_Link_Server ( ENUM_NetPro_TypeDef enumE, char * ip, char * ComNum, ENUM_ID_NO_TypeDef id)
{
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_Cmd ( cCmd, "OK", "ALREAY CONNECT", 4000 );
}
/*
* 函數名:ESP8266_StartOrShutServer
* 描述 :WF-ESP8266模塊開啟或關閉服務器模式
* 輸入 :enumMode,開啟/關閉
* :pPortNum,服務器端口號字符串
* :pTimeOver,服務器超時時間字符串,單位:秒
* 返回 : 1,操作成功
* 0,操作失敗
* 調用 :被外部調用
*/
bool ESP8266_StartOrShutServer ( FunctionalState enumMode, char * pPortNum, char * pTimeOver )
{
char cCmd1 [120], cCmd2 [120];
if ( enumMode )
{
sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 1, pPortNum );
sprintf ( cCmd2, "AT+CIPSTO=%s", pTimeOver );
return ( ESP8266_Cmd ( cCmd1, "OK", 0, 500 ) &&
ESP8266_Cmd ( cCmd2, "OK", 0, 500 ) );
}
else
{
sprintf ( cCmd1, "AT+CIPSERVER=%d,%s", 0, pPortNum );
return ESP8266_Cmd ( cCmd1, "OK", 0, 500 );
}
}
/*
* 函數名:ESP8266_Get_LinkStatus
* 描述 :獲取 WF-ESP8266 的連接狀態(tài),較適合單端口時使用
* 輸入 :無
* 返回 : 2,獲得ip
* 3,建立連接
* 3,失去連接
* 0,獲取狀態(tài)失敗
* 調用 :被外部調用
*/
uint8_t ESP8266_Get_LinkStatus ( void )
{
if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
{
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:2\r\n" ) )
return 2;
else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:3\r\n" ) )
return 3;
else if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "STATUS:4\r\n" ) )
return 4;
}
return 0;
}
/*
* 函數名:ESP8266_Get_IdLinkStatus
* 描述 :獲取 WF-ESP8266 的端口(Id)連接狀態(tài),較適合多端口時使用
* 輸入 :無
* 返回 : 端口(Id)的連接狀態(tài),低5位為有效位,分別對應Id5~0,某位若置1表該Id建立了連接,若被清0表該Id未建立連接
* 調用 :被外部調用
*/
uint8_t ESP8266_Get_IdLinkStatus ( void )
{
uint8_t ucIdLinkStatus = 0x00;
if ( ESP8266_Cmd ( "AT+CIPSTATUS", "OK", 0, 500 ) )
{
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:0," ) )
ucIdLinkStatus |= 0x01;
else
ucIdLinkStatus &= ~ 0x01;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:1," ) )
ucIdLinkStatus |= 0x02;
else
ucIdLinkStatus &= ~ 0x02;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:2," ) )
ucIdLinkStatus |= 0x04;
else
ucIdLinkStatus &= ~ 0x04;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:3," ) )
ucIdLinkStatus |= 0x08;
else
ucIdLinkStatus &= ~ 0x08;
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+CIPSTATUS:4," ) )
ucIdLinkStatus |= 0x10;
else
ucIdLinkStatus &= ~ 0x10;
}
return ucIdLinkStatus;
}
/*
* 函數名:ESP8266_Inquire_ApIp
* 描述 :獲取 F-ESP8266 的 AP IP
* 輸入 :pApIp,存放 AP IP 的數組的首地址
* ucArrayLength,存放 AP IP 的數組的長度
* 返回 : 0,獲取失敗
* 1,獲取成功
* 調用 :被外部調用
*/
uint8_t ESP8266_Inquire_ApIp ( char * pApIp, uint8_t ucArrayLength )
{
char uc;
char * pCh;
ESP8266_Cmd ( "AT+CIFSR", "OK", 0, 500 );
pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "APIP,\"" );
if ( pCh )
pCh += 6;
else
return 0;
for ( uc = 0; uc < ucArrayLength; uc ++ )
{
pApIp [ uc ] = * ( pCh + uc);
if ( pApIp [ uc ] == '\"' )
{
pApIp [ uc ] = '\0';
break;
}
}
return 1;
}
/*
* 函數名:ESP8266_UnvarnishSend
* 描述 :配置WF-ESP8266模塊進入透傳發(fā)送
* 輸入 :無
* 返回 : 1,配置成功
* 0,配置失敗
* 調用 :被外部調用
*/
bool ESP8266_UnvarnishSend ( void )
{
if ( ! ESP8266_Cmd ( "AT+CIPMODE=1", "OK", 0, 500 ) )
return false;
return
ESP8266_Cmd ( "AT+CIPSEND", "OK", ">", 500 );
}
/*
* 函數名:ESP8266_ExitUnvarnishSend
* 描述 :配置WF-ESP8266模塊退出透傳模式
* 輸入 :無
* 返回 : 無
* 調用 :被外部調用
*/
void ESP8266_ExitUnvarnishSend ( void )
{
delay_ms ( 1000 );
macESP8266_Usart ( "+++" );
delay_ms ( 500 );
}
/*
* 函數名:ESP8266_SendString
* 描述 :WF-ESP8266模塊發(fā)送字符串
* 輸入 :enumEnUnvarnishTx,聲明是否已使能了透傳模式
* :pStr,要發(fā)送的字符串
* :ulStrLength,要發(fā)送的字符串的字節(jié)數
* :ucId,哪個ID發(fā)送的字符串
* 返回 : 1,發(fā)送成功
* 0,發(fā)送失敗
* 調用 :被外部調用
*/
bool ESP8266_SendString ( FunctionalState enumEnUnvarnishTx, char * pStr, u32 ulStrLength, ENUM_ID_NO_TypeDef ucId )
{
char cStr [20];
bool bRet = false;
if ( enumEnUnvarnishTx )
{
macESP8266_Usart ( "%s", pStr );
bRet = true;
}
else
{
if ( ucId < 5 )
sprintf ( cStr, "AT+CIPSEND=%d,%d", ucId, ulStrLength + 2 );
else
sprintf ( cStr, "AT+CIPSEND=%d", ulStrLength + 2 );
ESP8266_Cmd ( cStr, "> ", 0, 100 );
bRet = ESP8266_Cmd ( pStr, "SEND OK", 0, 500 );
}
return bRet;
}
/*
* 函數名:ESP8266_ReceiveString
* 描述 :WF-ESP8266模塊接收字符串
* 輸入 :enumEnUnvarnishTx,聲明是否已使能了透傳模式
* 返回 : 接收到的字符串首地址
* 調用 :被外部調用
*/
char * ESP8266_ReceiveString ( FunctionalState enumEnUnvarnishTx )
{
char * pRecStr = 0;
strEsp8266_Fram_Record .InfBit .FramLength = 0;
strEsp8266_Fram_Record .InfBit .FramFinishFlag = 0;
while ( ! strEsp8266_Fram_Record .InfBit .FramFinishFlag );
strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ] = '\0';
if ( enumEnUnvarnishTx )
pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;
else
{
if ( strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "+IPD" ) )
pRecStr = strEsp8266_Fram_Record .Data_RX_BUF;
}
return pRecStr;
}
/*
* 函數名:ESP8266_CWLIF
* 描述 :查詢已接入設備的IP
* 輸入 :pStaIp,存放已接入設備的IP
* 返回 : 1,有接入設備
* 0,無接入設備
* 調用 :被外部調用
*/
uint8_t ESP8266_CWLIF ( char * pStaIp )
{
uint8_t uc, ucLen;
char * pCh, * pCh1;
ESP8266_Cmd ( "AT+CWLIF", "OK", 0, 100 );
pCh = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "," );
if ( pCh )
{
pCh1 = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "AT+CWLIF\r\r\n" ) + 11;
ucLen = pCh - pCh1;
}
else
return 0;
for ( uc = 0; uc < ucLen; uc ++ )
pStaIp [ uc ] = * ( pCh1 + uc);
pStaIp [ ucLen ] = '\0';
return 1;
}
/*
* 函數名:ESP8266_CIPAP
* 描述 :設置模塊的 AP IP
* 輸入 :pApIp,模塊的 AP IP
* 返回 : 1,設置成功
* 0,設置失敗
* 調用 :被外部調用
*/
uint8_t ESP8266_CIPAP ( char * pApIp )
{
char cCmd [ 30 ];
sprintf ( cCmd, "AT+CIPAP=\"%s\"", pApIp );
if ( ESP8266_Cmd ( cCmd, "OK", 0, 5000 ) )
return 1;
else
return 0;
}
全部資料51hei下載地址:
STM32Wifi模塊與OneNetHTTP上傳數據.7z
(219.23 KB, 下載次數: 89)
2019-9-22 15:50 上傳
點擊文件名下載附件
|