RT-Thread在Lan8720a和 lwip基础上移植ntp流程

发布时间:2023-10-30  

开发环境:野火的stm32f407,rt-thread studio版本是版本: 2.2.6,stm32f4的资源包为0.2.2。以RT-Thread中Lan8720和lwip协议栈的使用文章创建的工程为基础。

新建ntptest.c测试文件,移植以上参考的ntp代码,整理后如下:

#include
#include
#define SERVER_IP "114.67.237.130"
#define SERVER_PORT 123
#define TIMEOUT 10
//宏定义
#define NTP_TIMESTAMP_DELTA 2208988800ull //number of seconds between 1900 and 1970,1900-1970的时间差
#define SEC_TIME_ZONE + (86060) //Beijing,GMT+8, 时区差
typedef struct
{
uint8_t li_vn_mode; // Eight bits. li, vn, and mode.
// li. Two bits. Leap indicator.
// vn. Three bits. Version number of the protocol.
// mode. Three bits. Client will pick mode 3 for client.
uint8_t stratum; // Eight bits. Stratum level of the local clock.
uint8_t poll; // Eight bits. Maximum interval between successive messages.
uint8_t precision; // Eight bits. Precision of the local clock.
uint32_t rootDelay; // 32 bits. Total round trip delay time.
uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source.
uint32_t refId; // 32 bits. Reference clock identifier.
uint32_t refTm_s; // 32 bits. Reference time-stamp seconds.
uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second.
uint32_t origTm_s; // 32 bits. Originate time-stamp seconds.
uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second.
uint32_t rxTm_s; // 32 bits. Received time-stamp seconds.
uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second.
uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second.
} ntp_packet; // Total: 48 bytes.
int sockfd=-1;
int maxfd1;
fd_set readfds;
struct timeval timeout;
struct sockaddr_in servaddr;
int len;
int i;
uint8_t buf[48];
long local_timestamp;//uint32_t local_timestamp;
ntp_packet packet ;
struct tm * Net_time;
uint8_t NTP_Data[48]; //48字节的报文
int bsp_ntp_init(void)
{
NTP_Data[0]=0xa3;
//00100011, 0xa3,100 版本4
//00011011, 0x1b,011 版本3
//00010011, 0x13,010 版本2
//00001011, 0x0b,001 版本1
//后面分别发送了4个不同版本,都可以收到数据。
for(i=1;i<48;i++)NTP_Data[i]=0;//剩余的47字节为0
// servaddr.sin_family = AF_INET;
// servaddr.sin_port = htons(SERVER_PORT);
// servaddr.sin_addr.s_addr = inet_host(SERVER_IP);
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr.s_addr);
servaddr.sin_port = htons(SERVER_PORT);
if(sockfd>0)
{
//close(sockfd);
closesocket(sockfd);
sockfd=-1;
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
return -1;
}
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) != 0)
{
//close(sockfd);
closesocket(sockfd);
sockfd=-1;
return -1;
}
return 0;
}
int bsp_read_ntp(void)
{
if(sockfd<0)
{
if(bsp_ntp_init()<0)
{
rt_kprintf("sockfd is errn");
return -1;
}
}
send(sockfd, NTP_Data, sizeof(NTP_Data), 0);
rt_kprintf("send n");
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
maxfd1 = sockfd + 1;
timeout.tv_sec = TIMEOUT;
timeout.tv_usec = 0;
if (select(maxfd1, &readfds, NULL, NULL, &timeout) > 0)
{
if (FD_ISSET(sockfd, &readfds))
{
if ((len = recv(sockfd, buf, sizeof(buf), 0)) < 0)
{
//close(sockfd);
closesocket(sockfd);
sockfd=-1;
return -1;
}
packet.txTm_s = buf[40]<<24 | buf[40+1]<<16|buf[40+2]<<8 |buf[40+3];//由于本文的时间精度要求不高,故自己用服务器返回的时间作为对时的时间,并未用公式:时间差offset=((T2-T1)+(T3-T4))/2。而是用T3作为对时基准时间。
local_timestamp = packet.txTm_s - NTP_TIMESTAMP_DELTA;//减去1970和1900的差值
rt_kprintf( "unix_timestamp=%ldn",local_timestamp);
local_timestamp +=SEC_TIME_ZONE; //加上北京的时间差,GMT+8
Net_time = localtime(&local_timestamp); //秒数转换位标准时间
rt_kprintf("%d-%d-%d %d:%d:%drn",(Net_time->tm_year)+1900, (Net_time->tm_mon)+1, Net_time->tm_mday, Net_time->tm_hour,Net_time->tm_min,Net_time->tm_sec); //打印出时间
}
}
return 0;
}

主函数调用,代码如下:

extern int bsp_ntp_init(void);
extern int bsp_read_ntp(void);
int main(void)
{
int count = 1;
rt_thread_mdelay(5000);
bsp_ntp_init();
while (count++)
{
LOG_D("Hello RT-Thread!");
rt_thread_mdelay(1000);
bsp_read_ntp();
}
return RT_EOK;
}

编译无报错,下载测试,测试结果如下:

1.jpg

选择其中一个时间戳,利用时间戳转换工具比对,结果如下:

1.jpg

结果正常。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>