ESP32获取网络时间

一:目的

时间是软硬件系统或设备中比较重要的东西,特别是需要和外部进行交互时就更加需要用到有个统一的时间了。目前来说只要能联网的设备的时间主要是从网络时间服务器(NTP)上获取的,这篇文章将对此做个简单的说明。

二:基础说明

Arduino core for the ESP32中获取网络时间是非常简单的,只要下面几步就行:

  • 使用STA或ETH模式连上互联网;
  • 使用下面函数从网络时间服务器上获取并设置时间:

      void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char*        server2 = nullptr, const char* server3 = nullptr)

      网络时间服务器最常用的主机名是 pool.ntp.org ;
      通过网络时间服务器获得的时间是世界协调时间(UTC)/格林尼治时间(GMT),不同地区          的时间可以通过时区换算, gmtOffset_sec 参数就是用来修正时区的,比如对于我们东八区(        UTC/GMT+08:00)来说该参数就需要填写 8 * 3600 ;
       如果使用夏令时 daylightOffset_sec 就填写3600,否则就填写0;

设置完成后就可以使用下面函数读取当前时间了: 

  bool getLocalTime(struct tm * info, uint32_t ms = 5000)
  ms 为该操作超时时间,超时则返回false;
  info 是一个 struct tm 结构体对象,用于接收当前时间; 

三:示例演示 

在Arduino core for the ESP32中获取网络时间是非常简单的,只要先连上网,然后就可以调用库中封装的方法获取网络时间了。下面是个简单的示例演示: 

#include <WiFi.h>

const char *ssid = "********";    //你的网络名称
const char *password = "********"; //你的网络密码

const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;

void printLocalTime()
{
    struct tm timeinfo;
    if (!getLocalTime(&timeinfo))
    {
        Serial.println("Failed to obtain time");
        return;
    }
    Serial.println(&timeinfo, "%F %T %A"); // 格式化输出
}

void setup()
{
    Serial.begin(115200);
    Serial.println();

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
    Serial.println("WiFi connected!");

    // 从网络时间服务器上获取并设置时间
    // 获取成功后芯片会使用RTC时钟保持时间的更新
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    printLocalTime();

    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
    Serial.println("WiFi disconnected!");
}

void loop()
{
    delay(1000);
    printLocalTime();
}

 

 

         

四:额外说明

      网络时间服务器

可用的网络时间服务器主要有下面一些:

 

 

 

struct tm结构体与格式化输出

该结构体代码如下:

struct tm {
int tm_sec; // 秒,取值0~59;
int tm_min; // 分,取值0~59;
int tm_hour; // 时,取值0~23;
int tm_mday; // 月中的日期,取值1~31;
int tm_mon; // 月,取值0~11;
int tm_year; // 年,其值等于实际年份减去1900;
int tm_wday; // 星期,取值0~6,0为周日,1为周一,依此类推;
int tm_yday; // 年中的日期,取值0~365,0代表1月1日,1代表1月2日,依此类推;
int tm_isdst; // 夏令时标识符,实行夏令时的时候,tm_isdst为正;不实行夏令时的进候,tm_isdst为0;不了解情况时,tm_isdst()为负
};

 该结构体可以格式化输出,格式化规则如下:

%a 星期几的简写
%A 星期几的全称
%b 月分的简写
%B 月份的全称
%c 标准的日期的时间串
%C 年份的后两位数字
%d 十进制表示的每月的第几天
%D 月/天/年
%e 在两字符域中,十进制表示的每月的第几天
%F 年-月-日
%g 年份的后两位数字,使用基于周的年
%G 年分,使用基于周的年
%h 简写的月份名
%H 24小时制的小时
%I 12小时制的小时
%j 十进制表示的每年的第几天
%m 十进制表示的月份
%M 十时制表示的分钟数
%p 本地的AM或PM的等价显示
%r 12小时的时间
%R 显示小时和分钟:hh:mm
%S 十进制的秒数
%t 水平制表符
%T 显示时分秒:hh:mm:ss
%u 每周的第几天,星期一为第一天 (值从0到6,星期一为0)
%U 第年的第几周,把星期日做为第一天(值从0到53)
%V 每年的第几周,使用基于周的年
%w 十进制表示的星期几(值从0到6,星期天为0)
%W 每年的第几周,把星期一做为第一天(值从0到53)
%x 标准的日期串
%X 标准的时间串
%y 不带世纪的十进制年份(值从0到99)
%Y 带世纪部分的十进制年份
%z,%Z 时区名称,如果不能得到时区名称则返回空字符

 五:获取时间并在0.96OLED屏中显示时间

 

#include <Wire.h> // 使用 I2C 的库
#include <Adafruit_GFX.h> //Adafruit 库写入显示器
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
const char *ssid = "nova6";    //你的网络名称
const char *password = "zdx123456"; //你的网络密码 
#define SCREEN_WIDTH 128 // 使用的是 128×64 OLED 显示屏
#define SCREEN_HEIGHT 64 // 
 
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
//  I2C 通信协议
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);// (-1) 参数表示您的 OLED 显示器没有 RESET 引脚
 
void testscrolltext(void); //函数声明
 
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;

void printLocalTime()
{
    struct tm timeinfo;
    if (!getLocalTime(&timeinfo))
    {
        Serial.println("Failed to obtain time");
        return;
    }
    Serial.println(&timeinfo, "%F %T %A"); // 格式化输出
    display.clearDisplay();// 清除显示
    display.setTextSize(2);// 设置文本大小
    display.setTextColor(WHITE);// 设置文本颜色
    display.setCursor(0, 30);//设置显示坐标
    // Display static text
    display.println(&timeinfo, "%F %T");//
}
void setup() {
  Serial.begin(115200);//115200 的波特率初始化串行监视器以进行调试
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
  Serial.println("WiFi connected!");
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))  //0x3d 0x3c  0x78 0x7A // Address 0x3D for 128x64
   { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);
  display.clearDisplay();// 清除显示
//  display.clearDisplay();// 清除显示
//  display.setTextSize(3);// 设置文本大小
//  display.setTextColor(WHITE);// 设置文本颜色
//  display.setCursor(0, 30);//设置显示坐标
//  // Display static text
//  display.println("naiva");//
//    display.setTextColor(WHITE);// 设置文本颜色
//  display.setCursor(20, 0);//设置显示坐标
//  display.println("haha");// 
//  display.display(); // 屏幕上实际显示文本
   configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
   printLocalTime();
}
 
//void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2 = nullptr, const char* server3 = nullptr) 
int i = 0; 
void loop() {
//  //testscrolltext();
//  display.clearDisplay();
//  display.setTextSize(1); // 
//  display.setTextColor(WHITE);
//  display.setCursor(10, 0);
//  display.println(F("naiva"));
//  display.display();      //
//  delay(100);
//  display.startscrollright(0x00, 0x0F);//  从左到右滚动文本
//  delay(4000);
//  display.stopscroll();// 停止滚动
//  delay(1000);
//  display.startscrollleft(0x00, 0x0F);//  从右到左滚动文本
//  delay(4000);
//  display.stopscroll();
//  delay(1000);
  printLocalTime();
  display.setTextColor(WHITE);// 设置文本颜色
  display.setCursor(20, 0);//设置显示坐标
  display.println(i);// 
  display.display(); // 屏幕上实际显示文本
  i = i+1;
  delay(1000);
}
 
void testscrolltext(void) {
  display.clearDisplay();
 
  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(WHITE);
  display.setCursor(10, 0);
  display.println(F("NAIVA415"));
  display.display();      // Show initial text
  delay(100);
 
  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}
 
 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值