使用NTP服务器获取网络时间

在很多时候我们需要进行时间校准,这里一般就可以用NTP服务器进行获取时间信息,下面使用零知-ESP8266上进行NTP时间的获取。

一、硬件

需要的模块

零知ESP8266开发板

二、软件

本次使用了Time相关的软件库,因此需要安装如下库:Time.7z(点击下载)

注:在安装之前应该在【库】页面,在esp8266型号情况下,查找是否已经有安装了,如果没有就按照上图进行安装。

然后在零知开发工具中就可以看到Time相关例子,打开如下示例:

或者把下面代码粘贴到零知开发工具中:


							
	/*
	 * TimeNTP_ESP8266WiFi.ino
	 * Example showing time sync to NTP time source
	 *
	 * This sketch uses the ESP8266WiFi library
	 */
	  
	#include <TimeLib.h>
	#include <ESP8266WiFi.h>
	#include <WiFiUdp.h>
	  
	const char ssid[] = "xx";       // wifi名称
	const char pass[] = "xx";       // wifi密码
	  
	// NTP Servers:
	//static const char ntpServerName[] = "time.nist.gov";
	//static const char ntpServerName[] = "time-a.timefreq.bldrdoc.gov";
	//static const char ntpServerName[] = "time-b.timefreq.bldrdoc.gov";
	//static const char ntpServerName[] = "time-c.timefreq.bldrdoc.gov";
	  
	const int timeZone = 8; //BeiJing in China
	  
	// const int timeZone = 1;     // Central European Time
	//const int timeZone = -5;  // Eastern Standard Time (USA)
	//const int timeZone = -4;  // Eastern Daylight Time (USA)
	//const int timeZone = -8;  // Pacific Standard Time (USA)
	//const int timeZone = -7;  // Pacific Daylight Time (USA)
	  
	  
	WiFiUDP Udp;
	unsigned int localPort = 8888; 
	  
	time_t getNtpTime();
	void digitalClockDisplay();
	void printDigits(int digits);
	void sendNTPpacket(IPAddress &address);
	  
	void setup()
	{
	  Serial.begin(9600);
	  while (!Serial) ; // Needed for Leonardo only
	  delay(250);
	  Serial.println("TimeNTP Example");
	  Serial.print("Connecting to ");
	  Serial.println(ssid);
	  WiFi.begin(ssid, pass);
	  
	  while (WiFi.status() != WL_CONNECTED) {
	    delay(500);
	    Serial.print(".");
	  }
	  
	  Serial.print("IP number assigned by DHCP is ");
	  Serial.println(WiFi.localIP());
	  Serial.println("Starting UDP");
	  Udp.begin(localPort);
	  Serial.print("Local port: ");
	  Serial.println(Udp.localPort());
	  Serial.println("waiting for sync");
	  setSyncProvider(getNtpTime);
	  setSyncInterval(300);
	}
	  
	time_t prevDisplay = 0;
	  
	void loop()
	{
	  if (timeStatus() != timeNotSet) {
	    if (now() != prevDisplay) {
	      prevDisplay = now();
	      digitalClockDisplay();
	    }
	  }
	}
	  
	void digitalClockDisplay()
	{
	  Serial.print(hour());
	  printDigits(minute());
	  printDigits(second());
	  Serial.print(" ");
	  Serial.print(day());
	  Serial.print(".");
	  Serial.print(month());
	  Serial.print(".");
	  Serial.print(year());
	  Serial.println();
	}
	  
	void printDigits(int digits)
	{
	  Serial.print(":");
	  if (digits < 10)
	  Serial.print('0');
	  Serial.print(digits);
	}
	  
	/*-------- NTP code ----------*/
	  
	const int NTP_PACKET_SIZE = 48; 
	byte packetBuffer[NTP_PACKET_SIZE]; 
	  
	time_t getNtpTime()
	{
	  IPAddress ntpServerIP; 
	  
	  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");
	      Udp.read(packetBuffer, NTP_PACKET_SIZE); 
	      unsigned long secsSince1900;
	      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; 
	}
	void sendNTPpacket(IPAddress &address)
	{
	  memset(packetBuffer, 0, NTP_PACKET_SIZE);
	  packetBuffer[0] = 0b11100011;   
	  packetBuffer[1] = 0;    
	  packetBuffer[2] = 6;     
	  packetBuffer[3] = 0xEC;  
	  packetBuffer[12] = 49;
	  packetBuffer[13] = 0x4E;
	  packetBuffer[14] = 49;
	  packetBuffer[15] = 52;
	  Udp.beginPacket(address, 123); 
	  Udp.write(packetBuffer, NTP_PACKET_SIZE);
	  Udp.endPacket();
	}
					

这里在这个地址http://www.ntp.org.cn/pool.php可以找到可用的NTP服务器,并把时区调整到东八区。

把代码上传到零知-ESP8266后,就可以看到如下结果,可以看到和我们电脑上的时间是一致的: