天天看点

esp8266 基于sntp协议更新系统时间esp8266 基于sntp协议更新系统时间

esp8266 基于sntp协议更新系统时间

我们esp8266设备,如何然他具有准确的系统时间呢?那就要依赖于sntp协议,一般芯片都集成了sntp协议,我们只需要使用就可以了。

1.创建一个sntp任务

sntp_example_task更新网络时间到本地

void app_main(void)
{
   //modify cdb 2019-12-19
   // printf("SDK version:%s\n", esp_get_idf_version());
   // Initialize NVS
    esp_err_t ret = nvs_flash_init();
    char sys_time[64] = {0};

    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }

    ESP_ERROR_CHECK(ret);
    //初始化wifi,并且联网
    initialise_wifi();
    //创建mqtt 处理线程
    ret = xTaskCreate((void*)mqtt_client_thread,
                  MQTT_CLIENT_THREAD_NAME,
                  MQTT_CLIENT_THREAD_STACK_WORDS,
                  NULL,
                  MQTT_CLIENT_THREAD_PRIO,
                  NULL);

    if (ret != pdPASS)  {
        DBG_C("mqtt create client thread %s failed\n", MQTT_CLIENT_THREAD_NAME);
    }

    //创建gpio led key处理任务
    ret = xTaskCreate((void*)gpio_task,
                  GPIO_THREAD_NAME,
                  GPIO_THREAD_STACK_WORDS,
                  NULL,
                  GPIO_THREAD_PRIO,
                  NULL);
    if (ret != pdPASS)  {
        DBG_C("qpio thread %s failed\n", GPIO_THREAD_NAME);
    }

	//创建sntp处理线程
    ret = xTaskCreate((void*)sntp_example_task,
                  SNTP_THREAD_NAME,
                  SNTP_THREAD_STACK_WORDS,
                  NULL,
                  SNTP_THREAD_PRIO,
                  NULL);
    if (ret != pdPASS)  {
        DBG_C("sntp thread %s failed\n", SNTP_THREAD_NAME);
    }

    //程序将进入死循环,防止退出,并且打印运行时间log,单位s,也开启rtos任务调度
    while(1)
    {  //调用获取系统时间接口,并且打印
        memset(sys_time,0,64);
        get_system(sys_time);
        DBG_C("the system is runing,runtime:%s\n",sys_time);
        vTaskDelay(1000 / portTICK_RATE_MS);
    }

}

           

这里注意下,我前面创建任务的函数第一个参数,函数名取地址赋值,发现编译由警告,其实函数名就是此函数的地址。

在component中添加user_sntp.c user_sntp.h

esp8266 基于sntp协议更新系统时间esp8266 基于sntp协议更新系统时间

2.附上user_sntp.c

/* 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 <stdlib.h>
#include <string.h>
#include <time.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"

#include "nvs_flash.h"

#include "lwip/apps/sntp.h"

/* The examples use simple WiFi configuration that you can set via
   'make menuconfig'.

   If you'd rather not, just change the below entries to strings with
   the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/


/* FreeRTOS event group to signal when we are connected & ready to make a request */
extern EventGroupHandle_t wifi_event_group;

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
extern int CONNECTED_BIT;

#define  DBG_C(...) printf("[%s,%d]",__FUNCTION__,__LINE__);printf(__VA_ARGS__)

static void initialize_sntp(void)
{
    DBG_C("Initializing SNTP\n");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_init();
}

static void obtain_time(void)
{
    DBG_C("Waiting for network connected\n");
    xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
                        false, true, portMAX_DELAY);
    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 (timeinfo.tm_year < (2016 - 1900) && ++retry < retry_count) {
        DBG_C("Waiting for system time to be set... (%d/%d)\n", retry, retry_count);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        time(&now);
        localtime_r(&now, &timeinfo);
    }
}

void get_system(char * nowtime)
{
    time_t now;
    struct tm timeinfo;

    time(&now);
    localtime_r(&now, &timeinfo);

    sprintf(nowtime,"%02d-%02d-%02d %02d:%02d",timeinfo.tm_year+1900,timeinfo.tm_mon+1,timeinfo.tm_mday,timeinfo.tm_hour,timeinfo.tm_min);
}

void sntp_example_task(void *arg)
{
    time_t now;
    struct tm timeinfo;
    char strftime_buf[64];

    time(&now);
    localtime_r(&now, &timeinfo);

    // Is time set? If not, tm_year will be (1970 - 1900).
    if (timeinfo.tm_year < (2016 - 1900)) {
        DBG_C("Time is not set yet. Connecting to WiFi and getting time over NTP.\n");
        obtain_time();
    }

    // Set timezone to Eastern Standard Time and print local time
    // setenv("TZ", "EST5EDT,M3.2.0/2,M11.1.0", 1);
    // tzset();

    // Set timezone to China Standard Time
    setenv("TZ", "CST-8", 1);
    tzset();

    while (1) {
        // update 'now' variable with current time
        time(&now);
        localtime_r(&now, &timeinfo);

        if (timeinfo.tm_year < (2016 - 1900)) {
            DBG_C("The current date/time error\n");
        } else {
            strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
          //  DBG_C("The current date/time in Shanghai is: %s\n", strftime_buf);
        }

       // DBG_C("Free heap size: %d\n", esp_get_free_heap_size());
        vTaskDelay(1000 / portTICK_RATE_MS);
    }
}


           

3.附上user_sntp.h

#ifndef _ESP8266_MY_SNTP_H_
#define _ESP8266_MY_SNTP_H_

void sntp_example_task(void *arg);
//获取系统时间的函数
void get_system(char *nowtime);

#endif
           

3.修改component.mk

#
# Component Makefile
#

COMPONENT_SRCDIRS := mqtt gpio sntp

COMPONENT_ADD_INCLUDEDIRS += mqtt/include
COMPONENT_ADD_INCLUDEDIRS += gpio/include
COMPONENT_ADD_INCLUDEDIRS += sntp/include
           

4.编译

make clean

make

5.烧录运行

esp8266 基于sntp协议更新系统时间esp8266 基于sntp协议更新系统时间

至此,开发板就存在可用的api获取准确的系统时间了,哪里需要,就在哪调用即可。

继续阅读