串口初始化代码就不分享了,大家都有的,我做的是回环测试,也就是用了两个串口,一个串口给ESP8266发送指令,另一个接收他发回来的数据,如果需要代码最后会给
先分享一下代码,大概讲解一下(从简)
建立连接
//Server:服务器类型 IP:服务器地址 PORT:端口号
void ESP_CIPSTART(const char* Server,const char* IP,const char* PORT)
{
char temp[40] = {0};
uint8_t k = 0;
sprintf(temp,"AT+CIPSTART=\"%s\",\"%s\",%s\r\n",Server,IP,PORT);
while(temp[k]!='\0')
{
USART_SendByte(ESP_USARTx,temp[k]);
while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
k++;
}
while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) ==RESET);
}
CIPSTART不懂,那就去先了解AT指令,附上别人的分享
https://blog.csdn.net/lalala098/article/details/81240806
检测响应
//rsp:你要检测的响应字符串,waitTimes_ms:超时退出
uint8_t ESP_Check_Respond(const char* rsp,u16 waitTimes_ms)
{
while((strstr(ESP_Usart_RecBuf,rsp) == NULL)&&(--waitTimes_ms))
{
delay_ms(1);
}
if(waitTimes_ms) return SUCCESS;
else return ERROR;
}
strstr是标准库string.h的,include
发送命令字符串
//Enter是否加入换行 1就加入
void ESP8266_SendATcmd(const char* AT_cmd,u8 Enter)
{
char CMDBuf[20] = {0};
uint8_t k = 0;
strcat(CMDBuf,AT_cmd);
if(Enter)
{
strcat(CMDBuf,"\r\n"); //加入换行
}
while(*(CMDBuf+k)!='\0')
{
USART_SendByte(ESP_USARTx,*(CMDBuf+k));
while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
k++;
}
while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) ==RESET);
}
void ESP_SendString(const char* str)
{
uint8_t k = 0;
do
{
USART_SendByte(ESP_USARTx,str[k]);
while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
k++;
}while(*(str+k)!='\0');
while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) == RESET);
}
发送AT指令、发送字符串(向ESP8266)
基于上面两个函数,我定义了一些宏
#define OPEN_PTMODE() ESP8266_SendATcmd("AT+CIPMODE=1",1) //打开透传模式,要记得关
#define CLOSE_PTMODE() ESP_SendString("+++") //退出透传模式(重要!不然会一直接收数据)
#define CMD_CIPCLOSE() ESP_SendString("AT+CIPCLOSE\r\n") //退出IP
#define CMD_AT() ESP8266_SendATcmd(AT,CMD_ENTER)
#define CMD_RST() ESP8266_SendATcmd(AT_RST,CMD_ENTER)
获取时间
NETWORK_TIME myTime;
//获取网络时间
uint8_t Get_NetWork_Time(void)
{
uint8_t GetFlag = 0;
ESP_CIPSTART("TCP","www.beijing-time.org","80");
delay_ms(50);
if(ESP_Check_Respond("CONNECT",400) == 0)
{
ESP_ERROR("ERROR0");
return 0;
}
//delay_ms(1000);
OPEN_PTMODE(); //开透传
delay_ms(50);
if(ESP_Check_Respond("OK",400) == 0)
{
CLOSE_PTMODE();
ESP_ERROR("ERROR1");
return 0;
}
ESP8266_SendATcmd("AT+CIPSEND",1);
delay_ms(50);
if(ESP_Check_Respond("OK",400) == 0)
{
CLOSE_PTMODE();
ESP_ERROR("ERROR1");
return 0;
}
ESP_SendString("GET /time15.asp HTTP/1.1\r\nHost:www.beijing-time.org\r\n");
ESP_SendString("GET /time15.asp HTTP/1.1\r\nHost:www.beijing-time.org\r\n");
delay_ms(500);
if(GetNET_Time(&myTime,ESP_Usart_RecBuf)) GetFlag = 1;
//delay_ms(1000);
CLOSE_PTMODE(); //关透传
delay_ms(50);
CMD_CIPCLOSE(); //退出IP
delay_ms(50);
return GetFlag;
}
先别急着看代码,我说一下这个函数的流程是,建立连接,开启透传(记得关).发送CIPSEND指令开始进入发送模式,然后发送两次获取时间的字符串(不知道为什么要发两次),然后通过一个函数(GetNET_Time)提取时间数据,成功提取返回1,失败为0,最后关闭透传,切记),退出连接.下面分享一下怎么提取数据。
提取时间数据
先给大家看一下格式
HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 30 Jul 2020 13:58:01 GMT
Connection: close
Content-Length: 339
很明显,Date后面就是数据了,这样照葫芦画瓢,定义一个结构体来存储这些数据
typedef struct
{
char week[5];
char date[3];
char month[5];
char year[6];
char hours[4];
char minute[4];
char seconds[4];
} NETWORK_TIME;
上代码
uint8_t GetNET_Time(NETWORK_TIME* time,char *Timestr)
{
char* pbuf = NULL;
pbuf = strstr(Timestr,"Date:");
if(pbuf)
{
if(sscanf(pbuf,"%*[^:]: %[^,], %[^ ] %[^ ] %[^ ] %[^:]:%[^:]:%[^ ]",
time->week,time->date,time->month,time->year,time->hours,time->minute,time->seconds))
{
return 1;
}
}
return 0;
}
sscanf在stdio.h, include进去,sscanf用法自己查
说一下过程,传入数组缓冲区数据,然后用strstr函数查找”Date:“这个字符所在位置(指针),最后传入sscanf按格式提取出年月日。。。等时间数据(字符串)。
可能有些人不懂数组缓冲区,我以前发了一篇IDLE中断,需要的可以看看,同样可以定义一个ESP用到的串口的接收缓冲。
下面来测试一下结果,分享我的测试代码
extern NETWORK_TIME myTime;
int thour;
int tmin;
int tsec;
int main()
{
/*Parameter Configuration*/
/*Init*/
delay_init(168);
USART_Config();
LED_GPIO_Config();
ESP8266_USART_Config(); //初始化ESP的串口
ESP_Idle_Receive_Config(); //初始化空闲接收中断
/*Configuration Operation*/
ESP8266_SendATcmd("AT+RST",1); //一定要复位一下,并且连上WIFI,CWMODE=1或者3
if(Get_NetWork_Time())
{
sscanf(myTime.hours,"%d",&thour);
sscanf(myTime.minute,"%d",&tmin);
sscanf(myTime.seconds,"%d",&tsec);
printf("\r\n%s %d:%d:%d",myTime.year,thour+8,tmin,tsec);
}
/*LOOP*/
while(1)
{
LED1_TOGGLE;
delay_ms(500);
}
}
我把字符串转化成整型了,其实也可以直接使用字符串,%s就行了,我转成整型是因为时间有时差,那是0度线的时间,我也不知道哪里,北京时间+8就对了(东8区?)
我的结果:
回环测试
#define ESP_USE_IDLE_RECEIVE //是否开启空闲接收中断
#define ESP_USART_REC_BUFSIZE 100
//头文件↑
static u16 ESP_Usart_Count = 0; //接收计数,在中断函数调用
char ESP_Usart_RecBuf[ESP_USART_REC_BUFSIZE];
#ifdef ESP_USE_IDLE_RECEIVE
void ESP_USARTx_IRQHandle()
{
u16 times;
if(USART_GetITStatus(ESP_USARTx,USART_IT_RXNE) != RESET)
{
ESP_Usart_RecBuf[ESP_Usart_Count] = USART_ReceiveData(ESP_USARTx);
ESP_Usart_Count++;
}
if(USART_GetITStatus(ESP_USARTx,USART_IT_IDLE) != RESET)
{
ESP_Usart_RecBuf[ESP_Usart_Count] = USART_ReceiveData(ESP_USARTx);
//ESP_Usart_Count++;
/*此处加入对接收缓冲区的操作*/
for(times = 0;times < ESP_Usart_Count;times++)
{
USART_SendByte(DEBUG_USART,ESP_Usart_RecBuf[times]);
}
ESP_Usart_Count = 0;
}
}
#endif
完