Per NTP Protokoll lässt sich relativ einfach die aktuelle Zeit holen und verwerten. Die relevanten Instruktionen als Terminalmitschnitt lauten
AT+CIPSTART=1,"UDP","193.67.79.202",371,CONNECTOKAT+CIPSEND=1,3OK> XSEND OK+IPD,1,4:пы./OKAT+CIPCLOSE=11,CLOSEDOKGrün sind die gesendeten AT-Befehle, magenta hinterlegt die Rückgabe und in gelber Schrift die vier Byte mit der eigentlichen Zeitinformation
Die Rückgabe ist ein Wert vom Typ Long:
"[..] Die Zeitstempel im NTP sind 64 Bits lang. 32 Bits kodieren die Sekunden seit dem 1. Januar 1900 00:00:00 Uhr, weitere 32 Bits den Sekundenbruchteil. Auf diese Weise lässt sich ein Zeitraum von 232 Sekunden (etwa 136 Jahre) mit einer Auflösung von 2−32 Sekunden (etwa 0,23 Nanosekunden) darstellen.[..]" [1]
Bascom erfordert noch ein wenig eine Umrechnung und Korrektur, kann dann aber den gewonnen Long-Wert einfach in die eigene Systemzeit umrechnen
Im Folgenden ist ein Code dargestellt, der alle fünf Sekunden via NTP die aktuelle Zeit holt und im AVR die Systemzeit stellt. Hier ist eine User-Clock verwendet, die Zeitinformation wird aber nicht wirklich gespeichert. Dazu wäre noch eine externe RTC notwending. Sofern ein LCD angeschlossen und aktiviert ist, wird Zeit und Datum dort dargestellt
' ------------------------------------------------------------------------------' µC holt NTP und stellt dar'' HW:tr045-R06' - ESP8266 am seriellen Port' - LCD für Statusausgabe (optional)' - Baudratenclock'' V1.0:' V1.1: NTP auswerten ohne DST Korrektur (nur manueller Fixwert => Offset_gmt)' V1.2: mit DST Korrektur'' ------------------------------------------------------------------------------$Regfile="m8def.dat"$Crystal=14745600 ' externer Baudratenclock$hwstack=40$swstack=16$framesize=32$baud=57600$version 1,2,0' ------------------ Konstanten const mySSID = "meineSSID" const myPW = "meinPW" const NotausgangZeit = 10000 const LCD_Ausgabe = 1 const Offset_gmt = 7200 ' ------------------ Subroutinen deklarieren declare sub Warte_OK_Error(byval Suchstring as string*10,byval NoDelete as byte) declare Sub Ntp_dst_correction ' ------------------ Deklarationen ' Variablen dim i as byte, j as byte dim Empfangs_Ticker as word dim Sendestring as string * 250, headerstring as string * 100, SendeKanal as string*1 dim myIPAdress as string *15 dim strdummy as string *10 dim Flagbyte as byte Flag_ok alias Flagbyte.0 Flag_Error alias Flagbyte.1 ' Ntp Stuff Dim Tt(4) As String * 1 Dim Ss(4) As Byte Dim L1 As Long At Ss Overlay ' Overlay a long variable to receive-string Dim L2 As Long ' with overlay you need no transfer from the byte-array to a long-variable ' UART ISR const Uart_string_laenge=45 Dim Uart_get_char As Byte , Uart_string_len As Byte , Uart_char As String * 1 , Uart_string As String * Uart_string_laenge ', Str_laenge As Byte ' Timer Config Timer0 = Timer , Prescale = 64 Const Timer0_preload = 131' Timer1 tickt im Sekundentakt On Timer0 Timer0_isr 'I2C Config Scl = Portc.5 Config Sda = Portc.4 #if LCD_Ausgabe=1 ' LCD Config Lcdpin = Pin , Db4 = Portd.7 , Db5 = Portd.6 , Db6 = Portd.5 , Db7 = Portd.4 , E = Portb.1 , Rs = Portb.0 Config Lcd = 16 * 2 initlcd Cls Cursor Off LCDLight alias portb.2:config LCDLight = output:set lcdlight ' Pin für LCD Beleuchtung #endif 'Config Clock Config Clock = User Config Date = Dmy , Separator = . ' Interrupts On Urxc Uart_isr' ------------------ Hauptschleife --------------------------------------------- #if LCD_Ausgabe=1 lcd Version(1) lowerline:lcd version(2) #endif wait 1 Enable Urxc enable timer0 enable interrupts ' ESP8266 initialisieren $include "ESP8266Init.bas"do Print "AT+CIPMUX=1" call Warte_OK_Error("",0) Print "AT+CIPSTART=1," ; Chr(34) ; "UDP" ; Chr(34) ; "," ; Chr(34) ; "193.67.79.202" ; Chr(34) ; ",37" call Warte_OK_Error("",0) Print "AT+CIPSEND=1,3" call Warte_OK_Error("",0) uart_string="" Print "X" call Warte_OK_Error("+IPD",1) waitms 100 i = instr(uart_string,"+IPD") if i>0 then i = i + 9 strdummy = mid(uart_string,i,4) Tt(1) = Mid(strdummy , 4 , 1) 'from big endian to little endian Tt(2) = Mid(strdummy , 3 , 1) 'swap the bytes Tt(3) = Mid(strdummy , 2 , 1) Tt(4) = Mid(strdummy , 1 , 1) Ss(1) = Asc(tt(1)) 'this is L1 split in 4s by overlay Ss(2) = Asc(tt(2)) Ss(3) = Asc(tt(3)) Ss(4) = Asc(tt(4)) L2 = L1 + 1139293696 call Ntp_dst_correction Time$ = Time(l2) 'set the time Date$ = Date(l2) 'set the date #if LCD_Ausgabe=1 cls lcd time$; " ";_day;".";_month;". " lowerline lcd "Stamp:";l2 'lcd date$ #endif end if uart_string = "" Print "AT+CIPCLOSE=1" call Warte_OK_Error("",0) wait 5loopend' ------------------------------------------------------------------------------' -- Subroutinen ---' ------------------------------------------------------------------------------Sub Warte_OK_Error(byval Suchstring as string*10,byval NoDelete as byte) Empfangs_Ticker=0 if Suchstring="" then ' warte bis OK oder ERROR empfangen wird while instr(Uart_string,"OK")=0 AND instr(uart_string,"ERROR")=0 if Empfangs_Ticker > NotausgangZeit then exit while 'Notausgang end if wend else while instr(Uart_string,Suchstring)=0 if Empfangs_Ticker > NotausgangZeit then exit while 'Notausgang end if wend end if ' lösche nur, wenn NoDelete-Byte =0 if NoDelete <>1 then Uart_string = "" end if Flag_error = 0 Flag_ok = 0 Empfangs_Ticker = 0end subSub Ntp_dst_correction 'Dont change order of time and date variables !!! This order is required for Date/Time functions used. 'this routine is orginated by framuel Local Second As Byte Local Minute As Byte Local Hour As Byte Local Day As Byte Local Month As Byte Local Year As Byte Local Dow As Byte 'Day of week Day = Date(l2) 'set 3 variables: Day, Month, Year, so Year contains now current year 'DST starts at the last sunday of March, so let's see what weekday the 1st of April is Month = 4 Day = 1 Hour = 2 Minute = 0 Second = 0 Dow = Dayofweek(day) '0 = Monday to 6 = Sunday Day = 31 - Dow 'Now count back the days until last sunday Month = 3 'and set month to March If l2 >= Syssec(second) Then 'DST ends at the last sunday of October, so let's see what weekday the 1st of November is Day = 1 Month = 11 Dow = Dayofweek(day) '0 = Monday to 6 = Sunday Day = 31 - Dow 'Now count back the days until last sunday Month = 10 'and set month to October If l2 < Syssec(second) Then l2 = l2 + 7200 'subtract one hour End If End IfEnd Sub ' ISR Routinene ------------------------------------------------------------- Uart_isr: Uart_get_char = Udr Uart_char = Chr(uart_get_char) Uart_string =Uart_string + Uart_char ' warte auf Schlüsselwörter Empfangs_Ticker=0 ' Wartewatchdog zurücksetzten, da Daten reinkamen if instr(Uart_string,"OK")>0 then Flag_ok=1 elseif instr(uart_string,"ERROR")>0 then Flag_Error=1 else Flag_ok=0 Flag_Error=0 end if Return ' Diese Routine wird jede mSekunde aufgerufen wenn Timer0 aktiviert ist Timer0_isr: ' Timer0 wieder neu vorladen Timer0 = Timer0_preload incr Empfangs_Ticker return '******************* local Subroutines **********************************'clock routinesSetdate:ReturnSettime:ReturnGetdatetime:ReturnDie notwendinge ESP8266Init.bas ist im Downloadbereich unten verfügbar