一、连接WIFI

在进行时间同步之前,先连接WIFI

#include "wifi.h"

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"


static wifi_status_t wifi_status = WIFI_STATUS_DEINIT;          // WIFI 默认为未初始化状态
static EventGroupHandle_t s_wifi_event_group;                   // WIFI 事件组
esp_event_handler_instance_t instance_any_id;                   // 注册事件处理程的标识
esp_event_handler_instance_t instance_got_ip;                   //

/* 事件组允许有多个事件标志位 */
static const int WIFI_STATUS_INIT_BIT = BIT0;                   // WIFI 初始化状态
static const int WIFI_STATUS_START_BIT = BIT1;                  // WIFI 启动状态
static const int WIFI_STATUS_SCAN_BIT = BIT3;                   // WIFI 扫描状态
static const int WIFI_STATUS_CONNECTED_BIT = BIT4;              // WIFI 连接状态

/* 需要连接的WIFI名称和密码 */
static wifi_sta_config_t cfg_sta = {
    .ssid = "test",
    .password = "test8888",
};

/* 互斥锁 */
SemaphoreHandle_t xWifiSemaphore;

static const char *TAG = "WIFI";

/**
 * @brief WIFI 事件
 * 
 * @param arg 
 * @param event_base 
 * @param event_id 
 * @param event_data 
 */
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    /* WIFI事件 */
    if (event_base == WIFI_EVENT)
    {
        switch (event_id)
        {
            /* WIFI 就绪 */
            case WIFI_EVENT_WIFI_READY:
                ESP_LOGI(TAG,"ESP32 WiFi ready");
                break;
            /* WIFI 扫描完成 */
            case WIFI_EVENT_SCAN_DONE:
                ESP_LOGI(TAG,"ESP32 finish scanning AP");
                xEventGroupSetBits(s_wifi_event_group, WIFI_STATUS_SCAN_BIT);      // 设置WIFI标志位为打开状态
                break;
            /* WIFI 启动 */
            case WIFI_EVENT_STA_START:
                ESP_LOGI(TAG,"ESP32 station start");
                xEventGroupSetBits(s_wifi_event_group, WIFI_STATUS_START_BIT);      // 设置WIFI标志位为打开状态
                wifi_status = WIFI_STATUS_START;                                    // 设置WIFI为打开状态
                break;
            /* WIFI 关闭 */
            case WIFI_EVENT_STA_STOP:
                ESP_LOGI(TAG,"ESP32 station stop");
                xEventGroupClearBits(s_wifi_event_group, WIFI_STATUS_START_BIT);    // 设置WIFI标志位为关闭状态
                wifi_status = WIFI_STATUS_STOP;                                     // 设置WIFI为关闭状态
                break;
            /* WIFI 连接成功 */
            case WIFI_EVENT_STA_CONNECTED:
                ESP_LOGI(TAG,"ESP32 station connected to AP");
                xEventGroupSetBits(s_wifi_event_group, WIFI_STATUS_CONNECTED_BIT);          // 设置WIFI标志位为关闭状态
                wifi_status = WIFI_STATUS_CONNECTED;                                        // 设置WIFI为关闭状态
                break;
            /* WIFI 断开连接 */
            case WIFI_EVENT_STA_DISCONNECTED:
                ESP_LOGI(TAG,"ESP32 station disconnected from AP");
                xEventGroupClearBits(s_wifi_event_group, WIFI_STATUS_CONNECTED_BIT);        // 设置WIFI标志位为关闭状态
                wifi_status = WIFI_STATUS_DISCONNECTED;                                     // 设置WIFI为关闭状态
                break;
            /* WIFI 接入点认证方式改变 */
            case WIFI_EVENT_STA_AUTHMODE_CHANGE:
                ESP_LOGI(TAG,"the auth mode of AP connected by ESP32 station changed");
                break;

            default:
                ESP_LOGI(TAG,"Other status");
                break;
        }
    }
    
    if(event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG, "Got IP: " IPSTR,  IP2STR(&event->ip_info.ip));
    }
}


/**
 * @brief WIFI 初始化
 * 
 */
void app_wifi_init(void)
{
    // 初始化 NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    /* 初始化底层TCP/IP堆栈 */
    ESP_ERROR_CHECK(esp_netif_init());

    s_wifi_event_group = xEventGroupCreate();                           // 创建新的事件组
    ESP_ERROR_CHECK(esp_event_loop_create_default());                   // 创建默认事件循环
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();       // 创建默认WIFI STA
    assert(sta_netif);

    /* 使用默认参数初始化WIFI */
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );

    /* 向默认循环注册事件处理程序 */
    ESP_ERROR_CHECK( esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, instance_any_id) );
    ESP_ERROR_CHECK( esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, instance_got_ip) );

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );                // 设置WIFI模式

    xEventGroupSetBits(s_wifi_event_group, WIFI_STATUS_INIT_BIT);       // 设置WIFI标志位为初始化状态
    wifi_status = WIFI_STATUS_INIT;                                     // 设置WIFI状态为初始化状态
    xWifiSemaphore = xSemaphoreCreateMutex();                           // 创建互斥锁
}

void app_main(void)
{
    app_wifi_init();
    ESP_ERROR_CHECK( esp_wifi_start() );   // 启动WIFi

    /* 而直接将wifi_sta_config_t(或指针)转为wifi_config_t(或指针)是GCC的拓展语法,如下 */
    esp_wifi_set_config(WIFI_IF_STA, (wifi_config_t *) &cfg_sta);

    esp_wifi_connect();
}

二、时间同步

/**
 * @brief 同步时间完成后的回调函数
 * 
 * @param tv 
 */
void time_update_callback(struct timeval* tv) 
{
    /* 设置时区 */
    setenv("TZ", "CST-8", 1);
    tzset();
}

/**
 * @brief 在联网的情况下获取网络时间 
 * 
 */
static void get_network_time(void)
{
    /* 等待 WIFI 连接*/
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_STATUS_CONNECTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY);

    /* SNTP校时 */
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "ntp.aliyun.com");
    sntp_set_time_sync_notification_cb(time_update_callback);
    sntp_init();                                        // 启动校时 
}

注意:不使用sntp_set_time_sync_notification_cb()注册同步成功回调时,也可以使用sntp_get_sync_status()轮询检测同步是否完毕

三、获取系统时间

static struct tm timeinfo = {0};           // 时间寄存器
time_t now = 0;

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

/* 打印获取到的时间 */
char str[64];
strftime(str, sizeof(str), "%c", &timeinfo);
ESP_LOGI(TAG, "time updated: %s", str);

ESP_LOGI(TAG, "%d%d:%d%d", timeinfo.tm_hour / 10, timeinfo.tm_hour % 10, timeinfo.tm_min / 10, timeinfo.tm_min % 10);
ESP_LOGI(TAG, "%d-%d-%d", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);

switch (timeinfo.tm_wday)
{
case 0:
    ESP_LOGI(TAG, "星期日");
    break;
case 1:
    ESP_LOGI(TAG, "星期一");
    break;
case 2:
    ESP_LOGI(TAG, "星期二");
    break;
case 3:
    ESP_LOGI(TAG, "星期三");
    break;
case 4:
    ESP_LOGI(TAG, "星期四");
    break;
case 5:
    ESP_LOGI(TAG, "星期五");
    break;
case 6:
    ESP_LOGI(TAG, "星期六");
    break;
default:
    break;
}

参考文献

ESP32 之 ESP-IDF 教学(二十)—— SNTP校时:<https://blog.csdn.net/m0_50064262/article/details/126690030

原文地址:http://www.cnblogs.com/jzcn/p/16827218.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性