STM32+ESP8266+TFTLCD实现天气预报显示
前言项目思路效果演示心知天气API硬件部分材料硬件连接
软件部分ESP8266AT固件指令页面布局JSON数据解析时间数据解析与计时
遇到的问题
前言
最近发现自己学的东西都太杂了,真正开始找工作,才意识到自己应该精通某样技能。认真开始使用STM32做小项目后才发现自己有好多东西不知道,感觉自己是真的菜。虽然这也不是新的技术,但是真正要做到精通,其中道理要研究的东西还是蛮多的。并且好久没有更新文章了,最近在知乎上看到别人使用STM32做了一个实时疫情的显示屏,想着自己也动手做一个显示天气预报的装置。工程源码见文末。
项目思路
STM32与ESP8266通过串口连接,STM32通过串口向ESP8266发送指令:连接AP,创建TCP连接,创建SSL连接,发送GET请求获取天气数据,STM32解析JSON数据,将天气数据显示在TFTLCD屏幕上。屏幕可显示最近三天的天气情况和显示实时24小时天气(最多显示至第12小时),使用按键来切换,显示不同的天气页面。
效果演示
系统启动默认显示当前时间之后三个小时的天气信息 按下切换按钮显示下三个小时的天气信息 按下切换按钮显示逐日天气信息 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201009181130185.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2MjI1NjIy,size_16,color_FFFFFF,t_70#pic_center)
心知天气API
我使用心知天气获取天气信息,由于STM32使用cJSON需要消耗大量内存,如果获取的数据量过大会导致JSON数据解析失败的结果,而这个API可以根据自己的要求获取一定数量的数据,不仅可以获取24小时逐小时天气数据,还可以获取逐日天气数据。 逐日天气预报参数表 24小时逐小时天气预报 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2020100922563086.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2MjI1NjIy,size_16,color_FFFFFF,t_70#pic_center)
硬件部分
材料
STM32F103ZET6开发板,ESP8266-01,2.8寸TFTLCD屏幕。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201009182003185.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2MjI1NjIy,size_16,color_FFFFFF,t_70#pic_center) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201019105320674.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2MjI1NjIy,size_16,color_FFFFFF,t_70#pic_center)
硬件连接
ESP8266-RX->PB10 ESP8266-TX->PB11 ESP8266-CH_PD->3V3 ESP8266-3V3->3V3 ESP8266-GND->GND![在这里插入图片描述](https://img-blog.csdnimg.cn/20201010162127654.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2MjI1NjIy,size_16,color_FFFFFF,t_70#pic_center)
软件部分
ESP8266AT固件指令
连接ap指令:AT+CWJAP=“SSID”,“password”创建TCP连接:AT+CIPSTART=“TCP”,“www.domain.com”,80创建SSL连接:AT+CIPSTART=“SSL”,“www.domain.com”,443设置为透传模式:AT+CIPMODE=1发送数据:AT+CIPSEND直接向串口发送GET请求退出透传模式: +++ AT+CIPMODE=0断开TCP连接:AT+CIPCLOSE断开SSL连接:AT+CIPCLOSE
页面布局
/*
显示实时天气
*/
void showRTweather(){
char path[15];
u8 i,x0=20,x1=50;
LCD_Fill(0,22,320,240,WHITE);
for(i=0;ivaluestring,strlen(item->valuestring));
printf("temperature:%s",weather.temperature[i]);
item=cJSON_GetObjectItem(result0,"high");
memcpy(RDweather.high[i],item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(result0,"low");
memcpy(RDweather.low[i],item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(result0,"humidity");
memcpy(RDweather.humidity[i],item->valuestring,strlen(item->valuestring));
printf("humidity:%s",weather.humidity[i]);
item=cJSON_GetObjectItem(result0,"wind_speed");
printf("windspeed:%s\r\n",item->valuestring); //
memcpy(RDweather.wind_speed[i],item->valuestring,strlen(item->valuestring));
printf("wind_speed:%s\r\n",weather.wind_speed[i]); //wind_speed:傀?
}
}
}else{
error=1;
printf("Error before: [%s]\n",cJSON_GetErrorPtr());
}
cJSON_Delete(root); //一定要释放JSON对象
USART_RX_STA3 = 0;
Usart_SendString(USART3,"AT+CIPCLOSE\r\n"); //关闭连接
return error;
}
时间数据解析与计时
/*
将u8字符串数字转换成u16类型数字
*/
u16 u8Tou16(char *str){
u8 i;
u16 num=0;
u8 len=strlen(str);
for(i=len;i>0;i--){
num+=(*str-'0')*pow(10,i-1); //pow次方函数
str++;
}
return num;
}
/*
转换成字符串时间
*/
void Parse_Time(char *str){
u8 i=0,j=0,k=0;
char time[6][5]={"","","","","",""};
//time=malloc();
u8 len=strlen(str);
for(i=0;ivalueint;
if(code==200){
result_arr=cJSON_GetObjectItem(root,"newslist");
if(result_arr->type==cJSON_Array){
result=cJSON_GetObjectItem(result_arr,0);
TimeStr=(const char *)cJSON_GetObjectItem(result,"strtime")->valuestring;
Localtime.weeknum=(u8 *)cJSON_GetObjectItem(result,"weeknum")->valuestring;
}
}else{ error=1;}
}else{
error=3;
printf("JSON format error:%s\r\n", cJSON_GetErrorPtr()); //堆尺寸太小,导致转换失败
}
strcpy(time,TimeStr);
cJSON_Delete(root);
Parse_Time(time);
TIM_Cmd(TIM2,ENABLE); //获取到时间后,启动TIM2
}else{ error=2;}
USART_RX_STA3 = 0;
Usart_SendString(USART3,"AT+CIPCLOSEMODE=0\r\n"); //关闭连接
delay_ms(500);
Usart_SendString(USART3,"AT+CIPCLOSE=0\r\n");
return error;
}
void TimeRun(){
if(Localtime.sec |