NodeMcu arduino ESP8266 使用u8g2图形库 在096 oled 显示

NodeMcu U8g2库的使用

NodeMcu arduino ESP8266 使用U8g2库 在096 oled 显示


文章目录

  • NodeMcu U8g2库的使用
  • 一、U8g2库是什么?
    • 2.U8g2库函数
  • 二、使用步骤
    • 1. 下载库
    • 2.引入库
    • 3.接线 096 oled 12864
    • 示例 04-ESP8266简易WIFI天气时钟
  • 总结


提示:以下是本篇文章正文内容,下面案例可供参考

一、U8g2库是什么?

U8g2 是一个用于嵌入式设备的单色图形库。U8g2支持单色OLED和LCD,并支持如SSD1306等多种类型的OLED驱动。

U8g2源码的开源库地址:https://github.com/olikraus/u8g2
U8g2专为Arduino提供的方便安装的库地址:https://github.com/olikraus/U8g2_Arduin

2.U8g2库函数

U8g2库在loop中的通用写法是使用do{}while()的形式:

void loop(void) {
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB10_tr);
    u8g2.drawStr(0,24,"Hello new World!");
  } while ( u8g2.nextPage() );
  //delay(1000);
}

setFont(font) 设置字体
font:u8g2的字体,比较常用的有u8g2_font_unifont_t_symbols(通常使用这个)和u8g2_font_wqy12_t_gb2312b(用于显示汉字)等

setFontMode(num) 设置字体背景颜色模式
num:启用(1)透明模式
num:禁用(0)透明模式

setDrawColor(color) 设置所有绘图函数的位值
color:0(显示RAM中的清晰像素值)
color:1(设置像素值)
color:2(异或模式)

u8g2.begin( ) //开始构造U8G2, 在setup()内使用。 特别说明:初始化在Arduino的环境。 配置OLED的显示模式initDiplay或者省电模式setPowerSave,或者重置(清屏)clearDisplay 。同时检测六个按钮程序(比如前进、后退、确认、上一级…)。如果没有,可以在里定义按钮事件的引脚,用GetMenuEvent函数来定义,来进入到用户想要的界面,详情就看userInterfaceMessage和GetMenuEvent函数。无返回值。
关联使用函数:initDispaly 、setPowersave、clearDisplay

u8g2.clear() // 清除缓冲区"Buffer"内的所有像素点
关联使用函数:print、home、clearBuffer

u8g2.clearBuffer() //清除内存中的所有缓冲区内的像素,而后可以用sendBuffer函数来把缓冲区“Buffer”在屏幕上显示出来,以便清屏。因这个过程是在微处理器中RAM里的副本"Buffer"中进行,标志“F”,所以sendBuffer也就是直接操作副本“Buffer”

void loop(void) {
u8g2.clearBuffer();   //清除当前Buffer内的像素
                           // 在Buffer内一些操作 
u8g2.sendBuffer();    //发送Buffer内容到屏上
delay(1000);

u8g2.enableUTF8Print () //启用 UTF8字集,许可UniCode向print发送字符串。这个函数通常在begin()后调用。
关联使用函数:print、disableUTF8Print

u8g2.disableUTF8Print() //禁用 UTF8字集 (万国语字库),默认是开启的。关联使用函数:print 、enableUTF8Print

u8g2.clearDisplay() //清除显示中所有像素。此过程在begin()中调用。在程序中一般用不上,也是通过sendBuffer和clearBuffer函数显示出来,一样的处理方式。
关联使用函数:begin

u8g2.Print() //在入当前光标位置用当前设置的字体,来打印出(内容)。光标位置可以用setCursor函数。字体可以用setFont函数。
关联使用函数:print(U8x8)、enableUTF8Print、setFont、setCursor、

NodeMcu arduino ESP8266 使用u8g2图形库 在096 oled 显示_第1张图片

二、使用步骤

1. 下载库

Arduino IDE 库 安装 U8g2,或者网盘下载加载库U8g2。

方案1
NodeMcu arduino ESP8266 使用u8g2图形库 在096 oled 显示_第2张图片

方案2
NodeMcu arduino ESP8266 使用u8g2图形库 在096 oled 显示_第3张图片

2.引入库

代码如下(示例):

#include 
#include 
#include 

//定义了一个宏定义,用于延时显示每一次的画图,方便观察OLED的显示过程:
#define SEND_BUFFER_DISPLAY_MS(ms)\

U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ D5, /* data=*/ D6, /* reset=*/ U8X8_PIN_NONE);   // All Boards without Reset of the Display

void setup(void) {

 
  u8g2.begin();  
}

void loop(void) {
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB10_tr);
    u8g2.drawStr(0,24,"Hello new World!");
  } while ( u8g2.nextPage() );
  //delay(1000);
}

U8g2库各类画图函数测试实例 ,绘画线,点,图形,图标,图片

/************************************************************
  ===================U8g2库各类画图函数测试实例==================
  Author:码农爱学习
  Date: 2022/03/06
  Version: V1.0
  Blog: https://xxpcb.gitee.io/
  BiliBili: https://space.bilibili.com/146899653
  ------------------------------------------------------------
  硬件:ESP8266 NodeMCU + 12864 SSD1306 OLED显示屏(4pin IIC引脚)
  接线:[ESP8266]  --- [OLED]
       3.3V     ---  VCC
       G (GND)  ---  GND
       D1(GPIO5)---  SCL
       D2(GPIO4)---  SDA
************************************************************/

#include 
#include 

//#define SCL 5
//#define SDA 4
//
//U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/SCL, /*data=*/SDA, /*reset=*/U8X8_PIN_NONE);   // All Boards without Reset of the Display


U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ D5, /* data=*/ D6, /* reset=*/ U8X8_PIN_NONE);   // All Boards without Reset of the Display

#define SEND_BUFFER_DISPLAY_MS(ms)\
  do {\
    u8g2.sendBuffer(); \
    delay(ms);\
  }while(0);

void initOLED();

void testDrawPixelFun();
void testDrawLineFun();
void testDrawTriangleFun();
void testDrawRectangleFun();
void testDrawCircleFun();
void testDrawEllipseFun();
void testGlyphFun();
void testDrawStrFun();
void testDrawXBMFun();

void testDrawBattery();


void setup()
{
  Serial.begin(9600);
  initOLED();
}

void loop()
{
  u8g2.firstPage();
  do
  {
    testDrawPixelFun(); //画像素点测试
    testDrawLineFun(); //画线测试
    testDrawTriangleFun(); //画三角形测试
    testDrawRectangleFun(); //画矩形测试
    testDrawCircleFun(); //画圆测试
    testDrawEllipseFun(); //画椭圆测试
    testGlyphFun(); //画图标测试
    testDrawStrFun(); //字符、汉字、变量显示测试
    u8g2.setFont(u8g2_font_unifont_t_symbols);
    testDrawBattery(); //画电池
    testDrawXBMFun(); //画自定义图片
  } while (u8g2.nextPage());
  delay(1000);
}

void initOLED()
{
  u8g2.begin();
  u8g2.setFont(u8g2_font_unifont_t_symbols);
}

画像素点

//画像素点-填充屏幕
void testDrawPixelToFillScreen()
{
  int t = 1000;
  u8g2.clearBuffer();
 
  for (int j = 0; j < 64; j++)
  {
    for (int i = 0; i < 128; i++)
    {
      u8g2.drawPixel(i, j);
    }
  }
  SEND_BUFFER_DISPLAY_MS(t);
}

//画直线

//画直线
void testDrawLine()
{
  int t = 500;
  u8g2.clearBuffer();
  u8g2.drawStr(33, 14, "drawLine");
 
  u8g2.drawLine(0, 0, 127, 63);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(0, 0, 127, 0);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(32, 15, 127, 15);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(33, 16, 127, 16);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(127, 0, 127, 15);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawLine(127, 16, 127, 63);
  SEND_BUFFER_DISPLAY_MS(t);
}

//画空心圆角矩形

//画空心圆角矩形
void testDrawRFrame()
{
  int t = 500;
  int x = 16;
  int y = 32;
  int w = 50;
  int h = 20;
  int r = 3;
  u8g2.clearBuffer();
  u8g2.drawStr(0, 15, "drawRFrame");
 
  u8g2.drawRFrame(x, y, w, h, r);
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawRFrame(x+w+5, y-10, w-20, h+20, r);
  SEND_BUFFER_DISPLAY_MS(t);
}

画空心圆
drawEllipse(x,y,rx,ry,opt) 绘制一个空心椭圆
drawFilledEllipse(x,y,rx,ry,opt) 绘制一个实心椭圆

//画空心圆
void testDrawCircle()
{
  int t = 500;
  int stx = 0;  //画图起始x
  int sty = 16; //画图起始y
  int with = 16;//一个图块的间隔
  int r = 15;   //圆的半径
  u8g2.clearBuffer();
  u8g2.drawStr(0, 15, "drawCircle");
 
  u8g2.drawCircle(stx, sty - 1 + with, r, U8G2_DRAW_UPPER_RIGHT); //右上
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawCircle(stx + with, sty, r, U8G2_DRAW_LOWER_RIGHT); //右下
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawCircle(stx - 1 + with * 3, sty - 1 + with, r, U8G2_DRAW_UPPER_LEFT); //左上
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawCircle(stx - 1 + with * 4, sty, r, U8G2_DRAW_LOWER_LEFT); //左下
  SEND_BUFFER_DISPLAY_MS(t);
  u8g2.drawCircle(stx - 1 + with * 2, sty - 1 + with * 2, r, U8G2_DRAW_ALL);//整个圆
  SEND_BUFFER_DISPLAY_MS(t);
}

字符串、汉字和变量显示

drawStr(x,y,string) 绘制一个字符串
x,y起点坐标
string字符串

//字符串/文字/变量显示测试
u8g2.enableUTF8Print();//enable UTF8
u8g2.setFont(u8g2_font_wqy12_t_gb2312b);//设置中文字符集

void testDrawStr()
{
  int t = 1000;
  u8g2.clearBuffer();
  u8g2.drawStr(0, 14, "drawStr / print");
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawStr(0, 32, "~!@#$%^&*()_+");
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.enableUTF8Print();//enable UTF8
  u8g2.setFont(u8g2_font_wqy12_t_gb2312b);//设置中文字符集
  u8g2.setCursor(0, 48);
  u8g2.print("码农爱学习");
  SEND_BUFFER_DISPLAY_MS(t);
 
  int a = 234;
  u8g2.setCursor(0, 64);
  u8g2.print("int a = ");
  u8g2.setCursor(40, 64);
  u8g2.print(a);//显示变量
  SEND_BUFFER_DISPLAY_MS(t);
}

画内置图标
drawGlyph(x,y,addr) 绘制U8g2内置的图标
x,y起点坐标
addr内置图标的地址

U8g2库内置了需要预先定义的图形,通过drawGlyp函数以及指定的地址,即可看OLED上显示对应的图标

void testGlyph()
{
  int t = 1000;
  u8g2.clearBuffer();
  u8g2.drawStr(0, 14, "drawGlyph");
 
  u8g2.drawGlyph(0, 32, 0x23f0);
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawGlyph(16, 32, 0x23f3);
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawGlyph(32, 32, 0x2603);
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawGlyph(48, 32, 0x2615);
  SEND_BUFFER_DISPLAY_MS(t);
 
  u8g2.drawGlyph(64, 32, 0x2618);
  SEND_BUFFER_DISPLAY_MS(t);
}

画自定义图片

drawXBM(x,y,w,h,addr) 绘制一个实心矩形 (圆角)
x,y起点坐标
w,h图片的宽度和高度`
addr图片(数组)的地址

自定义图片的显示,需要先将图形转换为数组,可以使用如下工具进行图片到数组的转换:
https://tools.clz.me/image-to-bitmap-array

// width: 128, height: 48
const unsigned char bilibili[] U8X8_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, ... 省略若干行 };
 
void testDrawXBM()
{
  int t = 1000;
  u8g2.clearBuffer();
  u8g2.drawStr(0, 14, "drawXBM");
  u8g2.drawXBM(0, 16, 128, 48, bilibili);
  SEND_BUFFER_DISPLAY_MS(t);
}

3.接线 096 oled 12864

NodeMcu arduino ESP8266 使用u8g2图形库 在096 oled 显示_第4张图片

工作电压:3V~5.5V
I2C介面 (位址:0x30)
驱动IC:SSD1306
OLED屏幕分为单色和双色两种
GND 电源地
VCC 电源正(3~5.5V)
SCL/SCK OLED 的 D5 脚,在 IIC 通信中为时钟管脚
SDA OLED 的 D6 脚,在 IIC 通信中为数据管

分辨率为 128*64

示例 04-ESP8266简易WIFI天气时钟

/************************************************************
  ===================ESP8266简易WIFI天气时钟==================
  Author:码农爱学习
  Date: 2022/05/28
  Version: V1.0
  Blog: https://xxpcb.gitee.io/
  BiliBili: https://space.bilibili.com/146899653
  图文教程:https://www.bilibili.com/read/cv16758967
  ------------------------------------------------------------
  硬件:ESP8266 NodeMCU + 12864 SSD1306 OLED显示屏(4pin IIC引脚)
  接线:[ESP8266]  --- [OLED]
       3.3V     ---  VCC
       G (GND)  ---  GND
       D1(GPIO5)---  SCL
       D2(GPIO4)---  SDA
************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SCL 5
#define SDA 4
#define HTTP_TIMEOUT 5000
#define CAPACITY (JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + 70)

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /*clock=*/D5, /*data=*/D6, /*reset=*/U8X8_PIN_NONE);   // All Boards without Reset of the Display

//---------------WIFI信息------------------------------
const char ssid[] = "dajiating";      //WiFi名(<---------替换为自己的)
const char pass[] = "DJT13619252979";      //WiFi密码(<---------替换为自己的)
//-----------------------------------------------------

WiFiClient client;
HTTPClient http;

void initOLED();
void initWiFi();
void initNTP();

//--------- weather ---------------
const char* host = "api.seniverse.com";     // 将要连接的服务器地址
const int httpPort = 80;                    // 将要连接的服务器端口
//心知天气HTTP请求所需信息
String reqUserKey = "SgPyzsfk1cq-k031x";   // 私钥(<---------替换为自己的)
String reqLocation = "Xian";           // 城市
String reqUnit = "c";                      // 摄氏/华氏
//建立心知天气API当前天气请求资源地址
String reqRes = "/v3/weather/now.json?key=" + reqUserKey +
                + "&location=" + reqLocation +
                "&language=en&unit=" + reqUnit;

//--------网络校时的相关配置---------
#define timeZone (8) //时区设置,采用东8区
#define NTP_PACKET_SIZE (48)     // NTP时间在消息的前48个字节里
static const char ntpServerName[] = "ntp1.aliyun.com"; //NTP服务器,使用阿里云
byte packetBuffer[NTP_PACKET_SIZE]; // 输入输出包的缓冲区
unsigned int localPort = 8888; // 用于侦听UDP数据包的本地端口
boolean isNTPConnected = false;
WiFiUDP Udp;

//----------时间、天气信息自定义结构体--------
typedef struct 
{
  int tm_year;
  int tm_mon;
  int tm_mday;
  int tm_hour;
  int tm_min;
  int tm_sec;
  int tm_week;
}rtc_time_t;

typedef struct 
{
  String weather; //天气字符串
  int iconIdx;    //天气对应的图标索引
  int temp;       //温度
}weather_info_t;

#define IOCN_OVERCAST 0
#define IOCN_CLOUDY   1
#define IOCN_RAIN     2
#define IOCN_SUNNY    3
char* icon_index[4]={"@","A","C","E"};//图标在天气字库里分别代表 阴(0x40),云,雨,晴

typedef struct
{
  int XinZhi_code;
  int icon_idx;
}weather_code_t;

weather_code_t weather_icon_table[4] = {
  {0, IOCN_SUNNY},
  {4, IOCN_CLOUDY},
  {9, IOCN_OVERCAST},
  {13, IOCN_RAIN}
};

//天气相关变量
String g_strWeather = "";
String g_strUpdateTime = "";
int g_iTemperature = 18;
int g_iCode = -1;
int g_iIdx = -1;

//==============================seup&loop=============================
void setup()
{
  Serial.begin(9600);
  Serial.println("NTP time and WiFi Weather test");
  initOLED();
  initWiFi();
  initNTP();
}

void loop()
{
  static int times = 0;
  //Serial.println(times);

  if ((times == 0) && (WiFi.status() == WL_CONNECTED))
  {
    // 向心知天气服务器服务器请求信息并对信息进行解析
    httpRequest(reqRes);
  }

  updateShowTime();

  if (++times >= 6000)
  {
    times = 0;
  }
  delay(300);
}
//======================================================================

void initOLED()
{
  u8g2.begin();
  u8g2.enableUTF8Print();//用于汉字显示
  u8g2.setFont(u8g2_font_wqy14_t_gb2312);

  u8g2.clearBuffer();
  u8g2.setCursor(0, 14);
  u8g2.print("等待WiFi连接");
  u8g2.setCursor(0, 30);
  u8g2.print("WiFi connection...");
  u8g2.sendBuffer();
}

void initWiFi()
{
  Serial.print("Connecting WiFi...");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void initNTP()
{
  Udp.begin(localPort);
  setSyncProvider(getNtpTime);
  setSyncInterval(300); //每300秒同步一次时间
}

/*-------- 网络天气 代码 ----------*/
// 向心知天气服务器服务器请求信息并对信息进行解析
void httpRequest(String reqRes)
{
  WiFiClient client;

  // 建立http请求信息
  String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" +
                       "Host: " + host + "\r\n" +
                       "Connection: close\r\n\r\n";
  Serial.println("");
  Serial.print("Connecting to ");
  Serial.print(host);

  // 尝试连接服务器
  if (client.connect(host, 80))
  {
    Serial.println(" Success!");

    // 向服务器发送http请求信息
    client.print(httpRequest);
    Serial.println("Sending request: ");
    Serial.println(httpRequest);

    // 获取并显示服务器响应状态行
    String status_response = client.readStringUntil('\n');
    Serial.print("status_response: ");
    Serial.println(status_response);

    // 使用find跳过HTTP响应头
    if (client.find("\r\n\r\n"))
    {
      Serial.println("Found Header End. Start Parsing.");
    }

    // 利用ArduinoJson库解析心知天气响应信息
    parseInfo(client);
  }
  else
  {
    Serial.println(" connection failed!");
  }
  //断开客户端与服务器连接工作
  client.stop();
}

// 利用ArduinoJson库解析心知天气响应信息
void parseInfo(WiFiClient client)
{
  const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 230;
  DynamicJsonDocument doc(capacity);
  deserializeJson(doc, client);
  Serial.println(doc.as<String>());

  JsonObject result0 = doc["results"][0];
  JsonObject result0_now = result0["now"];

  // 通过串口监视器显示以上信息
  g_strWeather = result0_now["text"].as<String>();// "Sunny"
  g_iCode = result0_now["code"].as<int>();// "0"
  g_iTemperature = result0_now["temperature"].as<int>();// "32"
  g_strUpdateTime = result0["last_update"].as<String>();// "2020-06-02T14:40:00+08:00"

  Serial.println(F("======Weahter Now======="));
  Serial.print(F("Weather Now: "));
  Serial.print(g_strWeather);
  Serial.print(F(" -> "));
  Serial.println(g_iCode);
  Serial.print(F("Temperature: "));
  Serial.println(g_iTemperature);
  Serial.print(F("Last Update: "));
  Serial.println(g_strUpdateTime);
  Serial.println(F("========================"));

  for (int i=0; i< 4; i++)
  {
    if(g_iCode == weather_icon_table[i].XinZhi_code)
    {
      g_iIdx = weather_icon_table[i].icon_idx;
      break;
    }
  }
}

void my_strcat(char* srcstr, int t)
{
  char str_tmp[5];
  if(t < 10) 
  {
    strcat(srcstr, "0");
  }
  itoa(t, str_tmp, 10); 
  strcat(srcstr, str_tmp); 
}

void testShowTimeAndWeather(rtc_time_t &now_time, weather_info_t &weather_info)
{
  u8g2.clearBuffer();
  int tm_year = now_time.tm_year;
  int tm_month = now_time.tm_mon;
  int tm_day = now_time.tm_mday;
  int tm_hour = now_time.tm_hour;
  int tm_minute = now_time.tm_min;
  int tm_sec = now_time.tm_sec;
  int tm_week = now_time.tm_week;
  
  //时分
  char str_big_time[] = "";
  my_strcat(str_big_time, tm_hour);
  strcat(str_big_time,":");
  my_strcat(str_big_time, tm_minute);
  u8g2.setFont(u8g2_font_logisoso24_tf); 
  u8g2.drawStr(0, 30, str_big_time);

  //秒
  char str_small_sec[] = "";
  my_strcat(str_small_sec, tm_sec);
  u8g2.setFont(u8g2_font_wqy14_t_gb2312);
  u8g2.drawStr(73, 30, str_small_sec);

  //日期
  char str_date[] = "";
  char str_temp[6];
  itoa(tm_year,str_temp,10);
  strcat(str_date,str_temp);
  strcat(str_date,"-");
  my_strcat(str_date, tm_month);
  strcat(str_date,"-");
  my_strcat(str_date, tm_day);
  u8g2.drawStr(0, 47, str_date);
  
  u8g2.setCursor(0, 63);
  u8g2.print("星期");
  switch (tm_week)
  {
    case 1: u8g2.print("日"); break;
    case 2: u8g2.print("一"); break;
    case 3: u8g2.print("二"); break;
    case 4: u8g2.print("三"); break;
    case 5: u8g2.print("四"); break;
    case 6: u8g2.print("五"); break;
    case 7: u8g2.print("六"); break;
    default: break;
  }
  u8g2.setCursor(60, 63);
  u8g2.print("西安");

  //分割线
  u8g2.drawLine(90, 0, 90, 63);
  
  //天气
  if (weather_info.iconIdx<0 || weather_info.iconIdx>3) //没有对应的天气图标
  {
    Serial.print("no icon for weather: ");
    Serial.println(weather_info.weather);
  }
  else
  {
    u8g2.setFont(u8g2_font_open_iconic_weather_4x_t );
    u8g2.drawStr(96, 34, icon_index[weather_info.iconIdx]);
  }
  char temperature_tmp[25];
  itoa(weather_info.temp, temperature_tmp, 10);
  strcat(temperature_tmp,"℃");
  u8g2.setFont(u8g2_font_wqy16_t_gb2312);
  u8g2.setCursor(96, 55);
  u8g2.print(temperature_tmp);
  
  u8g2.sendBuffer();
}

void updateShowTime()
{
  rtc_time_t now_time;
  now_time.tm_year = year();
  now_time.tm_mon = month();
  now_time.tm_mday = day();
  now_time.tm_hour = hour();
  now_time.tm_min = minute();
  now_time.tm_sec = second();
  now_time.tm_week = weekday();
  
  weather_info_t weather_info;
  weather_info.weather = g_strWeather;
  weather_info.iconIdx = g_iIdx;
  weather_info.temp = g_iTemperature;
  
  testShowTimeAndWeather(now_time, weather_info);
}

/*-------- NTP 代码 ----------*/
time_t getNtpTime()
{
    IPAddress ntpServerIP; // NTP服务器的地址
 
    while(Udp.parsePacket() > 0); // 丢弃以前接收的任何数据包
    Serial.println("Transmit NTP Request");
    // 从池中获取随机服务器
    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");
            isNTPConnected = true;
            Udp.read(packetBuffer, NTP_PACKET_SIZE); // 将数据包读取到缓冲区
            unsigned long secsSince1900;
            // 将从位置40开始的四个字节转换为长整型,只取前32位整数部分
            secsSince1900 = (unsigned long)packetBuffer[40] << 24;
            secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
            secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
            secsSince1900 |= (unsigned long)packetBuffer[43];
            Serial.println(secsSince1900);
            Serial.println(secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR);
            return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
        }
    }
    Serial.println("No NTP Response :-("); //无NTP响应
    isNTPConnected = false;
    return 0; //如果未得到时间则返回0
}
 
// 向给定地址的时间服务器发送NTP请求
void sendNTPpacket(IPAddress &address)
{
    memset(packetBuffer, 0, NTP_PACKET_SIZE);
    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;
    Udp.beginPacket(address, 123); //NTP需要使用的UDP端口号为123
    Udp.write(packetBuffer, NTP_PACKET_SIZE);
    Udp.endPacket();
}

总结

你可能感兴趣的:(NodeMcu,U8g2,单片机,嵌入式硬件)