NodeMCU(ESP8266)获取NTP时间
很久没有搞ESP8266了,可能是这两年工作太忙了,又或者是对生活失去了斗志,所以最近又重新把两年前的东西重新收拾收拾。
NTP协议 我之前有写一篇NTP 入门介绍 ,大家如果有对NTP不了解的,可以先查阅这篇《NTP 入门介绍 》
为啥要同步时间 之前看到有一个用户通过esp8266做了一个时钟出来( ESP8266物联网创意点阵时钟,女朋友看了都想要! ),自己也想搞一个类似的,然后就发现他有一个功能就是网络自动校准时间,才了解到有NTP这个协议的存在,所以就找到一些代码研究了一番,所以就有了今天这篇博文。
实现思路 esp8266感觉是一个很简单的东西,网上有很多的代码示例,这里我更推荐使用官方的示例库。
如何从官方的示例库中找到我们要用的示例代码:
代码 根据上述的示例和其他用户分享的库文件使用方法,我们稍微整理一下,把代码改成我们想要的样子。
先连接wifi
判断时间是否是正确的,如果不正确就去同步时间
如果时间正确就每秒中增加我们的时钟信息,顺便打印出来
上代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 #include <ESP8266WiFi.h> #include <WiFiUdp.h> #include <Ticker.h> #ifndef STASSID #define STASSID "你的WiFi名称" #define STAPSK "你的WiFi密码" #endif const char * ssid = STASSID;const char * pass = STAPSK;unsigned int h = 99 , m = 99 , s = 99 ;unsigned int localPort = 2390 ;IPAddress timeServerIP; const char * ntpServerName = "time.windows.com" ;const int NTP_PACKET_SIZE = 48 ;byte packetBuffer[ NTP_PACKET_SIZE]; WiFiUDP udp; Ticker ticker; void setup () { Serial.begin(115200 ); Serial.println(); Serial.print("连接wifi中 " ); Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500 ); Serial.print("." ); } Serial.println("" ); Serial.println("WiFi已连接" ); Serial.println("设备IP地址: " ); Serial.println(WiFi.localIP()); Serial.println("开启UDP通信" ); udp.begin(localPort); Serial.print("本地端口为: " ); Serial.println(udp.localPort()); } void loop () { WiFi.hostByName(ntpServerName, timeServerIP); if (h == 99 || m == 99 || s == 99 ) { sendNTPpacket(timeServerIP); delay(1000 ); setTimes(); ticker.attach(1 , addtime); } } void addtime () { if (s == 59 ) { s = 0 ; if (m == 59 ) { m = 0 ; if (h == 23 ) { h = 0 ; } else { h++; } } else { m++; } } else { s++; } Serial.print("当前时间为: " ); Serial.print(h); Serial.print(":" ); Serial.print(m); Serial.print(":" ); Serial.println(s); } void setTimes () { int cb = udp.parsePacket(); if (!cb) { Serial.println("没有接收到任何的数据包!" ); } else { Serial.print("接收到的数据包的长度为: " ); Serial.println(cb); udp.read(packetBuffer, NTP_PACKET_SIZE); unsigned long highWord = word(packetBuffer[40 ], packetBuffer[41 ]); unsigned long lowWord = word(packetBuffer[42 ], packetBuffer[43 ]); unsigned long secsSince1900 = highWord << 16 | lowWord; Serial.print("1900年格式标准的时间戳为:" ); Serial.println(secsSince1900); const unsigned long seventyYears = 2208988800UL ; unsigned long epoch = secsSince1900 - seventyYears; Serial.print("1970年格式标准的时间戳为:" ); Serial.println(epoch); h = (epoch % 86400L ) / 3600 + 8 ; m = (epoch % 3600 ) / 60 ; s = epoch % 60 ; } } void sendNTPpacket (IPAddress& address) { Serial.println("发送ntp数据包..." ); memset (packetBuffer, 0 , NTP_PACKET_SIZE); packetBuffer[0 ] = 0b11100011 ; udp.beginPacket(address, 123 ); udp.write(packetBuffer, NTP_PACKET_SIZE); udp.endPacket(); }
效果图
参考文章 ESP8266物联网创意点阵时钟,女朋友看了都想要! 从零开始的ESP8266探索(11)-定时任务调度器Ticker使用演示 ESP8266 – WiFiUDP库