Microduino ENC网络(十二)————用NTP获取Internet时间/zh

来自Microduino Wikipedia
跳转至: 导航搜索
Language English

目的

本教程将教大家如何通过NTP(网络时间协议)从互联网得到一个准确的时间。

设备

  • 其他硬件设备
    • USB数据连接线 一根

NTP

NTP是一个客户端-服务器协议,他工作在应用层,采用UDP传输协议,使用端口为123。

如果你发送一个请求到某个时间服务器,时间服务器会返回一个64位的值(时间戳):

  • 前32位表示自1900年1月1日间隔的秒数;
  • 后32位用以表示秒以下的部份,并加上网络延时量的估计.理论上可以精确到到2的-32次方秒,实际使用大约只有50ms(广域网)左右,在局域网可达1ms。在实际中您应找最近而且最稳定的时间服务器作为时间源。
NTP.jpg


原理图

  • Microduino-ENC28J60
  • Microduino-RJ45
  • Microduino-Core
  • Microduino-USBTTL

层层堆叠,再插上网线。

如下图所示:

MicroduinoENCShow.jpg

程序

ENCnetworktwelve

调试

步骤一:首先需要下载EtherCard库:https://github.com/jcw/ethercard

放到你的IDE的libraries文件夹中,重启IDE。

步骤二:解释一下代码:

在互联网上有很多时间服务器:比如美国的 NIST (National Institute of Standards and Technology) 提供整个互联网的时间服务;这里有一个意大利的 INRiM (Istituto Nazionale di Ricerca Metereologica)提供的时间服务器:

   static byte ntpServer[] = {193,204,114,232};

在EtherCard库针对NTP请求有两个方法:

  • ntpRequest(ntpServer, srcPort),向指定的服务器发送一个请求;
  • ntpProcessAnswer(&timeStamp, srcPort), 获取响应,提取时间戳(仅仅前32位)。

srcPort参数是用来在众多的enc28J60模块接收的包中发现一个包含NTP服务器回应的数据包:你可以自己选择这个值,但是ntpRequest方法和ntpProcessAnswer方法中这个参数应该一致。

取得时间戳的值后,你必须转换成date-time格式。这个方法过程如下:

  • 计算出时间戳对应的年数;
  • 在剩下的时间中计算出有多少个月份;
  • 相同的方法计算出日期,小时,分钟;
  • 最后剩下的就是秒数。

几个容易弄错的地方:

可能是闰年:如果是闰年必须用366*86500秒替代365*86500秒,判断是否为闰年可以用下面的方法:

   boolean isLeapYear(unsigned int year) {
     return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
   }

每个月份的天数是变化的:把这些值存入一个数组,格式如下:

   static int days_in_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

如果是闰年,二月份为29天:

   if(isLeapYear(year) && month == 1) seconds = SECONDS_IN_DAY * 29;

最后,时间戳是参考的GMT(格林尼治标准时间),如果你居住在不同的时区,你必须修正这个值:

   #define TIME_ZONE               +1
   [...]
   printDate(timeStamp + 3600 * TIME_ZONE);


步骤四:下载代码并编译通过。

步骤五:打开串口看看是否显示了时间。

结果

串口里显示了时间:

NTPShowTime.jpg

扩展

为了看时间更加方便美观,你可以使用Microduino OLED来显示时间:

MicroduinoENCTimeShow1.jpg
MicroduinoENCTimeShow2.jpg

视频