ESP32 SNTP校时
一、连接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
本文来自博客园,作者:浇筑菜鸟,转载请注明原文链接:https://www.cnblogs.com/jzcn/p/16827218.html
如本博客的内容侵犯了你的权益,请与以下地址联系,本人获知后,马上删除。同时本人深表歉意,并致以崇高的谢意! cn_jiaozhu@qq.com
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)