578|4

28

帖子

0

资源

一粒金砂(中级)

【ESP32-C3-DevKitM-1】ESP32-C3获取网络时间 [复制链接]

本帖最后由 怀揣少年梦 于 2021-7-6 10:55 编辑

    ESP32-C3获取网络时间,可以通过SNTP获取。简单了解了一下SNTP,翻译过来就是简单网络时间协议,是从NTP改过来的,我的理解就是通过这个SNTP协议,可以与NTP服务器进行通信,然后获取服务器的时间即可更新系统时间。

1、本次还是直接复制官方例子-sntp到自己的工程目录,然后在VScode 里面,在编译之前先设置一下menuconfig的wifi密码和SSID。具体设置方法是在界面左下角有一个齿轮。点击齿轮即可进入设置界面。如图。

 

设置.png

  1. 找到wifi设置。输入密码和SSID,保存即可。

修改wifi接口.png

  1. 最后编译下载,效果如图。看到GuangZhou时间,显示星期,月,日,时,分,秒,年

 

效果图.png

 

  1. 程序解释。

先上一张流程图。

 

SNTP流程.png

 

5.最后就是代码注释,比较详细。

/* LwIP SNTP example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_sleep.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"
#include "esp_sntp.h"

static const char *TAG = "example";

/* Variable holding number of times ESP32 restarted since first boot.
 * It is placed into RTC memory using RTC_DATA_ATTR and
 * maintains its value when ESP32 wakes from deep sleep.
 */
RTC_DATA_ATTR static int boot_count = 0;

static void obtain_time(void);
static void initialize_sntp(void);

#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_CUSTOM
void sntp_sync_time(struct timeval *tv)//同步系统时间,弱定义,由于使用time_sync_notification_cb回调,
                                       //那么时间同步后会调用该函数
{
   settimeofday(tv, NULL);
   ESP_LOGI(TAG, "Time is synchronized from custom code");
   sntp_set_sync_status(SNTP_SYNC_STATUS_COMPLETED);//时间同步时,sntp同步标志置1.
}
#endif

void time_sync_notification_cb(struct timeval *tv)//通知时间同步事件
{
    ESP_LOGI(TAG, "Notification of a time synchronization event");
}

void app_main(void)
{
    ++boot_count;//ESP32自第一次BOOT,重启的次数
    ESP_LOGI(TAG, "Boot count: %d", boot_count);

    time_t now;//声明当前时间变量
    struct tm timeinfo;//声明时间信息结构体,具体内容在time.h里面
    time(&now);
    localtime_r(&now, &timeinfo);
    // Is time set? If not, tm_year will be (1970 - 1900). 判断时间是否设置,没有设置则连接wifi,并通过NTP获取时间
    if (timeinfo.tm_year < (2016 - 1900)) {
        ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
        obtain_time();//获取时间
        // update 'now' variable with current time
        time(&now);//
    }
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
    else {
        // add 500 ms error to the current system time.
        // Only to demonstrate a work of adjusting method!
        {
            ESP_LOGI(TAG, "Add a error for test adjtime");
            struct timeval tv_now;
            gettimeofday(&tv_now, NULL);
            int64_t cpu_time = (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec;
            int64_t error_time = cpu_time + 500 * 1000L;
            struct timeval tv_error = { .tv_sec = error_time / 1000000L, .tv_usec = error_time % 1000000L };
            settimeofday(&tv_error, NULL);
        }

        ESP_LOGI(TAG, "Time was set, now just adjusting it. Use SMOOTH SYNC method.");
        obtain_time();
        // update 'now' variable with current time
        time(&now);
    }
#endif

    char strftime_buf[64];//定义时间数组

    // Set timezone to Eastern Standard Time and print local time。设置时区(美国)东部时间
    setenv("TZ", "EST5EDT,M3.2.0/2,M11.1.0", 1);
    tzset();//时区设置
    localtime_r(&now, &timeinfo);//更新当地时间
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in New York is: %s", strftime_buf);//打印时间

    // Set timezone to China Standard Time。设置时区中国标准时间
    setenv("TZ", "CST-8", 1);
    tzset();
    localtime_r(&now, &timeinfo);//更新当地时间
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in GuangZhou is: %s", strftime_buf);//打印时间

    if (sntp_get_sync_mode() == SNTP_SYNC_MODE_SMOOTH) {
        struct timeval outdelta;
        while (sntp_get_sync_status() == SNTP_SYNC_STATUS_IN_PROGRESS) {
            adjtime(NULL, &outdelta);
            ESP_LOGI(TAG, "Waiting for adjusting time ... outdelta = %li sec: %li ms: %li us",
                        (long)outdelta.tv_sec,
                        outdelta.tv_usec/1000,
                        outdelta.tv_usec%1000);
            vTaskDelay(2000 / portTICK_PERIOD_MS);
        }//等待时间被调整
    }

    const int deep_sleep_sec = 10; //深度休眠时间
    ESP_LOGI(TAG, "Entering deep sleep for %d seconds", deep_sleep_sec);
    esp_deep_sleep(1000000LL * deep_sleep_sec);//ESP32进入深度休眠,10秒退出休眠
}
//获取NTP服务器的时间
static void obtain_time(void)
{
    ESP_ERROR_CHECK( nvs_flash_init() );
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK( esp_event_loop_create_default() );

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());//这个函数配置WIFI功能,通过读取menuconfig里面的wifi密码和SSID,即可连接wifi

    initialize_sntp();

    // wait for time to be set
    time_t now = 0;
    struct tm timeinfo = { 0 };
    int retry = 0;
    const int retry_count = 10;
    while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
        ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }//获取时间同步标志,等待系统时间更新
    time(&now);
    localtime_r(&now, &timeinfo);

    ESP_ERROR_CHECK( example_disconnect() );//时间更新后,断开连接
}

//初始化SNTP相关函数
static void initialize_sntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");
    /*1,2,3函数主要作用就是通过SNTP,同步时间*/
    sntp_setoperatingmode(SNTP_OPMODE_POLL);//1,设置SNTP操作模式
    sntp_setservername(0, "pool.ntp.org");//2,设置时间服务器链接
    sntp_set_time_sync_notification_cb(time_sync_notification_cb);//设置时间同步通知事件
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH //定义同步平滑模式
    sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);//设置SNTP时间同步模式:平滑模式,是通过调整时间函数逐步缩小误差。
#endif
    sntp_init();//3,SNTP初始化
}

6、最后说明一下,SNTP的函数相关说明在ESP-IDF编程指南的system-API中的systemtime里面。

 

SNTP说明.png  


回复

721

帖子

0

资源

一粒金砂(高级)

pool.ntp.org   这个时间服务器好用吗? 速度快吗?

点评

我是一个小白,我是10秒更新一次时间,还没有做到实时更新。这个服务器反正挺多人用来做做获取时间,应该速度还可以  详情 回复 发表于 2021-7-6 17:27

回复

28

帖子

0

资源

一粒金砂(中级)

tagetage 发表于 2021-7-6 14:02 pool.ntp.org   这个时间服务器好用吗? 速度快吗?

我是一个小白,我是10秒更新一次时间,还没有做到实时更新。这个服务器反正挺多人用来做做获取时间,应该速度还可以


回复

721

帖子

0

资源

一粒金砂(高级)

10秒更新一次时间会被拒绝服务的,一般24小时更新一次就可以了。

点评

这我还没了解到额,只是10秒之后重新获取时间  详情 回复 发表于 2021-7-6 18:03

回复

28

帖子

0

资源

一粒金砂(中级)

tagetage 发表于 2021-7-6 17:33 10秒更新一次时间会被拒绝服务的,一般24小时更新一次就可以了。

这我还没了解到额,只是10秒之后重新获取时间


回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/9 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表