• 方案介紹
    • 一、背景知識
    • 二、ESP8266獲取網(wǎng)絡(luò)時間
  • 附件下載
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

ESP8266調(diào)用NTP服務(wù)器進(jìn)行時間校準(zhǔn)

03/20 10:33
633
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

更多詳細(xì)資料請聯(lián)系.docx

共1個文件

一、背景知識

【1】什么是NTP服務(wù)器?

NTP是網(wǎng)絡(luò)時間協(xié)議(Network Time Protocol,簡稱NTP),是一種用于同步計算機(jī)時間的協(xié)議。NTP服務(wù)器指的是提供NTP服務(wù)的計算機(jī)或設(shè)備。NTP服務(wù)器的主要功能是保證網(wǎng)絡(luò)上的所有設(shè)備的時間同步,以確保各個設(shè)備相互之間的時間協(xié)調(diào)一致。NTP服務(wù)器通常連接到具有高度精確時間源的設(shè)備,例如:GPS接收器或原子鐘,以確保提供準(zhǔn)確如一的時間。網(wǎng)絡(luò)上的計算機(jī)可以通過連接到NTP服務(wù)器來同步其時間,并確保它們在同一時刻進(jìn)行操作。

img

目前有許多可以使用的NTP服務(wù)器,以下是一些常用的NTP服務(wù)器列表:

1. cn.ntp.org.cn
2. ntp.sjtu.edu.cn
3. ntp.linux.org.cn
4. time.nist.gov.cn
5. ntp.aliyun.com
6. ntp.api.bz
7. ntp1.aliyun.com
8. time1.cloud.tencent.com
9. pool.ntp.org.cn

【2】RTC實時時鐘是什么?

RTC (Real-Time Clock)實時時鐘,是指一種專門用于記憶日期、時間的計時芯片或模塊。一般包括一個時鐘芯片、一塊石英晶體、一塊溫度補(bǔ)償電路、電源管理電路等組成。RTC可以精確地記錄日期和時間,即使是在斷電等異常情況下,也能保持記錄的時間長達(dá)數(shù)年。常常用于嵌入式系統(tǒng)、數(shù)據(jù)采集設(shè)備等領(lǐng)域,是一種至關(guān)重要的設(shè)備。在某些系統(tǒng)應(yīng)用中,RTC也會成為其他設(shè)備的時鐘源,如單片機(jī)微控制器單位等。

RTC的時間精度通常為ppm 級別,即每百萬分之一,能夠滿足大多數(shù)實時應(yīng)用場景的要求。為了提高RTC的穩(wěn)定度和精度,許多RTC都帶有自動校正功能,可以自動從外部時鐘源或NTP服務(wù)器中獲取準(zhǔn)確的時間,并進(jìn)行校正。同時,許多RTC還會集成電源管理功能,支持低功耗模式以延長電池壽命。

二、ESP8266獲取網(wǎng)絡(luò)時間

要通過ESP8266聯(lián)網(wǎng)并獲取網(wǎng)絡(luò)時間,需要執(zhí)行以下步驟:

  1. STM32F103ZET6上配置UART串口以與ESP8266進(jìn)行通信。
  2. 使用AT指令將ESP8266連接到Wi-Fi網(wǎng)絡(luò)。可以使用以下指令:
AT+CWJAP="SSID","password"

其中,替換 “SSID” 為自己的Wi-Fi網(wǎng)絡(luò)名稱,“password” 是Wi-Fi密碼。

  1. 使用AT指令連接到NTP服務(wù)器并獲取時間。您可以使用以下指令:
AT+CIPSNTPCFG=0,1,"pool.ntp.org"
AT+CIPSNTPTIME?

這將連接到ntp服務(wù)器并檢索當(dāng)前的UTC時間。

  1. 將ESP8266返回的UTC時間轉(zhuǎn)換為本地時間。您需要知道您所在的時區(qū),并對UTC進(jìn)行適當(dāng)?shù)恼{(diào)整。
  2. 將本地時間設(shè)置為STM32F103ZET6上的RTC實時時鐘。

下面是一個示例代碼

#include <stdio.h>
#include "stm32f10x.h"

// UART配置
void uart_init() {
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    USART_Cmd(USART1, ENABLE);
}

// 發(fā)送AT指令并等待響應(yīng)
int send_at_command(char* command, char* response, uint32_t timeout) {
  // 發(fā)送命令
  USART_SendData(USART1, (uint8_t*)command, strlen(command));
  
  // 等待響應(yīng)
  uint32_t start_time = HAL_GetTick();
  while ((HAL_GetTick() - start_time) < timeout) {
    if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET) {
      char c = USART_ReceiveData(USART1);
      
      // 檢查是否收到了預(yù)期的響應(yīng)
      if (strstr(response, c) != NULL) {
        return 0; // 成功
      }
    }
  }
  
  return -1; // 超時或沒有收到預(yù)期的響應(yīng)
}

// 連接ESP8266到Wi-Fi
void connect_to_wifi() {
  char command[50];
  char response[100];
  
  // 設(shè)置Wi-Fi SSID和密碼
  sprintf(command, "AT+CWJAP="%s","%s"rn", "YourSSID", "YourPassword");
  send_at_command(command, "OK", 5000);
}

// 連接到NTP服務(wù)器并獲取時間
int get_ntp_time(uint32_t* time) {
  char response[100];
  
  // 配置SNTP客戶端
  send_at_command("AT+CIPSNTPCFG=0,1,"pool.ntp.org"rn", "OK", 5000);
  
  // 獲取時間
  send_at_command("AT+CIPSNTPTIME?rn", response, 5000);
  
  // 解析響應(yīng)并提取時間戳
  char* token = strtok(response, ",");
  uint32_t timestamp = atoi(token);
  *time = timestamp - 2208988800UL; // 轉(zhuǎn)換為Unix時間戳
  
  return 0;
}

// 將時間設(shè)置到RTC
void set_rtc_time(uint32_t time) {
  // 啟用PWR和BKP外設(shè)時鐘
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  
  // 解鎖備份寄存器區(qū)域
  PWR_BackupAccessCmd(ENABLE);
  
  // 配置RTC
  RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128); // RTC時鐘源為HSE/128
  RCC_RTCCLKCmd(ENABLE); // 啟用RTC時鐘
  
  RTC_InitTypeDef RTC_InitStructure;
  // 配置RTC時鐘 
    RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; RTC_InitStructure.RTC_AsynchPrediv = 127; 
    RTC_InitStructure.RTC_SynchPrediv = 255; 
    RTC_Init(&RTC_InitStructure);

// 設(shè)置RTC時間 
    RTC_TimeTypeDef RTC_TimeStruct; 
    RTC_DateTypeDef RTC_DateStruct;

// 將Unix時間戳轉(zhuǎn)換為RTC時間和日期 
  uint32_t days = time / 86400; 
    uint32_t seconds = time % 86400; 
    uint32_t hours = seconds / 3600; 
    uint32_t minutes = (seconds % 3600) / 60; 
    uint32_t secs = (seconds % 3600) % 60; 
    uint32_t year = 1970; 
    uint32_t month = 1; 
    while (days > 365) { if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { days -= 366; } else { days -= 365; } year++; } 
    while (days > 0) { if (month == 2) 
    { if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { if (days > 29) { days -= 29; } else { break; } } else { if (days > 28) { days -= 28; } else { break; } } } else if (month == 4 || month == 6 || month == 9 || month == 11) { if (days > 30) { days -= 30; } else { break; } } else { if (days > 31) { days -= 31; } else { break; } } month++; if (month > 12) { month = 1; year++; } }

RTC_TimeStruct.RTC_Hours = hours; RTC_TimeStruct.RTC_Minutes = minutes; RTC_TimeStruct.RTC_Seconds = secs; RTC_DateStruct.RTC_Date = days; RTC_DateStruct.RTC_Month = month; RTC_DateStruct.RTC_Year = year - 2000;

// 設(shè)置RTC時間和日期 
    RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct); 
    RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct); }

int main() 
{ 
    // 初始化UART串口 
    uart_init();

   // 連接ESP8266到Wi-Fi
    connect_to_wifi();

// 獲取NTP時間 
    uint32_t ntp_time; get_ntp_time(&ntp_time);

// 將時間設(shè)置到
    RTC set_rtc_time(ntp_time);

while (1) { // 做其他的事情... } }
  • 更多詳細(xì)資料請聯(lián)系.docx
    下載

相關(guān)推薦