硬件电路:
- 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//云
};
- 看下效果吧~