要使用 CycloneTCP 和 FreeRTOS 从 SNTP 服务器获取时间,请按以下步骤操作:
1. 准备工作
2. 实现代码
#include "net.h"
#include "sntp_client.h"
// 定义SNTP服务器地址(如 pool.ntp.org)
#define SNTP_SERVER "pool.ntp.org"
#define NTP_PORT 123
void sntpTask(void *pvParameters) {
SntpClientContext sntpContext;
NtpTimestamp timestamp;
while(1) {
// 初始化SNTP上下文
sntpClientInit(&sntpContext);
// 设置SNTP服务器
sntpClientSetServer(&sntpContext, SNTP_SERVER, NTP_PORT);
// 发送请求并获取时间(超时5秒)
error_t error = sntpClientGetTimestamp(&sntpContext, ×tamp, 5000);
if(error == NO_ERROR) {
// 转换NTP时间戳为Unix时间(1970年以来的秒数)
time_t unixTime = timestamp.seconds - NTP_EPOCH_DELAY;
// 转换为可读时间
struct tm *timeinfo = gmtime(&unixTime);
printf("SNTP Time: %04d-%02d-%02d %02d:%02d:%02dn",
timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday,
timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
} else {
printf("SNTP Request Failed! Error: %dn", error);
}
// 每10分钟同步一次
vTaskDelay(pdMS_TO_TICKS(10 * 60 * 1000));
}
}
void main() {
// 初始化FreeRTOS和CycloneTCP
netInit();
// 创建SNTP任务
xTaskCreate(sntpTask, "SNTP", configMINIMAL_STACK_SIZE * 2, NULL, 2, NULL);
// 启动调度器
vTaskStartScheduler();
}
3. 关键步骤说明
4. 常见问题
- 超时失败:
- 检查网络连通性(用
ping 测试)。
- 确保防火墙未阻断 UDP 123 端口。
- 时间精度:NTP 提供毫秒级精度(通过
timestamp.fraction)。
- 时区处理:返回的是 UTC 时间,需在应用层转换时区。
5. 高级配置
- 多个备用服务器:
sntpClientSetServer(&sntpContext, "0.pool.ntp.org", NTP_PORT);
sntpClientSetServer(&sntpContext, "1.pool.ntp.org", NTP_PORT);
- 硬件时钟同步:将
unixTime 写入 RTC 芯片。
- 安全 SNTP:使用
SNTS(需服务器支持并配置身份验证)。
确保在 net_config.h 中启用了 UDP 支持:
#define UDP_SUPPORT ENABLED