基于STM32F103与ESP8266的网络日历

基于STM32F103与ESP8266的网络日历

最近尝试用ESP8266模块实现网络日历功能,通过免费的API接口NOW-API 获取网络时间与天气,大致思路是通过ESP8266连接服务器并通过HTTP GET的方式获取所需信息,以下是串口驱动ESP8266的代码及获取Demo。


代码块

ESP8266驱动esp8266.c


#include "stm32f10x.h"

#include "esp8266.h"

#include "delay.h"
#include "usart.h"

#include <stdarg.h>
#include <string.h>
#include <stdio.h>
//这里修改WIFI名称和密码
#define ESP8266_WIFI_INFO		"AT+CWJAP=\"TP-LINK_302\",\"330022AABBCCDD\"\r\n"

#define ESP8266_TIME_INFO   "AT+CIPSTART=\"TCP\",\"api.k780.com\",80\r\n"

char get_time0[] = "GET http://api.k780.com/?app=life.time&appkey=35488&sign=5138e2ad3378313fb818787e185054ae&format=json\r\n";
//阅读API接口说明后修改下面数据中的城市代码
char get_weather0[] = "GET http://api.k780.com/?app=weather.today&weaid=151&appkey=35488&sign=5138e2ad3378313fb818787e185054ae&format=json\r\n";
int i;
unsigned char esp8266_buf[1024];
unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;
extern clock localTime;//时间结构体
extern weather WEA;//天气结构体

#define REV_OK		0	
#define REV_WAIT	1	

void Usart2_Init(unsigned int baud)
{

	GPIO_InitTypeDef gpioInitStruct;
	USART_InitTypeDef usartInitStruct;
	NVIC_InitTypeDef nvicInitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
	
	//PA2	TXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_2;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	//PA3	RXD
	gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	gpioInitStruct.GPIO_Pin = GPIO_Pin_3;
	gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &gpioInitStruct);
	
	usartInitStruct.USART_BaudRate = baud;
	usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		
	usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						
	usartInitStruct.USART_Parity = USART_Parity_No;									
	usartInitStruct.USART_StopBits = USART_StopBits_1;								
	usartInitStruct.USART_WordLength = USART_WordLength_8b;							
	USART_Init(USART2, &usartInitStruct);
	
	USART_Cmd(USART2, ENABLE);														
	
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);									
	
	nvicInitStruct.NVIC_IRQChannel = USART2_IRQn;
	nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
	nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	nvicInitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&nvicInitStruct);

}

void ESP8266_Clear(void)
{

	memset(esp8266_buf, 0, sizeof(esp8266_buf));
	esp8266_cnt = 0;

}

_Bool ESP8266_WaitRecive(void)
{

	if(esp8266_cnt == 0) 							
		return REV_WAIT;
		
	if(esp8266_cnt == esp8266_cntPre)			
	{
		esp8266_cnt = 0;							
			
		return REV_OK;							
	}
		
	esp8266_cntPre = esp8266_cnt;					
	
	return REV_WAIT;								

}

_Bool ESP8266_SendCmd(char *cmd, char *res)
{
	
	unsigned char timeOut = 200;

	Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
	
	while(timeOut--)
	{
		if(ESP8266_WaitRecive() == REV_OK)						
		{
			if(strstr((const char *)esp8266_buf, res) != NULL)		
			{
				ESP8266_Clear();									
				
				return 0;
			}
		}
		
		DelayXms(10);
	}
	
	return 1;

}

void ESP8266_SendData(unsigned char *data, unsigned short len)
{

	char cmdBuf[32];
	
	ESP8266_Clear();								
	sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);		
	if(!ESP8266_SendCmd(cmdBuf, ">"))				
	{
		Usart_SendString(USART2, data, len);		
	}

}

unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{

	char *ptrIPD = NULL;
	
	do
	{
		if(ESP8266_WaitRecive() == REV_OK)								
		{
			ptrIPD = strstr((char *)esp8266_buf, "IPD,");//IPD为ESP8266设备返回接收数据前的标志				
			if(ptrIPD == NULL)											
			{

			}
			else
			{
				ptrIPD = strchr(ptrIPD, ':');							
				if(ptrIPD != NULL)
				{
					ptrIPD++;
					return (unsigned char *)(ptrIPD);
				}
				else
					return NULL;
				
			}
		}
		
		DelayXms(5);													
	} while(timeOut--);
	
	return NULL;													

}

void ESP8266_Init(void)
{
	
	GPIO_InitTypeDef GPIO_Initure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

	GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Initure.GPIO_Pin = GPIO_Pin_0;					
	GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_Initure);
	
	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
	DelayXms(250);
	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
	DelayXms(500);
	
	ESP8266_Clear();
	while(ESP8266_SendCmd("AT\r\n", "OK"))
	DelayXms(500);
	
	while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
	DelayXms(500);
	
	ESP8266_Clear();
}

void ESP8266_Init_TIME(void)
{
	
	GPIO_InitTypeDef GPIO_Initure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

	//ESP8266重启
	GPIO_Initure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Initure.GPIO_Pin = GPIO_Pin_0;					
	GPIO_Initure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_Initure);
	
	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
	DelayXms(250);
	GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
	DelayXms(500);
	
	ESP8266_Clear();

	while(ESP8266_SendCmd("AT\r\n", "OK"))
	DelayXms(500);
	
	while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
	DelayXms(500);
	
	while(ESP8266_SendCmd(ESP8266_TIME_INFO, "CONNECT"))
	DelayXms(500);
	
	ESP8266_Clear();
	

}

void	ESP8266_GETTIME(char *buff,int timeOut)
{
    char *ptrIPD = NULL;
	ESP8266_Init_TIME();
	ESP8266_SendData((unsigned char *)buff, strlen(buff));	
	
		do
		{
			 //检查HTTP GET 后返回的数据是否正常
			ptrIPD = strstr((const char*)esp8266_buf, "datetime_2");

			if(ptrIPD == NULL)
			{
			
			}
      else
			{   
						localTime.month =10*(*(ptrIPD-95+109-31)-0x30)+*(ptrIPD-95+110-31)-0x30;
				     localTime.day =10*(*(ptrIPD-95+112-31)-0x30)+*(ptrIPD-95+113-31)-0x30;
				
				     for(j=0;j<15;j++)
						 {
							localTime.date[j] =*(ptrIPD-95+236-31+j);
						 }
						 
            if(strstr((char *)localTime.date, "Sun")!=NULL){localTime.dateTemp=0;}
            else if(strstr((char *)localTime.date, "Mon")!=NULL){localTime.dateTemp=1;}
						else if(strstr((char *)localTime.date, "Tue")!=NULL){localTime.dateTemp=2;}
						else if(strstr((char *)localTime.date, "Wed")!=NULL){localTime.dateTemp=3;}
						else if(strstr((char *)localTime.date, "Thu")!=NULL){localTime.dateTemp=4;}
						else if(strstr((char *)localTime.date, "Fri")!=NULL){localTime.dateTemp=5;}
						else if(strstr((char *)localTime.date, "Sat")!=NULL){localTime.dateTemp=6;}
							  
	localTime.hour =10*(*(ptrIPD-95+115-31)-0x30)+*(ptrIPD-95+116-31)-0x30;
    localTime.min =10*(*(ptrIPD-95+118-31)-0x30)+*(ptrIPD-95+119-31)-0x30;
	localTime.sec =10*(*(ptrIPD-95+121-31)-0x30)+*(ptrIPD-95+122-31)-0x30+1;//延时补偿,可自行调整
				    
      			 if(localTime.sec>=60)
						 {
							 localTime.sec=localTime.sec-60;
							 localTime.min=localTime.min+1;
							 if(localTime.min==60)
							 {
								 localTime.min=0;
								 localTime.hour++;
							 }
		
						 }
		  }
		DelayXms(10);													
	} while(timeOut--);
	//检查接收是否成功,不成功重新再来
	  if(localTime.date[0]==0x00)
		{
			ESP8266_Clear();
			ESP8266_GETTIME(get_time0,500);
		}
	
	ESP8266_Clear();
}



void	ESP8266_GETWEATHER(char *buff,int timeOut)
{
  char *IPD,*aqi,*daywea,*id,*gif= NULL;
	ESP8266_Init_TIME();
	ESP8266_SendData((unsigned char *)buff, strlen(buff));	
	
	do
	{
		  IPD = strstr((char *)esp8266_buf, "IPD,");				
			if(IPD == NULL)											
			{

			}
			else
			{
				
		  }
		
		DelayXms(1);													
	} while(timeOut--);
	
	  aqi = strstr((char *)esp8266_buf, "aqi");
				
	       if(*(aqi+8)==0x22)
					{
						WEA.aqi=10*(*(aqi+6)-0x30)+*(aqi+7)-0x30;
					}
					else if(*(aqi+8)==0x22)
					{
					  WEA.aqi=100*(*(aqi+6)-0x30)+10*(*(aqi+7)-0x30)+*(aqi+8)-0x30;
					}	
					
		daywea = strstr((char *)esp8266_buf, "weather");
					
  				for(i=0;i<32;i++)
				  {
						WEA.dayweather[i]=*(daywea+10+i);
					}
					
		id = strstr((char *)esp8266_buf, "weatid");
					
					if(*(id+10)==0x22)
					{
						WEA.weatid=(*(id+9)-0x30);
					}
					else if(*(id+10)!=0x22)
					{
					  WEA.weatid=10*(*(id+9)-0x30)+*(id+10)-0x30;
					}	
		gif = strstr((char *)esp8266_buf, "weather_iconid");		
					
					if(*(gif+18)==0x22)
					{
						WEA.weagif=(*(gif+17)-0x30);
					}
					else if(*(gif+18)!=0x22)
					{
					  WEA.weagif=10*(*(gif+17)-0x30)+*(gif+18)-0x30;
					}	
					
		  if(WEA.dayweather[0]==0x00)
		{
			ESP8266_Clear();
      ESP8266_GETWEATHER(get_weather0,500);
		}
	  ESP8266_Clear();
}
	
void USART2_IRQHandler(void)
{

	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) 
	{
		if(esp8266_cnt >= sizeof(esp8266_buf))	esp8266_cnt = 0; 
		esp8266_buf[esp8266_cnt++] = USART2->DR;
		
		USART_ClearFlag(USART2, USART_FLAG_RXNE);
	}

}

头文件esp8266.h

#ifndef ESP8266_h
#define ESP8266_h

typedef struct
{
  unsigned char sec;
  unsigned char min;
  unsigned char hour;
  unsigned char day;
  unsigned char date[4];
  unsigned char month;
  unsigned char year;
  unsigned char dateTemp;
}clock;

typedef struct
{
  u16 aqi;
  unsigned char dayweather[32];
  unsigned char weatid;
  u16 weagif;
}weather;

void Usart2_Init(unsigned int baud)£»

void esp8266_init(void);
void esp8266_get_tianqi(void);
void esp8266_get_shijian(void);
void esp8266_get_time(void);
void dispose_time_data(void);

void ESP8266_Init(void);
void ESP8266_Init_TIME(void);
void ESP8266_GETTIME(char *buff,int timeOut);
void ESP8266_GETWEATHER(char *buff,int timeOut);

void ESP8266_Clear(void);

void ESP8266_SendData(unsigned char *data, unsigned short len);

unsigned char *ESP8266_GetIPD(unsigned short timeOut);

#endif

其余的延时函数delay.c,delay.h参考我的博客基于STM32F103与MY2480-16P语音模块的时钟兼闹钟设计(第一部分)
下面是测试程序main.c

//单片机头文件
#include "stm32f10x.h"

//网络设备
#include "esp8266.h"

//硬件驱动
#include "delay.h"
#include "usart.h"

//C库
#include <string.h>
#include <stdio.h>

clock localTime;
weather WEA;

char get_time[] = "GET http://api.k780.com/?app=life.time&appkey=35488&sign=5138e2ad3378313fb818787e185054ae&format=json\r\n";
//阅读API接口说明后修改下面数据中的城市代码
char get_weather[] = "GET http://api.k780.com/?app=weather.today&weaid=151&appkey=35488&sign=5138e2ad3378313fb818787e185054ae&format=json\r\n";
u8 time[6];

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断控制器分组设置

	Delay_Init();									//systick初始化
	
	Usart2_Init(115200);							//串口2,驱动ESP8266用
		
	ESP8266_GETTIME(get_time,500);                  //获取时间
	
    ESP8266_GETWEATHER(get_weather,500);            //获取天气	
   
	DelayXms(250);
}

注意事项

  1. 对HTTP GET方式不熟悉的请先仔细阅读NOW-API的说明文档
  2. 该代码配合我的第一篇博客基于STM32F103与MY2480-16P语音模块的时钟兼闹钟设计(第一部分),可以实现完整的网络时钟功能,日后会将完整工程上传
  • 8
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值