实用经验帖 ESP8266 NODEMCU 获取互联网上面时间服务器的标准时间
能少用原件尽量少用,所以就不用时间模块,直接用NODEMCU获取标准时间。
硬件:NODEMCU 一块
软件:arduino IDE (配好8266开发板)
所需库:NTPclient 直接在库管理里面用这个关键字,第一个就是。
发代码,不一同发库文件的都是耍流氓
时间会打印到串口。安装好库,复制此代码,仅需要修改WIFI密码和WIFI名称即可
文中变量名,基本都是拼音。我英文考试一直保持15-26分的成绩。
[mw_shl_code=arduino,true]#include <TimeLib.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char Wifi_MingCheng[] = "HuiKeDianNaoFuWu"; // your network Wifi_MingCheng (name)
const char Wifi_MiMa[] = "13488214252"; // your network Wifi_MiMaword
//const char Wifi_MingCheng[] = "DanDan"; // your network Wifi_MingCheng (name)
//const char Wifi_MiMa[] = "13488214252"; // your network Wifi_MiMaword
// NTP服务器:
static const char NTP_Server_Name[] = "us.pool.ntp.org";
//static const char NTP_Server_Name[] = "time.nist.gov";
//static const char NTP_Server_Name[] = "time-a.timefreq.bldrdoc.gov";
//static const char NTP_Server_Name[] = "time-b.timefreq.bldrdoc.gov";
//static const char NTP_Server_Name[] = "time-c.timefreq.bldrdoc.gov";
const int ShiQu = +8; //时区 北京时间
WiFiUDP Udp;
unsigned int localPort = 8888; // 用于侦听UDP数据包的本地端口
time_t HuoQu_NTP_ShiJian();// 获取NTP时间
void XianShiShiJian(); //显示时间
void GeShiHuaShuZi(int ShuZi);//格式化数字
void FaSong_NTP_Bao(IPAddress &address);//发送NTP包
void setup() {
Serial.begin(9600);
delay(250);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Udp.begin(localPort);
setSyncProvider(HuoQu_NTP_ShiJian);//设置同步提供程序
setSyncInterval(300); //设置同步间隔
}
time_t ShangYiGeXianShi = 0; // 显示数字时钟时
void loop() {
if (timeStatus() != timeNotSet) { //如果 时间状态 不等于 时间未设置 那么
if (now() != ShangYiGeXianShi) { //如果 当前时间 不等于 上一个时间 那么 仅当时间改变时更新显示
ShangYiGeXianShi = now(); //上一个时间 等于 当前时间
XianShiShiJian(); //显示时间
}
}
}
void XianShiShiJian() { // 数字时钟显示时间
Serial.print(year());
Serial.print("-");
GeShiHuaShuZi(month());
Serial.print("-");
GeShiHuaShuZi(day());
Serial.print(" ");
GeShiHuaShuZi(hour());
Serial.print(":");
GeShiHuaShuZi(minute());
Serial.print(":");
GeShiHuaShuZi(second());
Serial.println();
}
void GeShiHuaShuZi(int ShuZi) { // 格式化数字 如果输入数字小于10则在前面加0打印出来 注意:下面语句不能加{}否则时间出不来
if (ShuZi < 10)
Serial.print("0");
Serial.print(ShuZi);
}
/*-------- NTP code ----------*/
const int NTP_Bao_DaXiao = 48; //NTP包大小 NTP时间在消息的前48个字节中
byte ShuJuBaoHuanChongQu[NTP_Bao_DaXiao]; //数据包缓冲区 用于保存传入和传出数据包的缓冲区
time_t HuoQu_NTP_ShiJian() { //获取NTP时间
IPAddress NTP_Server_IP; // NTP服务器的IP地址
while (Udp.parsePacket() > 0) ; //丢弃以前接收的任何数据包
Serial.println("传输NTP请求");
// 从池中获取随机服务器
WiFi.hostByName(NTP_Server_Name, NTP_Server_IP);
Serial.print(NTP_Server_Name);
Serial.print(": ");
Serial.println(NTP_Server_IP);
FaSong_NTP_Bao(NTP_Server_IP);
uint32_t ShangCiShiJian = millis(); //开始等待
while (millis() - ShangCiShiJian < 1500) { //如果小于这个时间则
int size = Udp.parsePacket(); //分析数据包
if (size >= NTP_Bao_DaXiao) { //如果 获取到的包 大于或等于 NTP包大小
Serial.println("接收NTP响应");
Udp.read(ShuJuBaoHuanChongQu, NTP_Bao_DaXiao); // 将数据包读取到缓冲区
unsigned long secsSince1900; //从1900年到现在的秒
// 将从位置40开始的四个字节转换为长整数
secsSince1900 = (unsigned long)ShuJuBaoHuanChongQu[40] << 24;
secsSince1900 |= (unsigned long)ShuJuBaoHuanChongQu[41] << 16;
secsSince1900 |= (unsigned long)ShuJuBaoHuanChongQu[42] << 8;
secsSince1900 |= (unsigned long)ShuJuBaoHuanChongQu[43];
return secsSince1900 - 2208988800UL + ShiQu * SECS_PER_HOUR;
}
}
Serial.println("无NTP响应");
return 0; // 如果无法获得时间,则返回0
}
// 向给定地址的时间服务器发送NTP请求
void FaSong_NTP_Bao(IPAddress &address) {
// 将缓冲区中的所有字节设置为0
memset(ShuJuBaoHuanChongQu, 0, NTP_Bao_DaXiao);//清零
//初始化形成NTP请求所需的值
//(有关数据包的详细信息,请参阅上面的URL)
ShuJuBaoHuanChongQu[0] = 0b11100011; // li,版本,模式
ShuJuBaoHuanChongQu[1] = 0; // 时钟的层次或类型
ShuJuBaoHuanChongQu[2] = 6; // 轮询间隔
ShuJuBaoHuanChongQu[3] = 0xEC; // 对等时钟精度
//根延迟和根分散为8字节零
ShuJuBaoHuanChongQu[12] = 49;
ShuJuBaoHuanChongQu[13] = 0x4E;
ShuJuBaoHuanChongQu[14] = 49;
ShuJuBaoHuanChongQu[15] = 52;
//所有ntp字段现在都有值
//可以发送请求时间戳的数据包:
Udp.beginPacket(address, 123); //NTP请求到端口123
Udp.write(ShuJuBaoHuanChongQu, NTP_Bao_DaXiao);
Udp.endPacket();
}
[/mw_shl_code]
|