;uhr_LCD.a51 ************************************************************************************** ;********** Uhrzeit wird mit Stunden, Minuten, Sekunden im LC-Display angezeigt ******************* ;********** Timer2 dient als Zeitbasis, da echter 16-Bit-Timer mit Reload ist die Zeit hochpräzise ;********** In der Interrupt-Service-Routine ist ein Zähler realisiert, der eigene Speicherstellen ;********** für Sekunden-Einer, Sekundenzehner, Minuteneiner etc besitzt, so dass die Ausgabe an ;********** das LCD-Display oder an externe 7-Segment-anzeigen ohne Umrechnung von Hex nach BCD ;********** möglich ist. ;********** Zu diesem Projekt gehört auch die Datei lcd8252.a51 in der die LCD-Routinen stehen ;************************************************************************************************** cseg at 0 ;Programmanfangsadresse include C51RD2.inc ;Registeradressen einbinden Extern Code initLCD,loeschzeile1,loeschzeile2,textaus,zifferaus,cursorpos,cursoran,cursoraus ;LCD-Routinen in der Datei lcd8252.a51 im Ordner \hilf_asm\ ;********** Definitionen und Anschlussbelegungen ************************************************** ausgabe data p2 ;Ausgabe an sechs externe 7-Segmentanzeigen im Multiplex stellen bit p3.3 ;Taster an p3.3 pluseins bit p3.2 ;Taster an P3.2 basis equ 60h ;Basisadresse sekE data basis+1 ; sekZ data basis+2 ; minE data basis+3 ; minZ data basis+4 ; stdE data basis+5 ; stdZ data basis+6 ; ms100 data basis+7 ;10ms-Zähler weckStdE data basis+8 weckStdZ data basis+9 weckMinE data basis+10 weckMinZ data basis+11 weckSekE data basis+12 weckSekZ data basis+13 blink bit 00h ;Adresse reloadH equ high(0ffffh-10000); reloadL equ low (0ffffh-10000); stack equ 2fh ;beginn Stack oberhalb bitadressierbarer Bereich ;********** Programm ****************************************************************************** ljmp go ;Sprung hinter Interrupteinsprungbereich org 002Bh ;Interrupt-Einsprung Timer2 jmp ISRtimer2 ;zur Interrupt-Service-Routine ;********** Initialisierungen ************************************************************ go: mov sp,#stack ;Stackbeginn setzen clr a mov stdZ,a ;Speicherstellen für Uhr null setzen mov stdE,a mov minZ,a mov minE,a mov sekZ,a mov sekE,a mov P2,a ;Timer2-Initialisierung mov T2MOD,#00000000b ; mov TH2,#reloadH ;Anfangswert Timer2 High-Byte (Aufwärtszähler) mov TL2,#reloadL ; Low-Byte mov RCAP2H,#reloadH ;Reloadwerte Highbyte mov RCAP2L,#reloadL ; Lowbyte mov T2CON,#00000100b ;Timer2 starten im Auto-Reload-Modus mov ip,#0 ;alle Interrupts haben gleiche Priorität setb EA ;Interrupts freigeben (IE.7) setb ET2 ;Enable Timer0 Interrupt (IE.5) ;LC-Display call initLCD ;Initialisierungs-Routine call loeschzeile1 ;Zeile 1 löschen call loeschzeile2 mov dptr,#text ;Text für Zeile 1, siehe unten call textaus ;********** Hauptprogrammschleife ********************************************************* haupt: ;mov ausgabe,sekE ;Ausgabe Sekunden-Einer an LEDs lcall LCDausgabe ;Uhrzeit an LCD-Display ausgeben lcall zeit ;Zeitverzögerung jb stellen,h1 ;Sprung wenn Taster Stellen gedrückt jmp haupt ;Hauptprogramm-Schleife h1: lcall UPstellen ;Unterprogramm Uhr stellen jmp haupt ;*********** Interrupt-Service-Routine **************************************************** ISRtimer2: push acc ;Akkuinhalt retten clr TF2 ;Flag löschen djnz ms100,ISRend ;Sprung falls noch nicht eine Sekunde vorbei mov ms100,#100 ;Konst für 100 x 10ms = 1s mov C,blink ;Bit invertieren cpl C mov blink,C inc sekE ;Sekundeneiner mov a,sekE cjne a,#10,ISRend iw1: mov sekE,#0 inc sekZ ;Sekundenzehner mov a,sekZ cjne a,#6,ISRend iw2: mov sekZ,#0 inc minE ;Minuteneiner mov a,minE cjne a,#10,ISRend iw3: mov minE,#0 inc minZ ;Minutenzehne mov a,minZ cjne a,#6,ISRend iw4: mov minZ,#0 inc stdE ;Stundeneiner mov a,stdE cjne a,#4,iw5 ;Einer = 4? Wenn ja mov a,stdZ cjne a,#2,iw5 ; und Zehner=2 dann 24 Uhr jmp iw7 ; und Sprung zu 00 Uhr iw5: mov a,stdE cjne a,#10,ISRend mov stdE,#0 iw6: inc stdZ ;Stundenzehner sjmp ISRend iw7: mov stdE,#0 ;00 Uhr mov stdZ,#0 lcall weckanfang ISRend: pop acc reti ;*********** stellen ********************************************************************* UPstellen: clr tr2 ;Timer anhalten, Uhr steht s1: jb stellen,s1 ;warten bis losgelassen call cursoran ;Cursor anschalten s2: call stdanzeigen ;Stunden in LCD-Display anzeigen jb pluseins,s3 ;+1 falls Taster gedrückt jb stellen,s5 ;zur Minutenanzeige falls Taster Stellen gedrückt jmp s2 ;Stunden erhöhen bei jedem Tastendruck s3: inc stdE ; mov a,stdE cjne a,#4,sw5 ;Einer = 4? Wenn ja mov a,stdZ ; Zehnerstelle cjne a,#2,sw5 ; prüfen ob 2 jmp sw7 ; dann 00 Uhr sw5: mov a,stdE ;Einer = 10? cjne a,#10,s4 mov stdE,#0 ; wenn ja null setzen sw6: inc stdZ ; und Zehnerstelle erhöhen sjmp s4 sw7: mov stdE,#0 ;00 Uhr mov stdZ,#0 s4: jb pluseins,s4 ;warte bis Taster losgelassen jmp s2 s5: jb stellen,s5 ;warte bis Taster losgelassen call stdanzeigen s12: call minanzeigen ;Minuten im LCD-Display anzeigen jb pluseins,s13 ;+1 falls Taster +1 gedrückt jb stellen,s15 ;zur Sekundenanzeige falls Taster Stellen gedrückt jmp s12 ;Minuten erhöhen bei jedem Tastendruck s13: inc minE mov a,minE cjne a,#10,s14 ;Einer = 10? Wenn ja sw3: mov minE,#0 ; Einer = 0 inc minZ ; und Zehner erhöhen mov a,minZ ; cjne a,#6,s14 ;Zehner = 6? Wenn ja sw4: mov minZ,#0 ; Zehner = 0 s14: jb pluseins,s14 ;warte bis Taster losgelassen jmp s12 s15: jb stellen,s15 ;warte bis Taster losgelassen call minanzeigen ;Minuten im LCD-Display anzeigen s22: call sekanzeigen ;Sekunden im LCD-Display anzeigen jb pluseins,s23 ;+1 falls Taster +1 gedrückt jb stellen,s25 ;Ende falls Taster stellen gedrückt jmp s22 ;Sekunden erhöhen bei jedem Tastendruck s23: inc sekE ;Sekundeneiner mov a,sekE cjne a,#10,s24 ;Einer = 10? Wenn ja sw1: mov sekE,#0 ; Einer = 0 inc sekZ ; und Zehner erhöhen mov a,sekZ ; cjne a,#6,s24 ;Zehner = 6? Wenn ja sw2: mov sekZ,#0 ; Zehner = 0 s24: jb pluseins,s24 ;warte bis Taster losgelassen jmp s22 s25: jb stellen,s25 ;warte bis Taster losgelassen call sekanzeigen s26: setb tr2 ;Timer wieder starten, Uhr läuft wieder call cursoraus ;LCD-Cursor aus ret ;********** LCD-Anzeige ****************************************************************** stdanzeigen: ;Stunden anzeigen mov a,#6 call cursorpos mov a,stdZ call zifferaus mov a,stdE call zifferaus ret minanzeigen: ;Minuten anzeigen mov a,#9 call cursorpos mov a,minZ call zifferaus mov a,minE call zifferaus ret sekanzeigen: ;Sekunden anzeigen mov a,#12 call cursorpos mov a,sekZ call zifferaus mov a,sekE call zifferaus ret LCDausgabe: call stdanzeigen ;Uhrzeit anzeigen call minanzeigen call sekanzeigen ret ;********************************************************WECKER*************************** weckanfang: mov a,#01h mov weckStdE,a mov weckMinE,a mov weckMinZ,a mov weckSekE,a mov weckSekZ,a mov a,stdE cjne a,weckStdE,endweck mov a,stdZ cjne a,weckStdZ,endweck mov a,MinE cjne a,weckMinE,endweck mov a,MinZ cjne a,weckMinZ,endweck mov a,SekZ cjne a,weckSekZ,endweck mov a,SekE cjne a,weckSekE,endweck ljmp alarman ;weck5: ;mov a,mtag ;cjne a,#weckTag,weck6 ;ljmp ;weck6: ;mov a,funk ;cjne a,#weckfunk, ;ljmp alarman: setb p2.3 lcall alarmaus alarmaus: lcall pause aus: clr p2.3 ljmp endweck pause: mov r1,#255 aussen: mov r0,#255 innen: djnz r0,innen djnz r1,aussen ret ljmp aus endweck: ret ;********** Zeitverzögerung mit Dreifachschleife ***************************************** zeit: mov r0,#0 ;Zeitkonstante zeit0: djnz r0,zeit0 ;255 x 2µs ret ; ;********* Text LC-Display ************************************************************** text: db 'Zeit: : : ',0 end