《项目》 之 ESP8266 心知天气 + 时钟

硬件电路:

  1. DS3231  +  0.96OLED  +  8*32 WS2812点阵屏

需要的库文件:

①<DS3231>

②<FastLED>

③<Time-master>

④<U8g2>

⑤<Rtc_by_Makuna>

时钟模式:

  本地DS3231时钟 或  网络时钟

weather.ino文件

#include<ESP8266mDNS.h>
#include<ArduinoOTA.h>
#include<ArduinoJson.h>
#include<EEPROM.h>
#include<Ticker.h>
#include<math.h>
#include<WiFiUdp.h>
#include<TimeLib.h>
#include<U8g2lib.h>
#include"weather.h"
#include<FastLED.h>
#include <DS3231.h>
#include<Wire.h>
#include<RtcDS3231.h>
RtcDS3231<TwoWire> Rtc(Wire);

#include"font.h"//引入字体

//***********************************设置RGB灯*************************************

CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
CRGB* const leds( leds_plus_safety_pixel + 1);

//**********************************定义定时器变量********************************

Ticker openDisplay;

//**********************************DS3231初始化********************************

DS3231 Clock;
bool Century=false;
bool h12;
bool PM;

//***********************************网络时钟定义********************************

static const char ntpServerName[] = "time1.aliyun.com";
const int timeZone = 8;     //时区
WiFiUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP 
time_t getNtpTime();
void sendNTPpacket(IPAddress &address);
time_t prevDisplay = 0; // when the digital clock was displayed

//**********************************使用屏幕设置*******************************

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

//***************************************************************************
WiFiClient client; 
//***************************************************************************
 
void setup() {
  Serial.begin(BAUD_RATE);

  //****************************************************************************************************************************************************************************
  FlashMode_t ideMode = ESP.getFlashChipMode();
  String coreVersion = ESP.getCoreVersion();
  Serial.println("\n");
  Serial.print(F("Arduino Core For ESP8266 Version: "));
  Serial.println(coreVersion);
  Serial.printf("\nESP8266芯片id: %u \n\n", ESP.getChipId());
  Serial.printf("固件大小: %u KBytes\n\n", ESP.getSketchSize()/1024);
  Serial.printf("剩余可用固件空间: %u KBytes\n\n", ESP.getFreeSketchSpace()/1024);
  Serial.printf("Flash real id:   %08X\n\n", ESP.getFlashChipId());
  Serial.printf("Flash 实际大小: %u KBytes\n\n", ESP.getFlashChipRealSize()/1024);
  Serial.printf("IDE配置Flash大小: %u KBytes\n\n", ESP.getFlashChipSize()/1024);
  Serial.printf("IDE配置Flash频率: %u MHz\n\n", ESP.getFlashChipSpeed()/1000000);
  Serial.printf("Flash ide mode:  %s\n\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT" : ideMode == FM_DIO ? "DIO" : ideMode == FM_DOUT ? "DOUT" : "UNKNOWN"));
  //****************************************************************************************************************************************************************************
  
  //*******************************************GPIO设置*******************************************   
  pinMode(LED,OUTPUT);
  pinMode(WAKE_UP,INPUT_PULLUP);
  pinMode(UP_KEY,INPUT_PULLUP);
  pinMode(M_KEY,INPUT_PULLUP);
  pinMode(DOWN_KEY,INPUT_PULLUP);    
  digitalWrite(LED, HIGH);
  //******************************************0.96 OLED设置***************************************
  u8g2.begin();
  u8g2.enableUTF8Print();
  /**
 * 设置显示器的旋转角度
 * @param u8g2_cb 旋转选项
 *        U8G2_R0 不做旋转 水平
 *        U8G2_R1 旋转90度
 *        U8G2_R2 旋转180度
 *        U8G2_R3 旋转270度
 *        U8G2_MIRROR 不做旋转 水平,显示内容是镜像的,暂时不理解
 */
  u8g2.setDisplayRotation(U8G2_R0);//设置显示器方向
  U8G2_OLED_R = 0;//OLED方向标志位置0
  u8g2.setContrast(OLED_Brightness);//设置OLED亮度
  u8g2.setDrawColor(1);//设置绘制颜色
  delay(1000);
  
  //**************开机界面*************
  
  Boot_animation();//开机动画
  
  //***************************************WS2812 RGB点阵初始化************************************
  WS2812_INT();
  
  //********************************************初始化时钟*****************************************
  Rtc.Begin();
  Serial.print("固件编译时间:");
  Serial.print(__DATE__);
  Serial.print("   ");
  Serial.println(__TIME__);
  Serial.println();
  RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);//获取上传程序时间
  RtcDateTime now = Rtc.GetDateTime();////获取DS3231时间
  if (now < compiled) //偏差过大校准时间
  {
      Serial.println("RTC is older than compile time!  (Updating DateTime)");
      Rtc.SetDateTime(compiled);
  }
  //Rtc.SetDateTime(compiled);
  Rtc.Enable32kHzPin(false);
  Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeAlarmBoth);
   
  //*******************************************看门狗时间设置**************************************
  ESP.wdtEnable(5000);

  //**********************************************配置网络***************************************
  WiFi.disconnect();
  strcpy(config.stassid, ssid);   
  strcpy(config.stapsw, pswd); 

  if(WiFi.status() != WL_CONNECTED){
    WIFI_MODE = 0;
    if(autoConfig())
      WIFI_MODE = 1;
    else
      WIFI_MODE = 0;
  }
   DebugPrint("IP address: ");
   DebugPrintln(WiFi.localIP());//WiFi.localIP() 返 回 8266 获 得 的 ip 地 址
   DebugPrint("\n");
   BasicOTAINT();
  
   //********************************************网络时钟就绪************************************
   Udp.begin(localPort);
   setSyncProvider(getNtpTime);
   setSyncInterval(300);

   Wire.begin();
   //**********************************************初始化页*************************************
   page_int();
   
   //*********************************************初始时间设置***********************************
   LastWeatherTime = millis();
   LastRtcTime = millis();
   LastNTPTime = millis();
   
   u8g2.clearBuffer();//清屏缓存
   u8g2.setPowerSave(LOW);//默认屏幕亮
   digitalWrite(LED, HIGH);
   DebugPrintln("*********************************初始化结束,进入loop函数!***********************************");
}

void loop() {
  if(WIFI_MODE){
    //检测此时此刻是否联网
    while (!client.connected()){
    if (!client.connect(host, 80)){  
      flag = !flag;
      digitalWrite(LED, flag);
      delay(400);          
      // 喂 狗
      ESP.wdtFeed();      
     } 
   }
   
   //获取天气并显示
  if(millis()-LastWeatherTime >= WeatherDelay||millis()-LastWeatherTime<3*1000||millis()-LastSmartConfig<7*1000){
      RGB_ShowString(0,0,"Get!!");
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_wqy16_t_gb2312a);
      u8g2.setCursor(0, 36);
      u8g2.print("更新天气中......"); 
      u8g2.sendBuffer();
      LastWeatherTime = millis();
      digitalWrite(LED, LOW);
      delay(100);
      digitalWrite(LED, HIGH);
      if(sendRequest(host, city, APIKEY) && skipResponseHeaders()) {
        clrEsp8266ResponseBuffer();
        readReponseContent(response, sizeof(response));
        if(parseUserData(response, &userData)) {
          showWeather(&userData);        
          }      
        }   
      }
  }
        
 //获取本地时间并显示
  if(millis()-LastRtcTime >= RtcDelay){
    LastRtcTime = millis();
    RtcDateTime now = Rtc.GetDateTime();
    showTime(now,&userData);
  }

  uint8_t KEY=KEY_Scan2();//扫描按键
  switch(KEY)
  {
    case UP_KEY_PRES:
    DebugPrintln("*************TIME_MODE切换***************");
    if(TIME_MODE == DS3231_TIME_MODE)
      TIME_MODE = NTP_TIME_MODE;
    else
      TIME_MODE = DS3231_TIME_MODE;
    break;
    case M_KEY_PRES:
      Get_NTPclient = HIGH;
    break;
    case DOWN_KEY_PRES:
    break;
    case WAKE_UP_PRES:
      DebugPrintln("************5s后关闭OLED***************");
      u8g2.setPowerSave(LOW);
      openDisplay.once_ms(openOledTime, offDisplay);//定时器初始化
    break;
    case M_KEY_LONG_PRES:
    break;
    case WAKE_UP_LONG_PRES:
      DebugPrintln("*************进入设置***************");
      ALL_SET();
    break;
  }
  
 //判断是否需要获取网络时间更新到DS3231上
 if(Get_NTPclient&&WIFI_MODE){
  TIMER_GET();
  Get_NTPclient = LOW;
 }

 //判断是否需要智能配网
 if(Get_SmartConfig)
  smartConfig();
  
  ArduinoOTA.handle();//无线升级
  digitalWrite(LED, HIGH);//灭灯
  ESP.wdtFeed();// 喂 狗
}

//初始化页
void page_int(){
  strcpy(set_up_page.name,"设置");
  set_up_page.cursor = 1;
  set_up_page.rows = 11;
  
  strcpy(Desktop_Set_page.name,"桌面设置");
  Desktop_Set_page.cursor = 1;
  Desktop_Set_page.rows = 3;
}

//设置模式
void ALL_SET(){
  set_up_page.time = millis();      //赋值刷新时间
  set_up_page.cursor = 1;           //光标位置归零
  if(openDisplay.active())//如果开启了定时器则关闭
     openDisplay.detach();//关定时器
  u8g2.setPowerSave(LOW);//开显示屏
  
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_open_iconic_all_6x_t);
  u8g2.drawGlyph(40,55,129);
  u8g2.sendBuffer();
  delay(1000);
      
  while(true){
  //防止光标位置错
  set_up_page.cursor = set_up_page.cursor<=1 ? 1:set_up_page.cursor;
  set_up_page.cursor = set_up_page.cursor>=set_up_page.rows ? set_up_page.rows:set_up_page.cursor;
  
  //刷新屏幕
  if(millis()-set_up_page.time >= set_up_page.refresh_time){
    set_up_page.time = millis();
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_wqy16_t_gb2312a);
    uint8_t PAGE = (set_up_page.cursor%4 == 0 ? (set_up_page.cursor/4)-1:set_up_page.cursor/4);
    switch(PAGE)
    {
      case 0:
      u8g2.setCursor(10, 16*1-2);
      u8g2.print(" 1.桌面设置");
      u8g2.setCursor(10, 16*2-2);
      u8g2.print(" 2.屏幕设置");
      u8g2.setCursor(10, 16*3-2);
      u8g2.print(" 3.网络信息");
      u8g2.setCursor(10, 16*4-2);
      u8g2.print(" 4.智能配网");
      break;
      case 1:
      u8g2.setCursor(10, 16*1-2);
      u8g2.print(" 5.时间设置");
      u8g2.setCursor(10, 16*2-2);
      u8g2.print(" 6.天气设置");
      u8g2.setCursor(10, 16*3-2);
      u8g2.print(" 7.刷新时间");
      u8g2.setCursor(10, 16*4-2);
      u8g2.print(" 8.版本信息");
      break;
      case 2:
      u8g2.setCursor(10, 16*1-2);
      u8g2.print(" 9.RGB点阵屏");
      u8g2.setCursor(10, 16*2-2);
      u8g2.print("10.快捷键设置");
      u8g2.setCursor(10, 16*3-2);
      u8g2.print("11.退出设置");
      break;
    }
    //显示光标
    u8g2.setFont(u8g2_font_open_iconic_all_1x_t);
    u8g2.drawGlyph(0, 16*(set_up_page.cursor%4==0? 4:set_up_page.cursor%4)-4,118);
    u8g2.sendBuffer();
  }
  
  uint8_t KEY=KEY_Scan2();//扫描按键
  if(KEY == WAKE_UP_LONG_PRES)
    break;
    
  switch(KEY)
  {
    case UP_KEY_PRES:
      set_up_page.cursor --;
    break;
    case M_KEY_PRES:
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_wqy16_t_gb2312a);
      u8g2.setCursor(10, 16*2-2);
      u8g2.print(set_up_page.cursor);
      u8g2.sendBuffer();    
      switch(set_up_page.cursor){
        case 1:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 2:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 3:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 4:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 5:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 6:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 7:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 8:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 9:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 10:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_PRES)
              break;
            ESP.wdtFeed();// 喂 狗
          }
        break;
        case 11:
          while(true){
            uint8_t KEY=KEY_Scan2();//扫描按键
            if(KEY == WAKE_UP_LONG_PRES)
              break;
            else if(KEY == WAKE_UP_PRES)
            goto TIAOCHU;
            ESP.wdtFeed();// 喂 狗
          }
        break;
      }
    break;
    case DOWN_KEY_PRES:
      set_up_page.cursor ++;
    break;
    case WAKE_UP_PRES:
      
    break;
    case UP_KEY_LONG_PRES:
//      U8G2_OLED_R = !U8G2_OLED_R;
//      if(!U8G2_OLED_R)
//        u8g2.setDisplayRotation(U8G2_R0);//设置显示器方向
//      else
//        u8g2.setDisplayRotation(U8G2_R2);//设置显示器方向
    break;
  }
    ESP.wdtFeed();// 喂 狗
  }
  TIAOCHU:
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_open_iconic_all_6x_t);
  u8g2.drawGlyph(35,60,64);
  u8g2.sendBuffer();
  delay(1000);
}

//关闭显示屏
void offDisplay(){
  u8g2.setPowerSave(HIGH);//关屏幕
}

//按键处理函数
//mode:0,不支持连续按;1,支持连续按;
//0,没有任何按键按下
uint8_t KEY_Scan(uint8_t mode)
{   
  uint8_t key_up=1;//按键按松开标志
  if(mode)key_up=1;  //支持连按     
  if(key_up&&(KEYU==0||KEYM==0||KEYD==0||KEYW==0))
  {
    delay(5);//去抖动
    key_up=0;
    if(KEYU==0)return 1;
    else if(KEYM==0)return 2;
    else if(KEYD==0)return 3;
    else if(KEYW==0)return 4;
  }else if(KEYU==1||KEYM==1||KEYD==1||KEYW==1)key_up=1;
  return 0;// 无按键按下
}
uint8_t KEY_Scan2()
{
  uint8_t KEY = KEY_Scan(0);
  switch(KEY)
  {
  case UP_KEY_PRES:
      up_pres_time = millis();
    break;
  case M_KEY_PRES:
      m_pres_time = millis();
    break;
  case DOWN_KEY_PRES:
      down_pres_time = millis();
    break;
  case WAKE_UP_PRES:
      wake_pres_time = millis();
  break;
  }
  while(KEYU==0||KEYM==0||KEYD==0||KEYW==0)
  {
    if(up_pres_time!=0&& millis()-up_pres_time >= key_long_pres_time){
      KEY = UP_KEY_LONG_PRES;
    }
    else if(m_pres_time!=0&& millis()-m_pres_time >= key_long_pres_time){
      KEY = M_KEY_LONG_PRES;
    }
    else if(down_pres_time!=0&& millis()-down_pres_time >= key_long_pres_time){
      KEY = DOWN_KEY_LONG_PRES;
    }
    else if(wake_pres_time!=0&& millis()-wake_pres_time >= key_long_pres_time){
      KEY = WAKE_UP_LONG_PRES;
    }
    ESP.wdtFeed();// 喂 狗   
  }
  up_pres_time = 0;
  m_pres_time = 0;
  down_pres_time = 0;
  wake_pres_time = 0;
  
  return KEY;
}

//串口打印RTC时间
#define countof(a) (sizeof(a) / sizeof(a[0]))
void printDateTime(RtcDateTime& dt)
{
  char datestring[25];
  
  snprintf_P(datestring, 
      countof(datestring),
      PSTR("%04u/%02u/%02u %02u:%02u:%02u"),
      dt.Year(),
      dt.Month(),
      dt.Day(),
      dt.Hour(),
      dt.Minute(),
      dt.Second());
    DebugPrint("\n****************");
    RtcTemperature temp = Rtc.GetTemperature();
    Serial.print(temp.AsFloatDegC());  //或者temp.Print(Serial);
    Serial.print(" ℃  ");
    DebugPrint(datestring);
    DebugPrint("****************");
    Serial.println();
}

//判断星期
char week1[10],week2[16],week3[2],week4[6];
char * num_week(uint8_t dayofweek,int Mode){
  switch(dayofweek)
  {
    case 1: 
    strcpy(week1,"Sunday");
    strcpy(week2,"周日");
    strcpy(week3,"Su");
    strcpy(week4,"日"); 
      break;
    case 2: 
    strcpy(week1,"Monday");
    strcpy(week2,"周一");
    strcpy(week3,"Mo");
    strcpy(week4,"一"); 
      break;
    case 3: 
    strcpy(week1,"Tuesday");
    strcpy(week2,"周二");
    strcpy(week3,"Tu");
    strcpy(week4,"二"); 
      break;
    case 4: 
    strcpy(week1,"Wednesday");
    strcpy(week2,"周三"); 
    strcpy(week3,"We");
    strcpy(week4,"三"); 
      break;
    case 5: 
    strcpy(week1,"Thursday");
    strcpy(week2,"周四"); 
    strcpy(week3,"Th");
    strcpy(week4,"四"); 
      break;
    case 6: 
    strcpy(week1,"Friday");
    strcpy(week2,"周五");
    strcpy(week3,"Fr"); 
    strcpy(week4,"五");
      break;
    case 7: 
    strcpy(week1,"Saturday");
    strcpy(week2,"周六"); 
    strcpy(week3,"Sa");
    strcpy(week4,"六");
      break;
    default:
    strcpy(week1,"NO");
    strcpy(week2,"无");
    strcpy(week3,"NO");
    strcpy(week4,"无");
      break; 
  }
  switch(Mode)
  {
    case 1: return week1; break;
    case 2: return week2; break;
    case 3: return week3; break;
    case 4: return week4; break;
  }
}

//显示时间到屏幕
void showTime(RtcDateTime& dt,struct UserData* userData){
  char Hours[3],Minutes[3],Seconds[3];
  //强制类型转换
  strcpy(Hours,  u8x8_u8toa(dt.Hour()  , 2));
  strcpy(Minutes,u8x8_u8toa(dt.Minute(), 2));
  strcpy(Seconds,u8x8_u8toa(dt.Second(), 2));
  //RGB点阵刷新时间
  RGB_ShowNum(0,0,dt.Hour(),2);
  RGB_ShowChar(12,0,':');
  RGB_ShowNum(18,0,dt.Minute(),2);
  //OLED刷新显示时间
    u8g2.clearBuffer();
    
    if(WIFI_MODE == 1)
       showWeather(userData);
    else
    {
      u8g2.setFont(u8g2_font_open_iconic_all_2x_t);
      u8g2.drawGlyph(0, 16, 197);
    }

   if(TIME_MODE == DS3231_TIME_MODE)
   {
    u8g2.setFont(u8g2_font_6x10_mf);
    u8g2.setCursor(67, 11);
    u8g2.print(dt.Year());
    
    u8g2.drawStr(91,11,".");
    
    u8g2.setCursor(97, 11);
    u8g2.print(dt.Month());
    
    u8g2.drawStr(109,11,".");

    u8g2.setCursor(115, 11);
    u8g2.print(dt.Day());

    u8g2.drawStr(0,63,"IP:");
    u8g2.setCursor(22, 63);
    u8g2.print(WiFi.localIP());

    u8g2.setFont(u8g2_font_wqy12_t_gb2312);
    u8g2.setCursor(112, 63);
    u8g2.print(num_week(dt.DayOfWeek()+1,4)); 
    
    u8g2.setFont(u8g2_font_inb21_mn );
    u8g2_uint_t strWidth0 = 3;
    u8g2_uint_t strWidth1 = u8g2.getUTF8Width(Hours);
    u8g2_uint_t strWidth2 = u8g2.getUTF8Width(Minutes);
    u8g2_uint_t strWidth4 = u8g2.getUTF8Width(":");
    u8g2.drawStr(strWidth0,45,Hours);
    u8g2.drawStr(strWidth1+strWidth0,43,":");
    u8g2.drawStr(strWidth1+strWidth4+strWidth0,45,Minutes);
    u8g2.setFont(u8g2_font_ncenR12_tf );
    u8g2_uint_t strWidth3 = u8g2.getUTF8Width(Seconds);
    u8g2_uint_t strWidth5 = u8g2.getUTF8Width(":");
    u8g2.drawStr(strWidth1+strWidth4+strWidth2+strWidth5+strWidth0,45,":");
    u8g2.drawStr(strWidth1+strWidth4+strWidth2+strWidth5*3+strWidth0,45,Seconds);
   }
   else if(TIME_MODE == NTP_TIME_MODE)
   {
        prevDisplay = now();
    u8g2.setFont(u8g2_font_6x10_mf);
    u8g2.setCursor(67, 11);
    u8g2.print(year());
    
    u8g2.drawStr(91,11,".");
    
    u8g2.setCursor(97, 11);
    if(month()>=10)
      u8g2.print(month());
    else{
      u8g2.print("0");
      u8g2.setCursor(104,11);
      u8g2.print(month());
    }
    
    u8g2.drawStr(109,11,".");

    u8g2.setCursor(115, 11);
    if(day()>=10)
      u8g2.print(day());
    else{
      u8g2.print("0");
      u8g2.setCursor(123,11);
      u8g2.print(day());
    }

    u8g2.drawStr(0,63,"IP:");
    u8g2.setCursor(22, 63);
    u8g2.print(WiFi.localIP());

    u8g2.setFont(u8g2_font_wqy12_t_gb2312);
    u8g2.setCursor(112, 63);
    u8g2.print(num_week(weekday(),4)); 
    
    u8g2.setFont(u8g2_font_inb21_mn );
    u8g2.setCursor(3,45);
    if(hour()>=10)
      u8g2.print(hour());
    else{
      u8g2.print("0");
      u8g2.setCursor(23,45);
      u8g2.print(hour());
    }
    u8g2.drawStr(42,43,":");
    u8g2.setCursor(60,45);
    if(minute()>=10)
      u8g2.print(minute());
    else{
      u8g2.print("0");
      u8g2.setCursor(80,45);
      u8g2.print(minute());
    }
    u8g2.setFont(u8g2_font_ncenR12_tf );
    u8g2.drawStr(100,45,":");
    u8g2.setCursor(110,45);
    if(second()>=10)
      u8g2.print(second());
    else{
      u8g2.print("0");
      u8g2.setCursor(120,45);
      u8g2.print(second());
    }
   }
   
    u8g2.sendBuffer();
}

//网络时间获取更新
void TIMER_GET(){
    prevDisplay = now();
    
    Serial.println("更新时间");
    Serial.print("网络时间是 : ");
    Serial.print(year());
    Serial.print(".");
    Serial.print(month());
    Serial.print(".");
    Serial.print(day());
    Serial.print(" ");
    Serial.print(hour());
    Serial.print(":");
    Serial.print(minute());
    Serial.print(":");
    Serial.print(second());
    Serial.print("     星期 ");
    Serial.println(num_week(weekday()-1,4));
    
    Clock.setClockMode(false);  // set to 24h
    Clock.setYear(year()-2000);
    Clock.setMonth(month());
    Clock.setDate(day());
    Clock.setDoW(weekday());
    Clock.setHour(hour());
    Clock.setMinute(minute());
    Clock.setSecond(second());
}

//无限升级程序
void BasicOTAINT(){
  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_FS
      type = "filesystem";
    }

    // NOTE: if updating FS this would be the place to unmount FS using FS.end()
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) {
      Serial.println("Auth Failed");
    } else if (error == OTA_BEGIN_ERROR) {
      Serial.println("Begin Failed");
    } else if (error == OTA_CONNECT_ERROR) {
      Serial.println("Connect Failed");
    } else if (error == OTA_RECEIVE_ERROR) {
      Serial.println("Receive Failed");
    } else if (error == OTA_END_ERROR) {
      Serial.println("End Failed");
    }
  });
  ArduinoOTA.begin();
  Serial.println("OTA Ready");
}

//保存WIFI信息到EEPEOM
void saveConfig(){   
  DebugPrintln("Save config!");   
  DebugPrint("stassid:");  
  DebugPrintln(config.stassid);  
  DebugPrint("stapsw:");   
  DebugPrintln(config.stapsw); 
  EEPROM.begin(1024);   
  uint8_t *p = (uint8_t*)(&config);   
  for (int i = 0; i < sizeof(config); i++){     
    EEPROM.write(i, *(p + i));   
    }   
    EEPROM.commit(); 
}
 
//从 EEPROM 读WIFI信息
void loadConfig(){   
  EEPROM.begin(1024);   
  uint8_t *p = (uint8_t*)(&config);   
  for (int i = 0; i < sizeof(config); i++){     
    *(p + i) = EEPROM.read(i);   
    }   
  EEPROM.commit();   
  DebugPrintln("-----Read config-----");   
  DebugPrint("stassid:");   
  DebugPrintln(config.stassid);   
  DebugPrint("stapsw:");   
  DebugPrintln(config.stapsw); 
}

//自 动 连 接 30s 超 过 之 后 自 动 进 入 SmartConfig 模 式
bool autoConfig(){
  WiFi.mode(WIFI_STA);     // 设 置 esp8266 工 作 模 式
  WiFi.begin(config.stassid,config.stapsw);
  //delay(2000);// 刚 启 动 模 块 的 话 延 时 稳 定 一 下
  DebugPrint("AutoConfiging");
  for(int index=0;index<100;index++){//连接20s
    int wstatus = WiFi.status();
    if (wstatus == WL_CONNECTED){
      DebugPrintln("\nAutoConfig Success");
      DebugPrint("SSID:");
      DebugPrintln(WiFi.SSID().c_str());
      DebugPrint("PSW:");
      DebugPrintln(WiFi.psk().c_str());
      return true;
    }else{
      DebugPrint(".");
      delay(200);
      flag = !flag;
      digitalWrite(LED, flag);
    } 
  }
      DebugPrintln("AutoConfig 失败!");
      return false; 
}

//开 启 SmartConfig 功 能
void smartConfig() {
  WiFi.mode(WIFI_STA);
  delay(1000);
  DebugPrintln("Wait for Smartconfig");
  WiFi.beginSmartConfig();

  Get_SmartConfig = LOW;//清标志位
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_wqy16_t_gb2312a);
  u8g2.setCursor(0, 36);
  u8g2.print("智能配网中......"); 
  u8g2.sendBuffer();
  
  while (true){
    DebugPrint(".");
    delay(200);
    flag = !flag;
    digitalWrite(LED, flag);
    
    if(WiFi.smartConfigDone()){
      //smartconfig 配 置 完 毕
     DebugPrintln("SmartConfig Success");
     DebugPrint("SSID:");
     DebugPrintln(WiFi.SSID().c_str());
     DebugPrint("PSW:");
     DebugPrintln(WiFi.psk().c_str());
     strcpy(config.stassid, WiFi.SSID().c_str());   
     strcpy(config.stapsw, WiFi.psk().c_str());
//     saveConfig(); 
     WiFi.mode(WIFI_AP_STA);
     // 设 置 esp8266 工 作 模 式
     WiFi.setAutoConnect(true);
     WiFi.setAutoReconnect(true);
     // 设 置 自 动 连 接
     u8g2.clearBuffer();
     u8g2.setFont(u8g2_font_wqy16_t_gb2312a);
     u8g2.setCursor(36, 16);
     u8g2.print("配网成功"); 
     u8g2.setCursor(0, 36);
     u8g2.print(WiFi.SSID().c_str());
     u8g2.setFont(u8g2_font_crox3t_tf );
     u8g2.setCursor(0, 60);
     u8g2.print(WiFi.psk().c_str()); 
     u8g2.sendBuffer();
     LastSmartConfig = millis();
     WIFI_MODE = 1;  
     break;  
     }

     ESP.wdtFeed();// 喂 狗   
   }
}

//发 送 请 求 指 令
bool sendRequest(const char* host, const char* cityid, const char* apiKey) {
  // We now create a URI for the request   
  // 心 知 天 气
   String GetUrl = "/v3/weather/now.json?key=";   
   GetUrl += apiKey;
   GetUrl += "&location=";
   GetUrl += city;
   GetUrl += "&language=";
   GetUrl += language;
   // This will send the request to the server
   client.print(String("GET ") + GetUrl + " HTTP/1.1\r\n" + 
                "Host: " + host + "\r\n" +
                "Connection: close\r\n\r\n");
   DebugPrintln("create a request:");
   DebugPrintln(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
                "Host: " + host + "\r\n" +
                "Connection: close\r\n");
   delay(1000);
   return true; 
}

//Desc 跳 过 HTTP 头 , 使 我 们 在 响 应 正 文 的 开 头
bool skipResponseHeaders(){
  // HTTP headers end with an empty line
  bool ok = client.find(endOfHeaders);
  if(!ok){
    DebugPrintln("No response or invalid response!");
    }
    return ok;
}

//Desc 从 HTTP 服 务 器 响 应 中 读 取 正 文
void readReponseContent(char* content, size_t maxSize){
  size_t length = client.readBytes(content, maxSize);
  delay(100);
  DebugPrintln("Get the data from Internet!");
  content[length] = 0;
  DebugPrintln(content);
  DebugPrintln("Read data Over!");
  client.flush();
  // 这 句 代 码 需 要 加 上  不 然 会 发 现 每 隔 一 次 client.find 会 失 败
 }
 
 // 关 闭 与 HTTP 服 务 器 连 接
 void stopConnect(){
  client.stop(); 
}   

void clrEsp8266ResponseBuffer(void){
  memset(response, 0, MAX_CONTENT_SIZE);// 清 空
}

bool parseUserData(char* content, struct UserData* userData){
//    -- 根 据 我 们 需 要 解 析 的 数 据 来 计 算 JSON 缓 冲 区 佳 大 小
//   如 果 你 使 用 StaticJsonBuffer 时 才 需 要
//    const size_t BUFFER_SIZE = 1024; 
//   在 堆 栈 上 分 配 一 个 临 时 内 存 池
//    StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
//    -- 如 果 堆 栈 的 内 存 池 太 大 , 使 用 DynamicJsonBuffer jsonBuffer 代 替
   DynamicJsonBuffer jsonBuffer;
   
   JsonObject& root = jsonBuffer.parseObject(content);
   if (!root.success()){
    Serial.println("JSON parsing failed!");
    return false;
    }       
    // 复 制 我 们 感 兴 趣 的 字 符 串
   strcpy(userData->city, root["results"][0]["location"]["name"]);
   strcpy(userData->weather_code, root["results"][0]["now"]["code"]);
   strcpy(userData->temp, root["results"][0]["now"]["temperature"]);
   //  -- 这 不 是 强 制 复 制 , 你 可 以 使 用 指 针 , 因 为 他 们 是 指 向 “ 内 容 ” 缓 冲 区 内 , 所 以 你 需 要 确 保
   //   当 你 读 取 字 符 串 时 它 仍 在 内 存 中
   return true;
}

// 根 据 天 气 接 口 返 回 的 数 据 判 断 显 示
void showWeather(struct UserData* userData){
  if(strcmp(userData->weather_code,WEATHER_CODE_DAY_SUN) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_DAY_SUN1) == 0){
    drawWeather(SUN_DAY,userData->temp,userData->city);
  }else if(strcmp(userData->weather_code,WEATHER_CODE_NIGHT_SUN) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_NIGHT_SUN2) == 0 ){
    drawWeather(SUN_NIGHT,userData->temp,userData->city);
  }else if(strcmp(userData->weather_code,WEATHER_CODE_DAY_PARTLY_CLOUDY) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_NIGHT_PARTLY_CLOUDY)== 0){
    drawWeather(SUN_CLOUD,userData->temp,userData->city);
  }else if(strcmp(userData->weather_code,WEATHER_CODE_CLOUDY) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_DAY_MOSTLY_CLOUDY) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_NIGHT_MOSTLY_CLOUDY) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_OVERCAST) == 0){
    drawWeather(CLOUD,userData->temp,userData->city);
  }else if(strcmp(userData->weather_code,WEATHER_CODE_SHOWER) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_LIGHT_RAIN) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_MODERATE_RAIN) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_HEAVY_RAIN) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_STORM) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_HEAVY_STORM) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_SEVERE_STORM) == 0){
    drawWeather(RAIN,userData->temp,userData->city);
  }else if(strcmp(userData->weather_code,WEATHER_CODE_THUNDERSHOWER) == 0
  || strcmp(userData->weather_code,WEATHER_CODE_THUNDERSHOWER_WITH_HAIL) == 0){
    drawWeather(THUNDER,userData->temp,userData->city);
  }else{drawWeather(CLOUD,userData->temp,userData->city);
  } 
}

void drawWeather(uint8_t symbol, char* degree,char* city){
  //DebugPrintln(city);
  // 绘 制 天 气 符 号
  drawWeatherSymbol(0, 16, symbol); 
  // 绘 制 温 度
  u8g2.setFont(u8g2_font_9x15_t_symbols);
  u8g2.setCursor(20, 13);
  u8g2.print(degree);
  u8g2.print("°C");
}

// 绘 制 天 气 符 号
void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol) {
  // fonts used:
  // u8g2_font_open_iconic_embedded_6x_t
  // u8g2_font_open_iconic_weather_6x_t
  // encoding values, see: https://github.com/olikraus/u8g2/wiki/fntgrpiconic 
  switch(symbol)
  {
    case SUN_DAY:// 太 阳
       u8g2.setFont(u8g2_font_open_iconic_weather_2x_t); 
       u8g2.drawGlyph(x, y, 69);
       break;
    case SUN_NIGHT:// 太 阳
       u8g2.setFont(u8g2_font_open_iconic_weather_2x_t);
       u8g2.drawGlyph(x, y, 66);
       break;
    case SUN_CLOUD:// 晴 间 多 云
       u8g2.setFont(u8g2_font_open_iconic_weather_2x_t);
       u8g2.drawGlyph(x, y, 65);
       break;
    case CLOUD:// 多 云
       u8g2.setFont(u8g2_font_open_iconic_weather_2x_t);
       u8g2.drawGlyph(x, y, 64);
       break;
    case RAIN:// 下 雨
       u8g2.setFont(u8g2_font_open_iconic_weather_2x_t);
       u8g2.drawGlyph(x, y, 67);
       break;
    case THUNDER:// 打 雷
       u8g2.setFont(u8g2_font_open_iconic_embedded_2x_t);
       u8g2.drawGlyph(x, y, 67);
       break;         
   } 
}


//WS2812 RGB点阵初始化
void WS2812_INT(void){
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
  FastLED.setBrightness( BRIGHTNESS );
}

//WS2812 RGB点阵屏XY转地址函数(XY->i)  使用时可直接调用下面的RGBXYsafe
uint16_t RGBXY( uint8_t x, uint8_t y)
{
  uint16_t i;
  
  if( kMatrixSerpentineLayout == false) {
    i = (x * kMatrixWidth) + y;
  }

  if( kMatrixSerpentineLayout == true) {
    if( x & 0x01) {
      // Odd rows run backwards
      uint8_t reverseY = (kMatrixWidth - 1) - y;
      i = (x * kMatrixWidth) + reverseY;
    } else {
      // Even rows run forwards
      i = (x * kMatrixWidth) + y;
    }
  }
  
  return i;
}

//WS2812 RGB点阵屏XY 判断输入XY是否超出最大值 超出返回-1 此时设置点阵不显示
uint16_t RGBXYsafe( uint8_t x, uint8_t y)
{
  if( x >= kMatrixHeight||y >= kMatrixWidth) return RGBXY(x+1-kMatrixHeight,y+1-kMatrixWidth);
  else return RGBXY(x,y);
}

//RGB写字符函数
void RGB_ShowChar(uint8_t x,uint8_t y,uint8_t chr){
  unsigned char c=0,i=0;
  int BCD[8]={};
  c=chr-' ';//得到偏移后的值 //也就是字符对应的 ASCII表 的数字值     
  if(x>kMatrixHeight-1)x=0; //最大32
  if(y>kMatrixWidth-1) y=0;  //最大8
  for(i=0;i<6;i++){
    FONT_16_2(F6x8[c][i],&BCD[0]);
    //DebugPrintln();
    for(int j=0;j<8;j++){
      if(BCD[j]==0){
        //DebugPrint("   ");
        leds[ RGBXYsafe(x+i, y+7-j)] = CHSV( 0, 255, 0);
      }
      else{
        //DebugPrint(" @ ");
        leds[ RGBXYsafe(x+i, y+7-j)] = CHSV( 120, 255, 255);
      }
    }
  }
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.show();
  //DebugPrintln();
}

//RGB显示字符串
void RGB_ShowString(uint8_t x,uint8_t y,const char *chr){
  uint8_t j=0;
  while (chr[j]!='\0'){
    RGB_ShowChar(x,y,chr[j]);
      x+=6;
    if(x>32){x=0;y=0;}
      j++;
    delay(1);
    ESP.wdtFeed();// 喂 狗
  }
}

//RGB显示数字
void RGB_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len){
  uint8_t t,tp;
  uint8_t enshow=0;               
  for(t=0;t<len;t++)//每次取一个数字显示
  {
    //转化数组ACIIC 到字符ACIIC 后面加了个'0'
    tp=(num/RGB_POW(10,len-t-1))%10;
    if(enshow==0&&t<(len-1))
    {
      if(tp==0)
      {
        RGB_ShowChar(x+6*t,y,'0');
        continue;
      }else enshow=1;  
    }
    RGB_ShowChar(x+6*t,y,tp+48);//tp+'0'
  }
}

//十六进制转数组
void FONT_16_2(const unsigned char chr,int *point){
   int a=chr;
   *point= a/128;
   a=a-128*(*point);point++;
   *point= a/64;
   a=a-64*(*point);point++;
   *point= a/32;
   a=a-32*(*point);point++;
   *point= a/16;
   a=a-16*(*point);point++;
   *point= a/8;
   a=a-8*(*point);point++;
   *point= a/4;
   a=a-4*(*point);point++;
   *point= a/2;
   a=a-2*(*point);point++;
   *point= a;
}

//RGB  m^n 
int RGB_POW(char m,char n){
  int result = 1;
  while(n--){
    result*=m;
    ESP.wdtFeed();// 喂 狗
  }
  return result;
}

//开机动画
void Boot_animation(){
  u8g2.firstPage();
  do
  {
  u8g2.drawXBMP(20,0,89,64,FACE_Neutral);
  }
  while (u8g2.nextPage());
  delay(800);
  u8g2.firstPage();
  do
  {
  u8g2.drawXBMP(20,0,89,64,FACE_Tired_middle);
  }
  while (u8g2.nextPage());
  delay(200);
  u8g2.firstPage();
  do
  {
  u8g2.drawXBMP(20,0,89,64,FACE_Neutral);
  }
  while (u8g2.nextPage());
  delay(1500);
  u8g2.firstPage();
  do
  {
  u8g2.drawXBMP(20,0,89,64,FACE_Tired_middle);
  }
  while (u8g2.nextPage());
  delay(200);
  u8g2.firstPage();
  do
  {
  u8g2.drawXBMP(20,0,89,64,FACE_Neutral);
  }
  while (u8g2.nextPage());
  delay(800);
  u8g2.firstPage();
  do
  {
  u8g2.drawXBMP(20,0,89,64,FACE_Love);
  }
  while (u8g2.nextPage());
  delay(500);

  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_cupcakemetoyourleader_tr);
    u8g2.drawStr(50,36,"Weather");
    u8g2.setFont(u8g2_font_open_iconic_all_6x_t);
    u8g2.drawGlyph(0, 52, 187);
  } while ( u8g2.nextPage() );
}

/*-------- NTP code ----------*/

const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

time_t getNtpTime()
{
  IPAddress ntpServerIP; // NTP server's ip address

  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  // get a random server from the pool
  WiFi.hostByName(ntpServerName, ntpServerIP);
  Serial.print(ntpServerName);
  Serial.print(": ");
  Serial.println(ntpServerIP);
  sendNTPpacket(ntpServerIP);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}

// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

weather.h文件

//************************是 否 开 启 debug 功 能*******************************
#define DEBUG 

#ifdef DEBUG 
#define DebugPrintln(message) Serial.println(message)
#else 
#define DebugPrintln(message)
#endif

#ifdef DEBUG 
#define DebugPrint(message) Serial.print(message) 
#else 
#define DebugPrint(message)
#endif

//*******************************GPIO配置**************************************
#define LED      D4 //gpio2
#define LED_PIN  8  //gpio15 RGB

#define UP_KEY   D6 //gpio12
#define M_KEY    D5 //gpio14
#define DOWN_KEY D7 //gpio13
#define WAKE_UP  D3 //gpio0

#define KEYU  digitalRead(UP_KEY)
#define KEYM  digitalRead(M_KEY)
#define KEYD  digitalRead(DOWN_KEY)
#define KEYW  digitalRead(WAKE_UP)

#define UP_KEY_PRES     1
#define M_KEY_PRES      2
#define DOWN_KEY_PRES   3
#define WAKE_UP_PRES    4

#define UP_KEY_LONG_PRES     11
#define M_KEY_LONG_PRES      22
#define DOWN_KEY_LONG_PRES   33
#define WAKE_UP_LONG_PRES    44

uint8_t TIME_MODE = 1;
#define DS3231_TIME_MODE  1
#define NTP_TIME_MODE     2

//***********************************设置RGB灯*************************************
#define COLOR_ORDER GRB
#define CHIPSET     WS2811
#define BRIGHTNESS 60    //设置RGB亮度
const uint8_t kMatrixWidth =  8;//高Y
const uint8_t kMatrixHeight = 32;//宽X
const bool    kMatrixSerpentineLayout = true;//true为S形点阵 false为一字形
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)

//*******************************定义时间结构体变量TIME****************************
struct TIME_CONFIG{
  uint8_t weeks;
  uint8_t years;
  uint8_t months;
  uint8_t days;
  uint8_t hours;
  uint8_t minutes;
  uint8_t seconds;
}TIME;

// **********************************天气数据*********************************
struct UserData {   
  char city[16];// 城 市 名 称
  char weather_code[4];// 天 气 现 象 code ( 多 云 ...)
  char temp[5];//温 度
}; 
UserData userData;

//*********************************wifi结构体********************************
struct config_type{   
  char stassid[32];   
  char stapsw[64]; 
}config; 

//********************************定义页码&光标*******************************

struct page_define{   
  char name[32];                  //当前页码名称
  uint8_t cursor = 1;             //此时光标所在行数
  uint8_t rows = 1;               //共有多少行
  long refresh_time = 1*100;      //设置模式OLED刷新时间间隔
  long time = 0;                  //页面时间
}set_up_page,Desktop_Set_page;
  
#ifndef __GETWEATHER_H
#define __GETWEATHER_H

//******************************定义气象种类***********************************
 #define WEATHER_CODE_DAY_SUN "0" // 晴 ( 国 内 城 市 白 天 晴 )
 #define WEATHER_CODE_NIGHT_SUN "1" // 晴 ( 国 内 城 市 夜 晚 晴 )
 #define WEATHER_CODE_DAY_SUN1 "2" // 晴 ( 国 外 城 市 白 天 晴 )
 #define WEATHER_CODE_NIGHT_SUN2 "3" // 晴 ( 国 外 城 市 夜 晚 晴 )
 #define WEATHER_CODE_CLOUDY "4" // 多 云
 #define WEATHER_CODE_DAY_PARTLY_CLOUDY "5" // 白 天 晴 间 多 云
 #define WEATHER_CODE_NIGHT_PARTLY_CLOUDY "6" // 夜 晚 晴 间 多 云
 #define WEATHER_CODE_DAY_MOSTLY_CLOUDY "7" // 白 天 大 部 多 云
 #define WEATHER_CODE_NIGHT_MOSTLY_CLOUDY "8" // 夜 晚 大 部 多 云
 #define WEATHER_CODE_OVERCAST "9" // 阴
 #define WEATHER_CODE_SHOWER "10" // 阵 雨
 #define WEATHER_CODE_THUNDERSHOWER "11" // 雷 阵 雨
 #define WEATHER_CODE_THUNDERSHOWER_WITH_HAIL "12" // 雷 阵 雨 伴 有 冰 雹
 #define WEATHER_CODE_LIGHT_RAIN "13" // 小 雨
 #define WEATHER_CODE_MODERATE_RAIN "14" // 中 雨
 #define WEATHER_CODE_HEAVY_RAIN "15" // 大 雨
 #define WEATHER_CODE_STORM "16" // 暴 雨
 #define WEATHER_CODE_HEAVY_STORM "17" // 大 暴 雨
 #define WEATHER_CODE_SEVERE_STORM "18" // 特 大 暴 雨
 #define WEATHER_CODE_ICE_RAIN "19" // 冻 雨
 #define WEATHER_CODE_SLEET "20" // 雨 夹 雪
 #define WEATHER_CODE_SNOW_FLURRY "21" // 阵 雪
 #define WEATHER_CODE_LIGHT_SNOW "22" // 小 雪
 #define WEATHER_CODE_MODERATE_SNOW "23" // 中 雪
 #define WEATHER_CODE_HEAVY_SNOW "24" // 大 雪
 #define WEATHER_CODE_SNOW_STORM "25" // 暴 雪
 
//******************************定义天气的类型******************************** 
#define SUN_DAY 0 
#define SUN_NIGHT 1 
#define SUN_CLOUD 2 
#define CLOUD 3 
#define RAIN 4 
#define THUNDER 5

#endif


//****************************配置RGB点阵显示函数*****************************
void WS2812_INT(void);
uint16_t RGBXY( uint8_t x, uint8_t y);
uint16_t RGBXYsafe( uint8_t x, uint8_t y);
void RGB_ShowChar(uint8_t x,uint8_t y,uint8_t chr);
void RGB_ShowString(uint8_t x,uint8_t y,const char *chr);
void RGB_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len);
int RGB_POW(char m,char n);
void FONT_16_2(const unsigned char chr,int *point);

//*******************************网络设置函数********************************
bool autoConfig(); 
void smartConfig();
void saveConfig();
void loadConfig();
//外设驱动函数
uint8_t KEY_Scan(uint8_t mode);
void offDisplay();

//**************************获取天气 解析 显示函数****************************
bool sendRequest(const char* host, const char* cityid, const char* apiKey); 
bool skipResponseHeaders(); 
void readReponseContent(char* content, size_t maxSize); 
void stopConnect(); 
void clrEsp8266ResponseBuffer(void); 
bool parseUserData(char* content, struct UserData* userData); 
void drawWeatherSymbol(u8g2_uint_t x, u8g2_uint_t y, uint8_t symbol); 
void drawWeather(uint8_t symbol, int degree);

//*********************************扫描时间(ms)*******************************
long LastWeatherTime = 0;//获取天气
long LastRtcTime = 0; //从DS3231读时间
long LastNTPTime = 0;//从网络获取时间
long LastSmartConfig = 0;//智能配网时间
long set_mode_time = 0; //设置模式OLED刷新时间间隔
long ntpget = 0;        //网络时间

long up_pres_time = 0;
long m_pres_time = 0;
long down_pres_time = 0;
long wake_pres_time = 0;

// 请 求 服 务 间 隔
long WeatherDelay = 5*60*1000;   //天气获取周期(ms)
long RtcDelay = 1*1000;           //时钟获取周期(ms)
long openOledTime = 5*1000;      //每次亮屏时间(ms)
long key_long_pres_time = 1.2*1000;//按键长时间按下时间
long set_mode_refresh_time = 1*100;//设置界面刷新时间(ms)
long NTPGET = 1*1000;            //网络时间更新时间

//*****************************************************************************
uint8_t Cursor_position = 1;                           //此时光标所在行数
uint8_t Number_of_rows = 1;                            //共有多少行
uint8_t OLED_Brightness = 200;                         //设置OLED显示屏亮度
const unsigned long BAUD_RATE = 115200;                // 波特率
const unsigned long HTTP_TIMEOUT = 5000;               // max respone time from server 
const size_t MAX_CONTENT_SIZE = 500;                   // max size of the HTTP response 
const char* host = "api.seniverse.com";                        //心知天气官网
const char* APIKEY = "umsnxrv2snsd68t3";                       //用户API KEY
const char* city = "xian";                                     //城市
const char* citys[3] = {"xian","shenzhen","weinan"};           //城市列表
const char* language = "zh-Hans";             //zh-Hans
char response[MAX_CONTENT_SIZE]; 
char endOfHeaders[] = "\r\n\r\n";

//****************************************************************************

//**********************************默认WIFI信息*******************************
char ssid[] = "liuzewen";
char pswd[] = "17609245102liu";

//***************************************************************************
bool flag = HIGH;// 默 认 当 前 灭 灯
bool Get_NTPclient = 0;//是否获取NTPclient标志位
bool Get_SmartConfig = 0;//是否配网标志位
bool WIFI_MODE = 0;//是否有网络
bool OTA_MODE = 0;//判断是否无线升级程序
bool U8G2_OLED_R = 0;//设置显示器方向
//***************************************************************************

//**************************************表情**********************************
const static unsigned char FACE_Love[] PROGMEM ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x00,0x00,0x00,0xFC,0xFF,0x3F,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x03,0x00,0x80,0xFF,0xFF,0xFF,0x01,0x00,0x80,0xFF,0xFF,0xFF,0x0F,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0xC0,0x07,0x00,0x00,0x1F,0x00,0xE0,0x03,0x00,0xC0,0x07,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x0F,0x00,0xE0,0x00,0x00,0x00,0x38,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0xE0,0x07,0x3F,0xE0,0x00,0x0C,0xF0,0x81,0x0F,0x30,0x00,0x38,0xF0,0x8B,0x5F,0xE0,0x00,0x0C,0xF8,0xC2,0x1F,0x30,0x00,0x38,0xF8,0xD7,0xBF,0xE0,0x00,0x0C,0xFC,0xE5,0x2F,0x30,0x00,0x38,0xF8,0xFF,0xBF,0xE0,0x00,0x0C,0xFE,0xFF,0x5F,0x30,0x00,0x38,0xFC,0xFF,0x7F,0xE0,0x00,0x0C,0xFE,0xFF,0x5F,0x30,0x00,0x38,0xFC,0xFF,0xFF,0xE1,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xFC,0xFF,0xFF,0xE1,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xFC,0xFF,0xFF,0xE1,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xF8,0xFF,0xFF,0xE0,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xF8,0xFF,0xFF,0xE0,0x00,0x0C,0xFE,0xFF,0x7F,0x30,0x00,0x38,0xF8,0xFF,0xFF,0xE0,0x00,0x0C,0xFC,0xFF,0x3F,0x30,0x00,0x38,0xF0,0xFF,0x7F,0xE0,0x00,0x0C,0xF8,0xFF,0x1F,0x30,0x00,0x38,0xC0,0xFF,0x1F,0xE0,0x00,0x0C,0xF0,0xFF,0x0F,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xE0,0xFF,0x07,0x30,0x00,0x38,0x00,0xFF,0x07,0xE0,0x00,0x0C,0xC0,0xFF,0x03,0x30,0x00,0x38,0x00,0xFE,0x03,0xE0,0x00,0x0C,0x80,0xFF,0x01,0x30,0x00,0x38,0x00,0xFC,0x01,0xE0,0x00,0x0C,0x00,0x7E,0x00,0x30,0x00,0x38,0x00,0xF8,0x00,0xE0,0x00,0x0C,0x00,0x3C,0x00,0x30,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x38,0x00,0x20,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x3C,0x00,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x78,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0xC0,0x03,0x00,0x00,0x1E,0x00,0xF0,0x01,0x00,0x80,0x0F,0x00,0x80,0x1F,0x00,0xC0,0x0F,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0x00,0xFF,0xFF,0xFF,0x07,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0x00,0xFC,0xFF,0xFF,0x01,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };

const static unsigned char FACE_Neutral[] PROGMEM ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x00,0x00,0x00,0xFC,0xFF,0x3F,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x03,0x00,0x80,0xFF,0xFF,0xFF,0x01,0x00,0x80,0xFF,0xFF,0xFF,0x0F,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0xC0,0x07,0x00,0x00,0x1F,0x00,0xE0,0x03,0x00,0xC0,0x07,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x0F,0x00,0xE0,0x00,0x00,0x00,0x38,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x84,0x00,0xE0,0x00,0x0C,0x00,0x41,0x00,0x30,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0x0C,0x00,0x38,0x01,0x30,0x00,0x38,0x00,0xFC,0x01,0xE0,0x00,0x0C,0x00,0x7F,0x00,0x30,0x00,0x38,0x00,0xFE,0x03,0xE0,0x00,0x0C,0xA0,0xFF,0x05,0x30,0x00,0x38,0x00,0x7F,0x06,0xE0,0x00,0x0C,0x80,0x3F,0x01,0x30,0x00,0x38,0x40,0x7F,0x17,0xE0,0x00,0x0C,0xC0,0xDF,0x03,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xD0,0xFF,0x0B,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xC0,0xFF,0x03,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xD0,0xFF,0x0B,0x30,0x00,0x38,0x00,0xFF,0x07,0xE0,0x00,0x0C,0xC0,0xFF,0x03,0x30,0x00,0x38,0x40,0xFF,0x17,0xE0,0x00,0x0C,0x80,0xFF,0x01,0x30,0x00,0x38,0x00,0xFE,0x03,0xE0,0x00,0x0C,0xA0,0xFF,0x05,0x30,0x00,0x38,0x00,0xFC,0x01,0xE0,0x00,0x0C,0x00,0xFF,0x00,0x30,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0x0C,0x80,0x3C,0x01,0x30,0x00,0x38,0x00,0x84,0x00,0xE0,0x00,0x0C,0x00,0x42,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x3C,0x00,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x78,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0xC0,0x03,0x00,0x00,0x1E,0x00,0xF0,0x01,0x00,0x80,0x0F,0x00,0x80,0x1F,0x00,0xC0,0x0F,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0x00,0xFF,0xFF,0xFF,0x07,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0x00,0xFC,0xFF,0xFF,0x01,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };

const static unsigned char FACE_Tired_middle[] PROGMEM ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0xFF,0x00,0x00,0x00,0xFC,0xFF,0x3F,0x00,0x00,0x00,0xFE,0xFF,0xFF,0x03,0x00,0x80,0xFF,0xFF,0xFF,0x01,0x00,0x80,0xFF,0xFF,0xFF,0x0F,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0xC0,0x07,0x00,0x00,0x1F,0x00,0xE0,0x03,0x00,0xC0,0x07,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0xF0,0x00,0x00,0x00,0x0F,0x00,0xE0,0x00,0x00,0x00,0x38,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x70,0x00,0x00,0x00,0x70,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x30,0x00,0x38,0x00,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x38,0x00,0xF8,0xFF,0xFF,0xFF,0xFF,0x00,0xFC,0xFF,0xFF,0xFF,0x3F,0x00,0xF8,0xFF,0xFF,0xFF,0xFF,0x00,0xFC,0xFF,0xFF,0xFF,0x3F,0x00,0x38,0x40,0xFF,0x17,0xE0,0x00,0x1C,0xD0,0xDF,0x0B,0x38,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xC0,0xFF,0x0B,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xD0,0xFF,0x03,0x30,0x00,0x38,0x80,0xFF,0x0F,0xE0,0x00,0x0C,0xD0,0xFF,0x0B,0x30,0x00,0x38,0x00,0xFF,0x07,0xE0,0x00,0x0C,0xC0,0xFF,0x03,0x30,0x00,0x38,0x40,0xFF,0x17,0xE0,0x00,0x0C,0x80,0xFF,0x01,0x30,0x00,0x38,0x00,0xFE,0x03,0xE0,0x00,0x1C,0xA0,0xFF,0x05,0x38,0x00,0x70,0x00,0xFC,0x01,0x70,0x00,0x1C,0x00,0xFF,0x00,0x38,0x00,0x70,0x00,0x70,0x00,0x70,0x00,0x3C,0x80,0x3C,0x01,0x3C,0x00,0xF0,0x00,0x84,0x00,0x78,0x00,0x38,0x00,0x42,0x00,0x1C,0x00,0xE0,0x01,0x00,0x00,0x3C,0x00,0x78,0x00,0x00,0x00,0x1E,0x00,0xC0,0x03,0x00,0x00,0x1E,0x00,0xF0,0x01,0x00,0x80,0x0F,0x00,0x80,0x1F,0x00,0xC0,0x0F,0x00,0xE0,0x07,0x00,0xE0,0x07,0x00,0x00,0xFF,0xFF,0xFF,0x07,0x00,0xC0,0xFF,0xFF,0xFF,0x03,0x00,0x00,0xFC,0xFF,0xFF,0x01,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };

font.h文件

//常用ASCII表
//偏移量32
//ASCII字符集
//偏移量32
//大小:12*6
/************************************6*8的点阵************************************/
const unsigned char  F6x8[][6] =    
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// (
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// )
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// *
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// ,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// .
0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// /
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// <
0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// >
0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W
0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X
0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y
0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ]
0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// '
0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines
};

//天气图标/* (12 X 8 ) */
const unsigned char  Weather[][12] ={
0x60,0xF0,0xF8,0xF8,0xF8,0xFE,0xFF,0xFF,0xFE,0xF8,0xF0,0x60//云
};
  • 看下效果吧~

发布了3 篇原创文章 · 获赞 9 · 访问量 471

猜你喜欢

转载自blog.csdn.net/qq_41868901/article/details/104225816