本文来源电子发烧友社区,作者:李元江, 帖子地址:https://bbs.elecfans.com/jishu_2025289_1_1.html
今天的帖子我写的是关于网络时间同步,主要功能为按下按键,进入网络NTP时间获取功能,最后完成网络时间的同步。
首先说说怎么获取网络时钟。现在很多NTP时间服务器,从服务器中就能获取网络时间。我所使用的时间服务器为time.windows.com,IP地址为52.231.114.183,端口号为123,采用UDP协议。需要先采用UDP方式,连接到该服务器。之后再发送48个字节的十六进制数(不用回车加换行):0b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d6 6d d9 00 00 00 00 00然后就可以看到时间服务器返回来的数据,下图是我使用调试组手获得的数据,正常情况下一共会收到48个字节数据,第41-44字节的数据是我们所需要的时间数据。如下获得的NTP数据为0xE398556A。
-
注意:该NTP数据是从1900年开始算的,而时间戳是从1970年开始算的
二、软件设计
- #ifndef PARAM_HOTSPOT_SSID
- #define PARAM_HOTSPOT_SSID "YYYYY" // your AP SSID
- #endif
-
- #ifndef PARAM_HOTSPOT_PSK
- #define PARAM_HOTSPOT_PSK"123456"// your AP PSK
- #endif
该函数主要完成网络连接,连接时间服务器及时间获取,并根据获取到的NTP时间计算出对应的时间戳。获取到的NTP时间数值是从1900年开始计算,时间戳数值从1970年开始计算。因此需要减去1970-1900年间的数值,才能得到我们所需的时间戳。
- #include
- #include
- #include
- #include
-
- #include "net_demo.h"
- #include "net_common.h"
- #include "net_params.h"
- #include "wifi_connecter.h"
- #include "ohos_init.h"
- #include "cmsis_os2.h"
-
- #define NTPIPADDR "52.231.114.183"
- #define NTPPORT 123
-
- #define NTP_TIMESTAMP_DELTA 2208988800ull
-
- externuint32_t timedata;
- extern bool GetNTPFlag;
-
- void getNtpTime(void)
- {
-
- uint32_t NTP_Time;
- unsigned char buf[48];//存储NTP服务器返回的数据
- unsigned char NTP_Data[]=
- { 0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x0d6,0x06d,0x0d9,0x00,0x00,0x00,0x00,0x00};
- ; //48字节的报文
-
-
- WifiDeviceConfig config = {0};
-
- // 准备AP的配置参数
- strcpy(config.ssid, PARAM_HOTSPOT_SSID);
- strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
- config.securityType = PARAM_HOTSPOT_TYPE;
- osDelay(10);
- int netId = ConnectToHotspot(&config);
-
- ssize_t retval = 0;
- int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // UDP socket
-
- struct sockaddr_in toAddr = {0};
- toAddr.sin_family = AF_INET;
- toAddr.sin_port = htons(NTPPORT); // 端口号,从主机字节序转为网络字节序
- if (inet_pton(AF_INET, NTPIPADDR, &toAddr.sin_addr) <= 0) { // 将主机IP地址从“点分十进制”字符串 转化为 标准格式(32位整数)
- printf("inet_pton failed!rn");
- goto do_cleanup;
- }
-
- // UDP socket 是 “无连接的” ,因此每次发送都必须先指定目标主机和端口,主机可以是多播地址
- retval = sendto(sockfd, NTP_Data, 48, 0, (struct sockaddr *)&toAddr, sizeof(toAddr));
- if (retval < 0) {
- printf("sendto failed!rn");
- goto do_cleanup;
- }
-
- printf("send NTP message %ld done!rn",retval);
- for(uint8_t i = 0;i<48;i++)
- {
- printf("%02xt",(unsigned char)NTP_Data[i]);
- if( (i+1) % 8 == 0 )
- printf("rn");
- }
- struct sockaddr_in fromAddr = {0};
- socklen_t fromLen = sizeof(fromAddr);
-
- // UDP socket 是 “无连接的” ,因此每次接收时前并不知道消息来自何处,通过 fromAddr 参数可以得到发送方的信息(主机、端口号)
- retval = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&fromAddr, &fromLen);
- if (retval <= 0) {
- printf("recvfrom failed or abort, %ld, %d!rn", retval, errno);
- goto do_cleanup;
- }
-
- NTP_Time = buf[40]<<24 | buf[40+1]<<16|buf[40+2]<<8 |buf[40+3];
- timedata = NTP_Time - NTP_TIMESTAMP_DELTA;
-
- printf("timedata is %ldn",timedata);
- //response[retval] = '';
- printf("recv UDP message {%s} %ld done!rn", buf, retval);
- printf("peer info: ipaddr = %s, port = %drn", inet_ntoa(fromAddr.sin_addr), ntohs(fromAddr.sin_port));
- GetNTPFlag = false;
-
- for(uint8_t i = 0;i<48;i++)
- {
- printf("%02xt",(unsigned char)buf[i]);
- if( (i+1) % 8 == 0 )
- printf("rn");
- }
- do_cleanup:
-
- GetNTPFlag = false;
- printf("do_cleanup...rn");
- close(sockfd);
-
- printf("disconnect to AP ...rn");
- DisconnectWithHotspot(netId);
- printf("disconnect to AP done!rn");
- }
在oled_demo.c文件中增加获取时间功能代码。按下按键进入时间同步功能。
- sources = [
- "oled_demo.c",
- "oled_ssd1306.c",
- "timeconv.c",
- "envrionment_demo.c",
- "aht20.c",
- "wifi_connecter.c",
- "getNTP.c"
- ]
四、总结
-
wi-fi
+关注
关注
14文章
2098浏览量
124260 -
HarmonyOS
+关注
关注
79文章
1966浏览量
29972 -
HiSpark
+关注
关注
1文章
156浏览量
6897
发布评论请先 登录
相关推荐
评论