#include #include #include #include #include #include // Core graphics library #include // Hardware-specific library for ST7735 #include // Hardware-specific library for ST7789 #include #include #include "animation.h" #include "MyFont_1.h"//中文字符库,需要使用汉字取模软件PCtoLCD2002.exe #include "pic.h"//天气图标库,需要使用图片取模软件ImageConverter565.exe #define TFT_CS 32 #define TFT_RST 33 // Or set to -1 and connect to Arduino RESET pin #define TFT_DC 27 #define TFT_BACKLIGHT 12 Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP,"ntp.aliyun.com"); unsigned long epochTime; // WiFi的SSID和密码 const char *ssid = "Mate 40"; // WiFi的SSID名称 const char *pwd = "123456789"; // WiFi的密码 // 天气服务的API密钥 const String xz_api_key = "Sn9ogChgIUNpx7KSC"; // API密钥 // 城市名称 const String city = "Gongshu"; // 城市名称 // JSON文档,用于存储解析的天气数据 DynamicJsonDocument doc(1024); // JSON文档大小1024字节 String now_address="",now_temperature="",now_weather="",now_weather_code=""; int now_weather_code_temp; int now_temperature_temp; void setweekday(int cursor_x, int cursor_y, int textsize, String weekday) { tft.setCursor(cursor_x, cursor_y); // 设置文本显示的起始位置 tft.setTextSize(textsize); // 设置文本大小,使用传入的参数 tft.setTextColor(ST77XX_YELLOW); // 设置文本颜色为黄色 tft.println(weekday); // 显示星期字符串 } void showMyFont(int32_t x, int32_t y, const char c[3], uint32_t color) { Serial.print("JINRU HANSHUI"); for (int k = 0; k <= 57; k++) { // 根据字库的字数调节循环的次数 if (CHINESE[k].Index[0] == c[0] && CHINESE[k].Index[1] == c[1] && CHINESE[k].Index[2] == c[2]) { tft.drawBitmap(x, y, CHINESE[k].CN_Id, CHINESE[k].CN_width, 16, color); } } } /*******************整句汉字显示****************/ void showMyFonts(int32_t x, int32_t y, const char* str, uint32_t color) { // 显示整句汉字,字库比较简单,上下、左右输出是在函数内实现 int x0 = x; for (int i = 0; i < strlen(str); i += 3) { // 显示每个字符,传递给 showMyFont showMyFont(x0, y, str + i, color); x0 += 17; // 每个字符占 17 像素宽度 } } void setup() { // 启动串口通信 Serial.begin(115200); // 连接WiFi Serial.printf("Connecting to %s ", ssid); WiFi.begin(ssid, pwd); // 等待WiFi连接成功 while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println("Connected!"); // WiFi已连接 timeClient.begin(); timeClient.setTimeOffset(28800); // 打印本地IP地址 Serial.println(WiFi.localIP().toString()); Serial.print(F("Hello! ST77xx TFT Test")); // Use this initializer if using a 1.8" TFT screen: tft.initR(INITR_BLACKTAB); // Init ST7735S chip, black tab tft.setRotation(3); pinMode(TFT_BACKLIGHT, OUTPUT); digitalWrite(TFT_BACKLIGHT, HIGH); tft.fillScreen(ST77XX_BLACK); } // 优化后的get_weather函数 int get_weather() { HTTPClient http; String url = "https://api.seniverse.com/v3/weather/now.json?key=" + xz_api_key + "&location=" + city + "&language=zh-Hans&unit=c"; http.begin(url); int http_code = http.GET(); if (http_code != HTTP_CODE_OK) { Serial.printf("GET fail, http code is %s\n", http.errorToString(http_code).c_str()); http.end(); return -1; } String response = http.getString(); Serial.printf("response:[%s]\n", response.c_str()); deserializeJson(doc, response); JsonObject root = doc.as(); JsonArray results = root["results"]; JsonObject now = results[0]["now"]; now_address = root["results"][0]["location"]["path"].as(); now_weather_code_temp = now["code"].as(); now_temperature_temp = now["temperature"].as(); http.end(); return 0; } tft.fillRect(5,65,32,16,ST77XX_BLUE); //打印地区 if(now_address=="拱墅") { showMyFonts(5,65,"拱墅" , ST77XX_YELLOW); } #define X 5 #define Y 105 #define pX 68 #define pY 68 tft.fillRect(X,Y,64,16,ST77XX_BLUE); tft.fillRect(68,68,60,60,ST77XX_BLUE); switch (now_weather_code_temp) {//天气代码不是int类型,要先转换 case 0: showMyFonts(X, Y, "晴", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p0_5151, 51, 51); break; case 1: showMyFonts(X, Y, "夜晚晴", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p1_5152, 51, 52); break; case 2: showMyFonts(X, Y, "晴", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p0_5151, 51, 51); break; case 3: showMyFonts(X, Y, "夜晚晴", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p1_5152, 51, 52); break; case 4: showMyFonts(X, Y, "多云", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p4_6047, 60, 47); break; case 5: showMyFonts(X, Y, "晴间多云", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p5_6044, 60, 44); break; case 6: showMyFonts(X, Y, "晴间多云", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p6_6051, 60, 51); break; case 7: showMyFonts(X, Y, "大部多云", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p7_6042, 60, 42); break; case 8: showMyFonts(X, Y, "大部多云", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p8_5649, 56, 49); break; case 9: showMyFonts(X, Y, "阴", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p9_6040, 60, 40); break; case 10: showMyFonts(X, Y, "阵雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p10_6059, 60, 59); break; case 11: showMyFonts(X, Y, "雷阵雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p11_5656, 56, 56); break; case 12: {//滚动显示,这里还需要优化 tft.fillRect(X,Y,64,16,ST77XX_BLUE); showMyFonts(X,Y,"阵雨冰雹" , ST77XX_GREEN);break; } case 13: showMyFonts(X, Y, "小雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p13_5654, 56, 54); break; case 14: showMyFonts(X, Y, "中雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p14_5654, 56, 54); break; case 15: showMyFonts(X, Y, "大雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p15_5654, 56, 54); break; case 16: showMyFonts(X, Y, "暴雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p16_5654, 56, 54); break; case 17: showMyFonts(X, Y, "大暴雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p17_5754, 57, 54); break; case 18: showMyFonts(X, Y, "特大暴雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p18_5754, 57, 54); break; case 19: showMyFonts(X, Y, "冻雨", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p19_5657, 56, 57); break; case 20: showMyFonts(X, Y, "雨夹雪", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p20_5655, 56, 55); break; case 21: showMyFonts(X, Y, "阵雪", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p21_5656, 56, 56); break; case 22: showMyFonts(X, Y, "小雪", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p22_5653, 56, 53); break; case 23: showMyFonts(X, Y, "中雪", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p23_5653, 56, 53); break; case 24: showMyFonts(X, Y, "大雪", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p24_5653, 56, 53); break; case 25: showMyFonts(X, Y, "暴雪", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p25_5656, 56, 56); break; case 26: showMyFonts(X, Y, "浮尘", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p26_5345, 53, 45); break; case 27: showMyFonts(X, Y, "扬沙", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p26_5345, 53, 45); break; case 28: showMyFonts(X, Y, "沙尘暴", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p28_5834, 58, 34); break; case 29: showMyFonts(X, Y, "强沙尘暴", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p28_5834, 58, 34); break; case 30: showMyFonts(X, Y, "雾", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p30_5450, 54, 50); break; case 31: showMyFonts(X, Y, "霾", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p31_5650, 56, 50); break; case 32: showMyFonts(X, Y, "风", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p32_5644, 56, 44); break; case 33: showMyFonts(X, Y, "大风", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p32_5644, 56, 44); break; case 34: showMyFonts(X, Y, "飓风", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p34_5656, 56, 56); break; case 35: showMyFonts(X, Y, "热带风暴", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p34_5656, 56, 56); break; case 36: showMyFonts(X, Y, "龙卷风", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p36_5655, 56, 55); break; case 37: showMyFonts(X, Y, "冷", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p37_5158, 51, 58); break; case 38: showMyFonts(X, Y, "热", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p38_5151, 51, 51); break; case 99: showMyFonts(X, Y, "未知", ST77XX_GREEN); tft.drawRGBBitmap(pX, pY, p99_5323, 53, 23); break; default: break; } tft.fillRect(5,84,63,16,ST77XX_BLUE); tft.setCursor(5, 84); tft.setTextSize(1); tft.setTextColor(ST77XX_BLUE); tft.setTextSize(2); tft.println(now_temperature_temp); if ( (now_temperature_temp < 10) && (now_temperature_temp >= 0)) { showMyFonts(24,84,"℃",ST77XX_BLUE); } else{ showMyFonts(40,84,"℃",ST77XX_BLUE); } } void loop() { // 每隔10秒获取一次天气数据 get_weather(); // put your main code here, to run repeatedly: for(int i=0;itm_mday; int currentMonth = ptm->tm_mon+1; int currentYear = ptm->tm_year+1900; Serial.print(currentYear); Serial.print("年"); Serial.print(currentMonth); Serial.print("月"); Serial.print(monthDay); Serial.println("日"); tft.fillRect(102,42,22,14,ST77XX_BLUE); //部分区域清屏,刷新秒 //10+2+10=22,“数字”分辨率10*14像素,连续显示时间隔2像素 tft.setCursor(102, 42); tft.setTextSize(1); //设置文本起始坐标 tft.setTextColor(ST77XX_RED); //设置文本颜色为红色 tft.setTextSize(2); //设置文字的大小 (1~7) if (currentSec < 10){ //将 0-9 变为00-09 tft.println(0); tft.setCursor(114, 42); tft.setTextSize(1); tft.setTextColor(ST77XX_RED); tft.setTextSize(2); tft.println(currentSec); } else{ tft.println(currentSec); //显示文字 } if (currentSec==0){ //刷新分 tft.fillRect(55,28,44,28,ST77XX_BLUE); //20+4+20=44 } tft.setCursor(55, 28); tft.setTextSize(1); tft.setTextColor(ST77XX_CYAN); tft.setTextSize(4); if (currentMinute < 10) { tft.println(0); tft.setCursor(79, 28); tft.setTextSize(1); tft.setTextColor(ST77XX_CYAN); tft.setTextSize(4); tft.println(currentMinute); } else{ tft.println(currentMinute); } if (currentMinute==0 && currentSec==0){ //刷新时 tft.fillRect(1,28,44,28,ST77XX_BLUE); } tft.setCursor(1, 28); tft.setTextSize(1); //tft.setTextFont(7); tft.setTextColor(ST77XX_CYAN); tft.setTextSize(1); if (currentHour < 10) { //tft.println(0); tft.setCursor(25, 28); tft.setTextSize(1); tft.setTextColor(ST77XX_CYAN); tft.setTextSize(1); tft.println(currentHour); } else{ tft.println(currentHour); } tft.setCursor(40, 28); tft.setTextSize(1);//时分分隔符 tft.setTextColor(ST77XX_CYAN); tft.setTextSize(1); tft.println(":"); tft.setCursor(89, 5); tft.setTextSize(1);//月日分隔符 tft.setTextColor(ST77XX_CYAN); tft.setTextSize(2); tft.println("/"); if (currentHour==0 && currentMinute==0 && currentSec==0){ //刷新 日、周 tft.fillRect(102,5,22,14,ST77XX_BLUE); tft.fillRect(5,5,24,14,ST77XX_BLUE); } tft.setCursor(102, 5); tft.setTextSize(1); tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); if (monthDay < 10) { tft.println(0); //"1_月01日",感觉太奇怪了,还是"1_月_1日"吧! tft.setCursor(114, 5); tft.setTextSize(1); tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); tft.println(monthDay); } else { tft.println(monthDay); } switch(weekDay){ case 0: setweekday(5, 5, 2, "SUN");break; case 1: setweekday(5, 5, 2, "MON");break; case 2: setweekday(5, 5, 2, "TUE");break; case 3: setweekday(5, 5, 2, "WEN");break; case 4: setweekday(5, 5, 2, "THI");break; case 5: setweekday(5, 5, 2, "FRI");break; case 6: setweekday(5, 5, 2, "SAT");break; default: break; } if (monthDay==1 && currentHour==0 && currentMinute==0 && currentSec==0){ //刷新月 tft.fillRect(65,5,22,14,ST77XX_BLUE); } tft.setTextSize(1); // 设置文本大小为1 tft.setCursor(65, 5); // 设置光标位置为 (65, 5) tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); if (currentMonth <10) { //tft.println(0); //"_1月_1日"比"1_月_1日"更好一点! tft.setCursor(77, 5); // 设置文本的起始位置为 (77, 5) tft.setTextSize(1); // 设置文本的大小为 1 tft.setTextColor(ST77XX_YELLOW); tft.setTextSize(2); tft.println(currentMonth); } else { tft.println(currentMonth); } }