全套代码已经开源,可以通过CSDN资源链接获取
文中有基本代码讲解
文章目录
一、需要的模块
1.C8T6
采用c8t6作为主控,搭载各种功能以及屏幕。
问题在于由于最小系统板内存小,后期添加功能不方便(内存小已经阉割了很多功能了,只有小部分字库和基础图片)
2.esp32
在这里esp32主要用来联网获取实时天气,时间,地点等。天气获取主要通过心知天气,时间日期通过阿里云数据。
3. 1.44寸TFT彩色屏幕
主要显示界面,显示天气时间等信息。
4. 分光棱镜
可以模拟出全息投影的感觉,帅到爆! ! !
二、准备工作
1.注册心知天气获取自己的API
心知天气官网链接:https://www.seniverse.com/
注册自己的控制台,并取得私钥,用来获取数据包。
点击【我的产品】
如图为【私钥】需要在Arduino的代码中修改。
2.了解合成cJSON数据包【让心知天气拥有时间数据】
- 获取天气数据
运行后esp32串口会下发一个心知天气的数据包:
{"results":[{"location":{"id":"私钥","name":"地点","country":"CN","path":"---","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"now":{"text":"Overcast","code":"9","temperature":"19"},"last_update":"2022-07-18T10:40:06+08:00"}]}
该处使用CSDN的cJSON工具解析数据。
代码如下(示例):
{
"results": [
{
"location": {
"id": "私钥",
"name": "地点",
"country": "CN",
"path": "---",
"timezone": "Asia/Shanghai",
"timezone_offset": "+08:00"
},
"now": {
"text": "Sunny",
"code": "0",
"temperature": "29"
},
"last_update": "2022-08-01T16:40:06+08:00"
}
]
}
如上图就是一个完整的数据包结构了,我们会在32中对数据进行解析保存,达到分级、分块调用的目的。
由于心知天气免费版只提供了基础的天气数据,没有时间日期等信息,所以我又使用了阿里云的数据,并把两个数据进行整合,合成新的数据包。
- 获取时间数据【合成数据包】
阿里云下发的数据不满足HTTP数据包的形式,所以曲线救国,我在代码中合成了新的数据包,
并把所以时间日期数据单独放在字符串中。
int Year,Mon,Day,Hour,Min,Wday;
struct tm timeInfo; //声明一个结构体
DynamicJsonDocument dat(1024);//建立一个新的数据包
//将时间数据对应在字符串中,方便合成新的cJSON数据包
const String MONTH_NAMES[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; //月份
const String DAY_NAMES[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
"21", "22", "23", "24", "25", "26", "27", "28", "29", "30","31"}; //日
const String HOUR_NAMES[] = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10",
"11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
"21", "22", "23", "24"};//时
const String MIN_NAMES[] = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10",
"11", "12", "13","14", "15", "16", "17", "18", "19", "20",
"21", "22", "23", "24", "25", "26", "27", "28", "29", "30",
"31", "32", "33", "34", "35", "36", "37", "38", "39", "40",
"41", "42", "43", "44", "45", "46", "47", "48", "49", "50",
"51", "52", "53", "54", "55", "56", "57", "58", "59", "60"}; //分
const String WDAY_NAMES[] = {"Sun.", "Mon.", "Tues.", "Wed.", "Thur.", "Fri.", "Sat."}; //星期
//location 心知天气的【location】数据
dat["results"][0]["location"]["id"] = doc["results"][0]["location"]["id"].as<String>();
dat["results"][0]["location"]["name"] = doc["results"][0]["location"]["name"].as<String>();
dat["results"][0]["location"]["country"] = doc["results"][0]["location"]["country"].as<String>();
dat["results"][0]["location"]["path"] = doc["results"][0]["location"]["path"].as<String>();
dat["results"][0]["location"]["timezone"] = doc["results"][0]["location"]["timezone"].as<String>();
dat["results"][0]["location"]["timezone_offset"] = doc["results"][0]["location"]["timezone_offset"].as<String>();
//now 心知天气【now】数据和时间结合 放在新的【now】结构体中
dat["results"][0]["now"]["text"] = doc["results"][0]["now"]["text"].as<String>();
dat["results"][0]["now"]["code"] = doc["results"][0]["now"]["code"].as<String>();
dat["results"][0]["now"]["temperature"] = doc["results"][0]["now"]["temperature"].as<String>();
dat["results"][0]["now"]["mon"]=MONTH_NAMES[timeInfo.tm_mon ].c_str();
dat["results"][0]["now"]["day"]=DAY_NAMES[timeInfo.tm_mday].c_str();
dat["results"][0]["now"]["hour"]=HOUR_NAMES[timeInfo.tm_hour].c_str();
dat["results"][0]["now"]["min"]=MIN_NAMES[timeInfo.tm_min].c_str();
dat["results"][0]["now"]["wday"]=WDAY_NAMES[timeInfo.tm_wday].c_str();
dat["results"][0]["last_update"]= doc["results"][0]["last_update"].as<String>();
char json_string[1024];
serializeJson(dat,json_string);//把所有数据放在新的【dat】中
Serial.println(json_string);//输出
于是我们得到了新的数据包,包含了实时时间和日期信息
{"results":[{
"location":{"id":"私钥","name":"地点","country":"CN","path":"---",
"timezone":"Asia/Shanghai","timezone_offset":"+08:00"},
"now":{"text":"Sunny","code":"0","temperature":"27","mon":"Aug","day":"2","hour":"18","min":"47","wday":"Tues."},"last_update":"2022-08-02T18:40:06+08:00"}]}
再次使用CSDN的cJSON工具解析数据。
代码如下(示例):
{
"results": [
{
"location": {
"id": "私钥",
"name": "地点",
"country": "CN",
"path": "---",
"timezone": "Asia/Shanghai",
"timezone_offset": "+08:00"
},
"now": {
"text": "Sunny",
"code": "0",
"temperature": "27",
"mon": "Aug",
"day": "2",
"hour": "18",
"min": "47",
"wday": "Tues."
},
"last_update": "2022-08-02T18:40:06+08:00"
}
]
}
可以看到现在的数据包要远远大于之前,拥有了时间和日期数据。
3.使用stm32解析数据包
- 解析cJSON数据
#include "cJSON.h"
//对应子对象1结构体--Location
typedef struct
{
char id[32];
char name[32];
char country[32];
char path[64];
char timezone[32];
char timezone_offset[32];
}Location;
//对应子对象2结构体--Now
typedef struct
{
char text[32];
char code[32];
char temperature[32];
char mon[32];
char day[32];
char hour[32];
char min[32];
char wday[32];
}Now;
//用于保存服务器返回的天气数据
typedef struct
{
Location location; //子对象1
Now now; //子对象2
char last_update[64]; //子对象3
}Results;
/*********************************************************************************
* Function Name : cJSON_WeatherParse,解析天气数据
* Parameter : JSON:天气数据包 results:保存解析后得到的有用的数据
* Return Value : 0:成功 其他:错误
* Function Explain :
* Create Date : 2017.12.6 by lzn
**********************************************************************************/
int cJSON_WeatherParse(char *JSON, Results *results)
{
cJSON *json,*arrayItem,*object,*subobject,*item;
json = cJSON_Parse(JSON); //解析JSON数据包
if(json == NULL) //检测JSON数据包是否存在语法上的错误,返回NULL表示数据包无效
{
return 1;
}
else
{
if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL);
//匹配字符串"results",获取数组内容
{
int size = cJSON_GetArraySize(arrayItem); //获取数组中对象个数
//printf("cJSON_GetArraySize: size=%d \r\n",size);
if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//获取父对象内容
{
/* 匹配子对象1 */
if((subobject = cJSON_GetObjectItem(object,"location")) != NULL)
{
//printf("---------------------------------subobject1-------------------------------\r\n");
if((item = cJSON_GetObjectItem(subobject,"id")) != NULL)
//匹配子对象1成员"id"
{
memcpy(results[0].location.id,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"name")) != NULL)
//匹配子对象1成员"name"
{
memcpy(results[0].location.name,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"country")) != NULL)
//匹配子对象1成员"country"
{
memcpy(results[0].location.country,item->valuestring,
strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"path")) != NULL)
//匹配子对象1成员"path"
{
memcpy(results[0].location.path,item->valuestring,
strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"timezone")) != NULL)
//匹配子对象1成员"timezone"
{
memcpy(results[0].location.timezone,item->valuestring,
strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"timezone_offset")) != NULL)
//匹配子对象1成员"timezone_offset"
{
memcpy(results[0].location.timezone_offset,item->valuestring,
strlen(item->valuestring));
}
}
/* 匹配子对象2 */
if((subobject = cJSON_GetObjectItem(object,"now")) != NULL)
{
//printf("---------------------------------subobject2-------------------------------\r\n");
if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)
//匹配子对象2成员"text"
{
memcpy(results[0].now.text,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)
//匹配子对象2成员"code"
{
memcpy(results[0].now.code,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL)
//匹配子对象2成员"temperature"
{
memcpy(results[0].now.temperature,item->valuestring,
strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"mon")) != NULL)
//匹配子对象2成员"mon"
{
memcpy(results[0].now.mon,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"day")) != NULL)
//匹配子对象2成员"day"
{
memcpy(results[0].now.day,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"hour")) != NULL)
//匹配子对象2成员"hour"
{
memcpy(results[0].now.hour,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"min")) != NULL)
//匹配子对象2成员"min"
{
memcpy(results[0].now.min,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"wday")) != NULL)
//匹配子对象2成员"wday"
{
memcpy(results[0].now.wday,item->valuestring,strlen(item->valuestring));
}
}
/* 匹配子对象3 */
if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL)
{
//printf("---------------------------------subobject3-------------------------------\r\n");
memcpy(results[0].last_update,item->valuestring,strlen(subobject->valuestring));
}
}
}
}
cJSON_Delete(json); //释放cJSON_Parse()分配出来的内存空间
return 0;
}
如上我们已经对数据包进行了解析。
然后进行分布调用。
//调用温度数据,结构基本不变
//只需要更改获取的数据结构体位置
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s^C",results[0].now.temperature);//更改这行代码获取其他数据。
LCD_ShowString(73,66,(u8 *)dtOLEDBuf,GRAYBLUE,BLACK,16,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
例如:
获取地点数据,只需要找不同,根据上面的代码,更改下面的
//地点
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].location.name);//更改了这行的
LCD_ShowString(60,100,(u8 *)dtOLEDBuf,CYAN,BLACK,16,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
4.屏幕显示,由于分光棱镜的原理,需要反转屏幕。
根据原子哥的视频和芯片手册
我们只需要改变这行代码,就可以实现屏幕反转。使分光棱镜中的显示正向。
在初始化屏幕的初始化文件中改为
具体可以参考CSDN博主https://blog.csdn.net/qq1113512618/article/details/111937148的文章。
三、代码编写
32 main函数编写。
include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "oled.h"
#include "led.h"
#include "lcd_init.h"
#include "lcd.h"
#include "pic.h"
#include "cJSON.h"
//子对象1结构体--Location
typedef struct
{
char id[32];
char name[32];
char country[32];
char path[64];
char timezone[32];
char timezone_offset[32];
}Location;
//子对象2结构体--Now
typedef struct
{
char text[32];
char code[32];
char temperature[32];
char mon[32];
char day[32];
char hour[32];
char min[32];
char wday[32];
}Now;
//用于保存服务器返回的天气数据
typedef struct
{
Location location; //子对象1
Now now; //子对象2
char last_update[64]; //子对象3
}Results;
/*********************************************************************************
* Function Name : cJSON_WeatherParse,解析天气数据
* Parameter : JSON:天气数据包 results:保存解析后得到的有用的数据
* Return Value : 0:成功 其他:错误
* Function Explain :
* Create Date : 2017.12.6 by lzn
**********************************************************************************/
int cJSON_WeatherParse(char *JSON, Results *results)
{
cJSON *json,*arrayItem,*object,*subobject,*item;
json = cJSON_Parse(JSON); //解析JSON数据包
if(json == NULL) //检测JSON数据包是否存在语法上的错误,返回NULL表示数据包无效
{
//printf("Error before: [%s] \r\n",cJSON_GetErrorPtr()); //打印数据包语法错误的位置
return 1;
}
else
{
if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL); //匹配字符串"results",获取数组内容
{
int size = cJSON_GetArraySize(arrayItem); //获取数组中对象个数
//printf("cJSON_GetArraySize: size=%d \r\n",size);
if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//获取父对象内容
{
/* 匹配子对象1 */
if((subobject = cJSON_GetObjectItem(object,"location")) != NULL)
{
//printf("---------------------------------subobject1-------------------------------\r\n");
if((item = cJSON_GetObjectItem(subobject,"id")) != NULL) //匹配子对象1成员"id"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.id,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"name")) != NULL) //匹配子对象1成员"name"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.name,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"country")) != NULL)//匹配子对象1成员"country"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.country,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"path")) != NULL) //匹配子对象1成员"path"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.path,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"timezone")) != NULL)//匹配子对象1成员"timezone"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.timezone,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"timezone_offset")) != NULL)//匹配子对象1成员"timezone_offset"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].location.timezone_offset,item->valuestring,strlen(item->valuestring));
}
}
/* 匹配子对象2 */
if((subobject = cJSON_GetObjectItem(object,"now")) != NULL)
{
//printf("---------------------------------subobject2-------------------------------\r\n");
if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)//匹配子对象2成员"text"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.text,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)//匹配子对象2成员"code"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.code,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL) //匹配子对象2成员"temperature"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.temperature,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"mon")) != NULL) //匹配子对象2成员"mon"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.mon,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"day")) != NULL) //匹配子对象2成员"day"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.day,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"hour")) != NULL) //匹配子对象2成员"hour"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.hour,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"min")) != NULL) //匹配子对象2成员"min"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.min,item->valuestring,strlen(item->valuestring));
}
if((item = cJSON_GetObjectItem(subobject,"wday")) != NULL) //匹配子对象2成员"wday"
{
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",item->type,item->string,item->valuestring);
memcpy(results[0].now.wday,item->valuestring,strlen(item->valuestring));
}
}
/* 匹配子对象3 */
if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL)
{
//printf("---------------------------------subobject3-------------------------------\r\n");
//printf("cJSON_GetObjectItem: type=%d, string is %s,valuestring=%s \r\n",subobject->type,subobject->string,subobject->valuestring);
memcpy(results[0].last_update,item->valuestring,strlen(subobject->valuestring));
}
}
}
}
cJSON_Delete(json); //释放cJSON_Parse()分配出来的内存空间
return 0;
}
int simple_atoi(char *source) //字符串转整形
{
int length = strlen(source); //计算长度
int sum = 0,i=0;
//for(int i=0;source[i]!='';i++) printf("source[%d]: %c",i,source[i]); //输出每个数字字符
if(length!=1)
{
for(int i=0;i<length;i++)
{
sum += (source[i]-'0') * pow(10,(double)length-1-i); //字符转数字并合并
}
return sum;
}
else
{
sum=source[0]-'0';
return sum;
}
}
int main(void)
{
u16 uart1Len;
Results results[] = {{0}};
u8 dtOLEDBuf[16]; //OLED缓存器
int weather=0;
int day,x=0;
char a;
char Cooper[]={"Cooper"};
//初始化
//延时函数初始化
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LED_Init();//LED初始化
LCD_Init();//LCD初始化
LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
while(1)
{
Results results[] = {{0}};
//串口1收到的信息
if(USART_RX_STA&0x8000)
{
uart1Len=USART_RX_STA&0x3f; //得到此次接收到的数据长度
day=cJSON_WeatherParse(USART_RX_BUF, results); //解析天气数据
打印结构体内内容
// ·("打印结构体内内容如下: \r\n");
// printf("%s \r\n",results[0].now.text);
// printf("%s \r\n",results[0].now.code);
// printf("%s \r\n",results[0].last_update);
//清屏,重新显示屏幕内容
LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
//天气
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].now.code);
// printf("%s",results[0].now.code);
weather=simple_atoi((char *)results[0].now.code);
switch(weather)
{
//晴天
case 0:
case 1:
case 2:
case 3:
{
LCD_ShowPicture(8,76,40,40,gImage_0);
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].now.text);
LCD_ShowString(70,82,(u8 *)dtOLEDBuf,LIGHTBLUE,BLACK,16,0);
}break;
//多云,阴天
case 5:
case 6:
case 7:
case 8:
case 9:
{
LCD_ShowPicture(8,76,40,40,gImage_4);
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].now.text);
LCD_ShowString(70,82,(u8 *)dtOLEDBuf,LIGHTBLUE,BLACK,16,0);
}break;
//雨天
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
{
LCD_ShowPicture(8,76,40,40,gImage_14);
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].now.text);
LCD_ShowString(70,82,(u8 *)dtOLEDBuf,LIGHTBLUE,BLACK,16,0);
}break;
//雪天
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
{
LCD_ShowPicture(8,76,40,40,gImage_23);
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].now.text);
LCD_ShowString(70,82,(u8 *)dtOLEDBuf,LIGHTBLUE,BLACK,16,0);
}break;
//其他
default:
{
LCD_ShowPicture(8,76,40,40,gImage_4);
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].now.text);
LCD_ShowString(70,82,(u8 *)dtOLEDBuf,LIGHTBLUE,BLACK,16,0);
}break;
}
//温度 (x,y) x大→小 y 上小 下大
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s^C",results[0].now.temperature);
LCD_ShowString(73,66,(u8 *)dtOLEDBuf,GRAYBLUE,BLACK,16,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
//地点
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].location.name);
LCD_ShowString(60,100,(u8 *)dtOLEDBuf,CYAN,BLACK,16,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
//日期
//月
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s.",results[0].now.mon);
LCD_ShowString(44,43,(u8 *)dtOLEDBuf,GRAYBLUE,BLACK,16,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
//日
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%sth.",results[0].now.day);
LCD_ShowString(4,43,(u8 *)dtOLEDBuf,GRAYBLUE,BLACK,16,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
//周
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].now.wday);
LCD_ShowString(84,15,(u8 *)dtOLEDBuf,CYAN,BLACK,16,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
//时
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s:",results[0].now.hour);
LCD_ShowString(2,10,(u8 *)dtOLEDBuf,WHITE,BLACK,32,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
//分
memset(dtOLEDBuf, 0, sizeof(dtOLEDBuf));
sprintf((char *)dtOLEDBuf,"%s",results[0].now.min);
LCD_ShowString(50,10,(u8 *)dtOLEDBuf,WHITE,BLACK,32,0);
USART_RX_STA=0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
//分号(时分之间)
LCD_ShowChar(33,8,':',YELLOW,BLACK,32,0);
//划线
LCD_DrawLine(0,62,128,62,YELLOW);
//画圆圈
x++;
if(x==10)
{
x=0;
LCD_ShowString(80,43,Cooper,YELLOW,BLACK,16,0);
}
Draw_Circle(103,44,x,LIGHTGREEN);
}
delay_ms(5);
}
}
esp32代码编写
#include <Arduino.h>
#include <WiFi.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
#define NTP1 "ntp1.aliyun.com"
#define NTP2 "ntp2.aliyun.com"
#define NTP3 "ntp3.aliyun.com"
//填写WIFI入网信息
const char * ID = "自己WIFI名称";
const char * PASSWORD = "WIFI密码";
const String MONTH_NAMES[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; //月份
const String DAY_NAMES[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
"21", "22", "23", "24", "25", "26", "27", "28", "29", "30","31"}; //日
const String HOUR_NAMES[] = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10",
"11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
"21", "22", "23", "24"};//时
const String MIN_NAMES[] = {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10",
"11", "12", "13","14", "15", "16", "17", "18", "19", "20",
"21", "22", "23", "24", "25", "26", "27", "28", "29", "30",
"31", "32", "33", "34", "35", "36", "37", "38", "39", "40",
"41", "42", "43", "44", "45", "46", "47", "48", "49", "50",
"51", "52", "53", "54", "55", "56", "57", "58", "59", "60"}; //分
const String WDAY_NAMES[] = {"Sun.", "Mon.", "Tues.", "Wed.", "Thur.", "Fri.", "Sat."}; //星期
//天气相关参数
String API = "上文提到的私钥";
String WeatherURL = "";
String CITY = "自己所在城市的代码";
String url_xinzhi = "";
String Weather = "0";
String Temperature = "0";
String Name = "0";
long sum = 0;
/* 创建实例 */
HTTPClient http;
String GitURL(String api,String city)
{
url_xinzhi = "https://api.seniverse.com/v3/weather/now.json?key=";
url_xinzhi += api;
url_xinzhi += "&location=";
url_xinzhi += city;
url_xinzhi += "&language=en&unit=c";
return url_xinzhi;
}
void ParseWeather(String url)
{
int Year,Mon,Day,Hour,Min,Wday;
struct tm timeInfo; //声明一个结构体
DynamicJsonDocument doc(1024); //分配内存,动态
DynamicJsonDocument dat(1024);
http.begin(url);
int httpGet = http.GET();
if(httpGet > 0)
{
//Serial.printf("HTTPGET is %d",httpGet);
if(httpGet == HTTP_CODE_OK)
{
if (!getLocalTime(&timeInfo))
{ //一定要加这个条件判断,否则内存溢出
// Serial.println("Failed to obtain time");
return;
}
String date = WDAY_NAMES[timeInfo.tm_wday];
// Serial.println(date.c_str());
// sprintf_P(buff1, PSTR("%04d-%02d-%02d %s"), timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, WDAY_NAMES[timeInfo.tm_wday].c_str());
String shuju = String(timeInfo.tm_year + 1900); //年
shuju += "-";
shuju += timeInfo.tm_mon + 1; //月
shuju += "-";
shuju += timeInfo.tm_mday; //日
shuju += " ";
shuju += timeInfo.tm_hour; //时
shuju += ":";
shuju += timeInfo.tm_min;
shuju += ":";
shuju += timeInfo.tm_sec;
shuju += " ";
shuju += WDAY_NAMES[timeInfo.tm_wday].c_str(); //星期
String json = http.getString();
deserializeJson(doc, json);
//location
dat["results"][0]["location"]["id"] = doc["results"][0]["location"]["id"].as<String>();
dat["results"][0]["location"]["name"] = doc["results"][0]["location"]["name"].as<String>();
dat["results"][0]["location"]["country"] = doc["results"][0]["location"]["country"].as<String>();
dat["results"][0]["location"]["path"] = doc["results"][0]["location"]["path"].as<String>();
dat["results"][0]["location"]["timezone"] = doc["results"][0]["location"]["timezone"].as<String>();
dat["results"][0]["location"]["timezone_offset"] = doc["results"][0]["location"]["timezone_offset"].as<String>();
//now
dat["results"][0]["now"]["text"] = doc["results"][0]["now"]["text"].as<String>();
dat["results"][0]["now"]["code"] = doc["results"][0]["now"]["code"].as<String>();
dat["results"][0]["now"]["temperature"] = doc["results"][0]["now"]["temperature"].as<String>();
dat["results"][0]["now"]["mon"]=MONTH_NAMES[timeInfo.tm_mon ].c_str();
dat["results"][0]["now"]["day"]=DAY_NAMES[timeInfo.tm_mday].c_str();
dat["results"][0]["now"]["hour"]=HOUR_NAMES[timeInfo.tm_hour].c_str();
dat["results"][0]["now"]["min"]=MIN_NAMES[timeInfo.tm_min].c_str();
dat["results"][0]["now"]["wday"]=WDAY_NAMES[timeInfo.tm_wday].c_str();
dat["results"][0]["last_update"]= doc["results"][0]["last_update"].as<String>();
char json_string[1024];
serializeJson(dat,json_string);
Serial.println(json_string);
}
else
{
Serial.printf("ERROR1!!");
}
}
else
{
Serial.printf("ERROR2!!");
}
http.end();
}
void setup()
{
Serial.begin(115200);
//==================wifi连接==================
// Serial.println("WiFi:");
// Serial.println(ID);
// Serial.println("PASSWORLD:");
// Serial.println(PASSWORD);
WiFi.mode(WIFI_STA);
WiFi.begin(ID,PASSWORD);
while(WiFi.status()!=WL_CONNECTED)
{
delay(500);
// Serial.println("Connecting...");
}
// Serial.println("Connect OK!");
//==================wifi连接==================
WeatherURL = GitURL(API,CITY);
configTime(8 * 3600, 0, NTP1, NTP2, NTP3);
}
void loop()
{
// Serial.println("连接成功!");
delay(20000);
}
esp32代码中所需的心知天气城市代码文档:城市代码
桌面天气全套文件:全套文件
包括源码以及图形库,字库等,word文档解答了遇到的问题。
总结
以上就是今天要讲的内容,本文介绍了桌面天气时钟的开发过程。
成品照片过几天会上传,屏幕由于操作失误烧掉了,重新购买了=-=
如果大家觉得还算有用的话
悄悄告诉你们一个催更小技巧
点赞、收藏、关注,可以加速更新嗷!!!