一:目的
时间是软硬件系统或设备中比较重要的东西,特别是需要和外部进行交互时就更加需要用到有个统一的时间了。目前来说只要能联网的设备的时间主要是从网络时间服务器(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 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 // 使用 I2C 的库#include //Adafruit 库写入显示器#include #include 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);}
来源地址:https://blog.csdn.net/xingstar521/article/details/131748026