依靠ESP32 IDF提供的SNTP案例(..\esp-idf-v4.4\examples\protocols\sntp)和定时器案例(..\esp-idf-v4.4\examples\system\esp_timer),本人继续进行参赛项目的功能开发,使得Kaluga板在启动并联网后获取网络时间,之后启动s级定时器——为了后续进行周期性监测作准备。依然是单独创建time.c源文件,时间相关代码编写于此。
#include "main.h"
/* Private macro -------------------------------------------------- */
#define TAG "AITA TIME"
#define CONFIG_SNTP_TIME_SYNC_METHOD_IMMED 1
#define AITA_SNTP_MAX_RETRY_TIMES 10
// SNTP related --------------------------------------------------- //
/* Private functions ---------------------------------------------- */
/*********************************************************************
* FunctionName : sntp_notification_cb()
* Description : time synchronization callback
* Parameters : struct timeval *tv ——> epoch time struct pointer
* Returns : void
*********************************************************************/
void sntp_notification_cb(struct timeval *tv) {
ESP_LOGI(TAG, "Epoch sec: %d, usec: %d",
(int)tv->tv_sec, (int)tv->tv_usec);
}
/*********************************************************************
* FunctionName : initialize_sntp()
* Description : initialize sntp & synchronize system time
* Parameters : void
* Returns : void
*********************************************************************/
void initialize_sntp(void) {
ESP_LOGI(TAG, "Initializing SNTP");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
// 0 - server number, "pool.ntp.org" - server url
sntp_setservername(0, "pool.ntp.org");
sntp_set_time_sync_notification_cb(sntp_notification_cb);
sntp_init();
}
/*********************************************************************
* FunctionName : obtain_time()
* Description : obtain system time
* Parameters : void
* Returns : void
*********************************************************************/
void obtain_time(void) {
initialize_sntp();
// wait for time to be set
int retry = 0;
while(sntp_get_sync_status()==SNTP_SYNC_STATUS_RESET &&
++retry<AITA_SNTP_MAX_RETRY_TIMES) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)",
retry, AITA_SNTP_MAX_RETRY_TIMES);
vTaskDelay(2000 / portTICK_PERIOD_MS);
}
}
/* Exported functions --------------------------------------------- */
/*********************************************************************
* FunctionName : aita_PrintCST8()
* Description : print cst-8 timezone time
* Parameters : time_t *now ——> sytem local time
* Returns : void
*********************************************************************/
void aita_PrintCST8(time_t *now) {
char buf[64];
struct tm timeinfo;
// set timezone to China standard time
setenv("TZ", "CST-8", 1);
tzset();
localtime_r(now, &timeinfo);
strftime(buf, sizeof(buf), "%c", &timeinfo);
ESP_LOGI(TAG, "current date/time in Shanghai: %s", buf);
}
/*********************************************************************
* FunctionName : aita_InitSNTP()
* Description : sntp & print cst-8 timezone time
* Parameters : void
* Returns : void
*********************************************************************/
void aita_InitSNTP(void) {
time_t now;
struct tm timeinfo;
time(&now);
localtime_r(&now, &timeinfo);
// If time is not set, tm_year will be (1970 - 1900).
if(timeinfo.tm_year < (2016-1900)) {
ESP_LOGI(TAG, "time is not set yet.");
ESP_LOGI(TAG, "getting time over NTP.");
obtain_time();
// update 'now' variable with current time
time(&now);
}
// print China timezone time
aita_PrintCST8(&now);
}
// timer related -------------------------------------------------- //
/* Private functions ---------------------------------------------- */
/*********************************************************************
* FunctionName : periodic_timer_callback()
* Description : periodic timer callback function
* Parameters : void* arg ——> callback's argument
* Returns : void
*********************************************************************/
static void periodic_timer_callback(void* arg) {
int64_t time_since_boot = esp_timer_get_time();
ESP_LOGI(TAG, "periodic timer called, time since boot: %lld us",
time_since_boot);
aita_InitSNTP();
}
/* Exported functions --------------------------------------------- */
/*********************************************************************
* FunctionName : aita_InitTimer()
* Description : initialize timer
* Parameters : void
* Returns : void
*********************************************************************/
void aita_InitTimer(void) {
const esp_timer_create_args_t periodic_timer_args = {
.callback = &periodic_timer_callback,
.name = "periodic"
};
esp_timer_handle_t periodic_timer;
ESP_ERROR_CHECK(
esp_timer_create(&periodic_timer_args, &periodic_timer)
);
/* Start the timers */
ESP_ERROR_CHECK(
esp_timer_start_periodic(periodic_timer, 1000000)
);
ESP_LOGI(TAG, "started timers, time since boot: %lld us",
esp_timer_get_time());
}
/*********** (C) COPYRIGHT AITA TCU ********** END OF FILE **********/
项目入口app_main()中调用aita_InitSNTP()得到网络授时,调用aita_InitTimer()开启1s的周期性定时器。
图10-1 SNTP和定时器功能测试输出
引用: Jacktang 发表于 2022-9-22 07:20 网络授时,调用aita_InitTimer()开启1s的周期性定时器这里应该没问题吧
测试没问题,因为我的项目后面功能需要定时采集,还考虑记录本地log,发送心跳包等功能,需要有准确的时间,所以考虑先做授时,再开启定时器。
实际授时使用RTC,Timer使用通用定时器,互补影响的吧。