打印

Arduino ESP8266 获取网络时间方法

[复制链接]
466|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

#include <ESP8266WiFiMulti.h>
#include <WiFiUdp.h>
#include"rtctime.h"

#include <time.h>      // time() ctime()


ESP8266WiFiMulti WiFiMulti;

unsigned int localPort = 2390;  // local port to listen for UDP packets
IPAddress timeServerIP;  // time.nist.gov NTP server address
const char* ntpServerName = "time.nist.gov";
const int NTP_PACKET_SIZE = 48;  // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[NTP_PACKET_SIZE];  // buffer to hold incoming and outgoing packets
// A UDP instance to let us send and receive packets over UDP
WiFiUDP udp;
struct rtc_tm rtcdate;

// NTP 服务器地址
const char* ntpServer = "pool.ntp.org";

// 时区和夏令时设置(例如:GMT+8)
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  delay(100);
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("XGY-NJY", "njy123456");

  Serial.println('\n');
  while(WiFiMulti.run() != WL_CONNECTED)
  {
    Serial.print("-.-");
    delay(250);
  }
  Serial.println('\n');
  
  Serial.print("Connected to :");
  Serial.println(WiFi.SSID());
  Serial.print("IP=");
  Serial.println(WiFi.localIP());

  Serial.println("Starting UDP");
  udp.begin(localPort);
  Serial.print("Local port: ");
  Serial.println(udp.localPort());

  // 配置时间
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  // 等待并获取时间
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }
char timeStringBuff[50]; // 缓冲区大小根据需要调整
   sprintf(timeStringBuff, "Current time: %04d-%02d-%02d %02d:%02d:%02d",
          timeinfo.tm_year + 1900,
          timeinfo.tm_mon + 1,
          timeinfo.tm_mday,
          timeinfo.tm_hour,
          timeinfo.tm_min,
          timeinfo.tm_sec);
  // 输出当前时间
  Serial.println(timeStringBuff);
  
}

void loop() {
  // put your main code here, to run repeatedly:
  // get a random server from the pool
  WiFi.hostByName(ntpServerName, timeServerIP);
  sendNTPpacket(timeServerIP);  // send an NTP packet to a time server
  // wait to see if a reply is available
  delay(1000);

  int cb = udp.parsePacket();
  if (!cb)
  {
    Serial.println("no packet yet");
  } else
  {
    Serial.print("packet received, length=");
    Serial.println(cb);
    // We've received a packet, read the data from it
    udp.read(packetBuffer, NTP_PACKET_SIZE);  // read the packet into the buffer
    // the timestamp starts at byte 40 of the received packet and is four bytes,
    //  or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print("Seconds since Jan 1 1900 = ");
    Serial.println(secsSince1900);

    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;
    // print Unix time:
    Serial.println(epoch);

    rtctime_gmtime(epoch,&rtcdate);
    Serial.println("The Beijing time is :");
  //下面变量要多定义一个,这样最后一个空闲作为结束标志
    char date_temp[11];
    char time_temp[9];
    sprintf(date_temp,"%04d-%02d-%02d",1900+rtcdate.tm_year,1+rtcdate.tm_mon,rtcdate.tm_mday);
    sprintf(time_temp,"%02d-%02d-%02d",8+rtcdate.tm_hour,rtcdate.tm_min,rtcdate.tm_sec);
    Serial.println(date_temp);
    Serial.println(time_temp);

/*
    // print the hour, minute and second:
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print((epoch % 86400L) / 3600);  // print the hour (86400 equals secs per day)
    Serial.print(':');
    if (((epoch % 3600) / 60) < 10)
    {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch % 3600) / 60);  // print the minute (3600 equals secs per minute)
    Serial.print(':');
    if ((epoch % 60) < 10)
    {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch % 60);  // print the second
    */
  }
  // wait ten seconds before asking for the time again
  delay(10000);
}


// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress& address) {
  Serial.println("sending NTP packet...");
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  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;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  udp.beginPacket(address, 123);  // NTP requests are to port 123
  udp.write(packetBuffer, NTP_PACKET_SIZE);
  udp.endPacket();
}


使用特权

评论回复

相关帖子

沙发
gaoyang9992006|  楼主 | 2024-7-4 20:19 | 只看该作者

/* seconds per day */
#define SPD 24*60*60
struct rtc_tm{
  int tm_sec;   /* Seconds.     [0-60] (1 leap second) */
  int tm_min;   /* Minutes.     [0-59] */
  int tm_hour;  /* Hours.       [0-23] */
  int tm_mday;  /* Day.         [1-31] */
  int tm_mon;   /* Month.       [0-11] */
  int tm_year;  /* Year - 1900. */
  int tm_wday;  /* Day of week. [0-6] */
  int tm_yday;  /* Days in year.[0-365]        */
};
/* days per month -- nonleap! */
static const short __spm[13] =
  { 0,
    (31),
    (31+28),
    (31+28+31),
    (31+28+31+30),
    (31+28+31+30+31),
    (31+28+31+30+31+30),
    (31+28+31+30+31+30+31),
    (31+28+31+30+31+30+31+31),
    (31+28+31+30+31+30+31+31+30),
    (31+28+31+30+31+30+31+31+30+31),
    (31+28+31+30+31+30+31+31+30+31+30),
    (31+28+31+30+31+30+31+31+30+31+30+31),
  };

static int __isleap (int year) {
  /* every fourth year is a leap year except for century years that are
   * not divisible by 400. */
  /*  return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); */
  return (!(year % 4) && ((year % 100) || !(year % 400)));
}

void rtctime_gmtime (const int32 stamp, struct rtc_tm *r)
{
  int32_t i;
  int32_t work = stamp % (SPD);
  r->tm_sec = work % 60; work /= 60;
  r->tm_min = work % 60; r->tm_hour = work / 60;
  work = stamp / (SPD);
  r->tm_wday = (4 + work) % 7;
  for (i = 1970; ; ++i) {
    int32_t k = __isleap (i) ? 366 : 365;
    if (work >= k) {
      work -= k;
    } else {
      break;
    }
  }
  r->tm_year = i - 1900;
  r->tm_yday = work;

  r->tm_mday = 1;
  if (__isleap (i) && (work > 58)) {
    if (work == 59) r->tm_mday = 2; /* 29.2. */
    work -= 1;
  }

  for (i = 11; i && (__spm[i] > work); --i) ;
  r->tm_mon = i;
  r->tm_mday += work - __spm[i];
}

使用特权

评论回复
发新帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1961

主题

15931

帖子

208

粉丝