Stoppuhr mit Assembler

hallo liebe technik Freunde,

ich arbeite zur zeit an einem schulprojekt, ich muss eine stoppuhr in Assembler programmieren, welches später mit einem microcontroller verbunden wird und über eine lcd angezeigt.
unser stoppuhr soll folgende voraussetzungen beherrschen,
1) startknopf
2) stoppknopf
3) speichern des wertes für 5 sekunden die stoppuhr soll aber weiterlaufen der wert der gestoppt wird soll 5 sek. angezeigt werden
4)resetknopf


ich habe schon folgendes programm aber da ist ein fehler drin, die stoppuhr zählt bis 09 und dann zählt er mit 0A, 0B, ... weiter
und das ist ya unerwünscht das sollen dezimal zahlen sein ich hoffe ihr könnt mir weiterhelfen und sagen wie ich das ansteuern kann mit dem microcontroller....


Programm:
$include (reg52.inc)

Starttaster bit P0.0
Stopptaster bit P0.1
Resettaster bit P0.2
Merkertaster bit P0.3
Abruftaster bit P0.4


org 0000h
LJMP start




;Einsprungadresse Interrupt-Serviceroutine für Timer 0
org 000Bh
LJMP isrTimer0



org 0100h
start: CALL initRegister ;Register initialisieren
CALL initTimer0 ;Interrupt Timer initialisieren

loop: CALL ausgabe ;berechnete Werte
ausgeben

JB Starttaster, Weiter_bei_Stop ;Abfrage des
Starttasters
SETB ET0 ;Freigabe Timer 0

Weiter_bei_Stop: JB Stopptaster, Weiter_bei_Merker ;Abfrage des
Stopptasters
CLR ET0 ;Zuruecksetzen des
Timers

Weiter_bei_Merker: JB Merkertaster, Weiter_bei_Abruf ;Abfrage des
Merkertasters
MOV 061h,R0 ;Schreibe die gestoppten
Werte
MOV 062h,R1 ;an Stellen im
Speicher
MOV 063h,R2
MOV 064h,R3
MOV 065h,R4
MOV 066h,R5

Weiter_bei_Abruf: JB Abruftaster,Weiter_bei_Reset ;Abfrage
Abfragetaster
MOV R0,061h ;gespeicherte Werte den
MOV R1,062h ;Registern zuweisen
MOV R2,063h
MOV R3,064h
MOV R4,065h
MOV R5,066h

CALL ausgabe ;gespeicherte Werte ausgeben

Weiter_bei_Reset: JB Resettaster, Weiter_bei_nichts ;Abfrage
Resettaster
CALL initRegister ;Register
zuruecksetzen
Weiter_bei_nichts: LJMP loop ;Endlosschleife



initRegister:
MOV R0,#0 ;bestimmt welche der Anzeigen aktiv ist
MOV R1,#0 ;Zähler von o bis 249 -->4ms*250 = 1 Sec

MOV R2,#0 ;für Segment rechts Sekunden Einer
MOV R3,#0 ;für Segment Mitte rechts Sekunden Zehner
MOV R4,#0 ;für Segment Mitte links Minuten Einer
MOV R5,#0 ;für Segment links Minuten Zehner

RET

initTimer0:


SETB EA ;Globale INT Freigabe. Bit im Reg IE

MOV TMOD,#00000001b ;Timer0 konfiguieren, Modus1: 16bit
Zaehler

MOV TL0,#060h ;Timer0 vorladen

MOV TH0,#0F0h ;65536 - 4000 = 61536 = F060h (4ms)

SETB TR0 ;Start Timer0

RET ;Ruecksprung aus dem Unterprogramm


;Interrupt-Service-Routine für Timer0
isrTimer0:


MOV TL0,#060h ;Timer0 erneut vorladen

MOV TH0,#0F0h ;65536 - 4000 = 61536 = F060h (4ms)

CALL neueUhrzeit ;neue Uhrzeit berechnen

RETI ;Ende der Interrupt-Service-Routine




neueUhrzeit:

INC R1 ;erhöht den Zaehler
CJNE R1,#250d,weiter ;Wenn die Routine noch nicht 250 mal
aufgerufen wurden
;dann springe nach weiter, da nichts geschieht
MOV R1,#0d ;den Zaehler wieder auf Null
zurücksetzen


INC R2 ;Sekunden Einerstelle um Eins erhöhen
CJNE R2,#10d,weiter ;Entsteht dadurch kein Überlauf (9->10)
springe
;nach weiter
MOV R2,#0d ;Es gab einen Überlauf, dadurch muss die
Einerstelle
;zurückgesetzt werden


INC R3 ;Die Zehnerstelle der Sekunden muss um
Eins erhöht werden
CJNE R3,#6d,weiter ;Wenn die Zehnerstelle noch nicht 6
anzeigt springe
;nach weiter
MOV R3,#0d ;Es gab einen Überlauf, dadurch muss
die Zehnerstelle
;zurückgesetzt werden

INC R4 ;Die Minuten Einerstelle um Eins erhöhen
CJNE R4,#10d,weiter ;Entsteht dadurch kein Überlauf
(9->10) springe
;nach weiter
MOV R4,#0d ;Es gab einen Überlauf, dadurch muss
die Einerstelle
;zurückgesetzt werden

INC R5 ;Die Minuten Zehnerstelle um Eins erhöhen
CJNE R5,#6d,weiter ;Entsteht dadurch kein Überlauf (5->6)
springe
;nach weiter
MOV R2,#0d ;Es gab einen Überlauf, dadurch muessen
Register 2 bis 5
MOV R3,#0d ;zurückgesetzt werden. Da die Uhr nicht
mehr
MOV R4,#0d ;anzeigen kann
MOV R5,#0d

weiter: RET ;Ruecksprung aus dem Unterpogramm


ausgabe: INC R0 ;erhöht die Anzeigennummer
CJNE R0,#04,rechts ;Ist der Wert ungleich 4 springe nach
rechts
MOV R0,#0 ;Setzt den Wert der Anzeigennummer zurück

rechts: CJNE R0,#0,mire ;Ist die Anzeigennummer ungleich 0 springe
nach mire
MOV A,R2 ;Schreibe den berechneten Uhrzeitwert in den
Akku
CALL BCD7Seg ;Ruft Werte für BCD7Seg Anzeige auf
MOV P1,A ;Gibt den im Akku gespeicherten Wert auf P1
aus
MOV P2,#00001110b ;gibt die Anzeigenposition auf P2 aus

mire: CJNE R0,#1,mili ;Ist die Anzeigennummer ungleich 1 springe
nach mili
MOV A,R3 ;Schreibe den berechneten Uhrzeitwert in den
Akku
CALL BCD7Seg ;Ruft Werte für BCD7Seg Anzeige auf
MOV P1,A ;Gibt den im Akku gespeicherten Wert auf P1
aus
MOV P2,#00001101b ;gibt die Anzeigenposition auf P2 aus

mili: CJNE R0,#2,links ;Ist die Anzeigennummer ungleich 2 springe
nach links
MOV A,R4 ;Schreibe den berechneten Uhrzeitwert in den
Akku
CALL BCD7Seg ;Ruft Werte für BCD7Seg Anzeige auf
MOV P1,A ;Gibt den im Akku gespeicherten Wert auf P1
aus
MOV P2,#00001011b ;gibt die Anzeigenposition auf P2 aus

links: CJNE R0,#3,m1 ;Ist die Anzeigennummer ungleich 3 springe
nach m1
MOV A,R5 ;Schreibe den berechneten Uhrzeitwert in den
Akku
CALL BCD7Seg ;Ruft Werte für BCD7Seg Anzeige auf
MOV P1,A ;Gibt den im Akku gespeicherten Wert auf P1
aus
MOV P2,#00000111b ;gibt die Anzeigenposition auf P2 aus

m1: RET ;Rücksprung aus dem Unterprogramm


; Wandelt vom BCD-Code in den 7-Segment-Code
BCD7Seg: INC A
MOVC A,@A+PC
RET
DB 3Fh, 06h, 5Bh, 4Fh, 66h, 6Dh, 7Dh, 07h, 7Fh, 6Fh




END


DANKE schon mal im vorraus
 
AW: Stoppuhr mit Assembler

Hallo aqtechnik,

ich habe erst mal deinen Code in eine vernüftige Form gebracht. Ist vielleicht leichter zu lesen.

Code:
[COLOR="Blue"]
	$include (reg52.inc)


	Starttaster bit P0.0
	Stopptaster bit P0.1
	Resettaster bit P0.2
	Merkertaster bit P0.3
	Abruftaster bit P0.4


	org 0000h
	LJMP start
	
	org 000Bh
	LJMP isrTimer0				//Einsprungadresse Interrupt-Serviceroutine für Timer 0



	org 0100h
start: 
	CALL initRegister 			//Register initialisieren
	CALL initTimer0 			//Interrupt Timer initialisieren

loop: 
	CALL ausgabe				//berechnete Werte ausgeben
	JB Starttaster, Weiter_bei_Stop 	//Abfrage des Starttasters
	SETB ET0				//Freigabe Timer 0

Weiter_bei_Stop: 
	JB Stopptaster, Weiter_bei_Merker	//Abfrage des Stopptasters
	CLR ET0					//Zuruecksetzen des Timers

Weiter_bei_Merker: 
	JB Merkertaster, Weiter_bei_Abruf 	//Abfrage des Merkertasters
	MOV 061h,R0 				//Schreibe die gestoppten Werte
	MOV 062h,R1				//an Stellen im Speicher
	MOV 063h,R2
	MOV 064h,R3
	MOV 065h,R4
	MOV 066h,R5

Weiter_bei_Abruf: 
	JB Abruftaster,Weiter_bei_Reset		//Abfrage Abfragetaster
	MOV R0,061h				//gespeicherte Werte den
	MOV R1,062h				//Registern zuweisen
	MOV R2,063h
	MOV R3,064h
	MOV R4,065h
	MOV R5,066h
	CALL ausgabe				//gespeicherte Werte ausgeben

Weiter_bei_Reset: 
	JB Resettaster, Weiter_bei_nichts	//Abfrage Resettaster
	CALL initRegister			//Register zuruecksetzen

Weiter_bei_nichts: 
	LJMP loop				//Endlosschleife



initRegister:
	MOV R0,#0				//bestimmt welche der Anzeigen aktiv ist
	MOV R1,#0				//Zähler von o bis 249 -->4ms*250 = 1 Sec
	MOV R2,#0				//für Segment rechts Sekunden Einer
	MOV R3,#0				//für Segment Mitte rechts Sekunden Zehner
	MOV R4,#0				//für Segment Mitte links Minuten Einer
	MOV R5,#0				//für Segment links Minuten Zehner
	RET


initTimer0:
	SETB EA					//Globale INT Freigabe. Bit im Reg IE
	MOV TMOD,#00000001b			//Timer0 konfiguieren, Modus1: 16Bit-Zaehler
	MOV TL0,#060h				//Timer0 vorladen
	MOV TH0,#0F0h				//65536 - 4000 = 61536 = F060h (4ms)
	SETB TR0 				//Start Timer0
	RET					//Ruecksprung aus dem Unterprogramm


isrTimer0:					//Interrupt-Service-Routine für Timer0
	MOV TL0,#060h				//Timer0 erneut vorladen
	MOV TH0,#0F0h				//65536 - 4000 = 61536 = F060h (4ms)
	CALL neueUhrzeit			//neue Uhrzeit berechnen
	RETI					//Ende der Interrupt-Service-Routine


neueUhrzeit:
	INC R1					//erhöht den Zaehler
	CJNE R1,#250d,weiter			//Wenn die Routine noch nicht 250 mal aufgerufen wurden dann springe nach weiter, da nichts geschieht
	MOV R1,#0d				//den Zaehler wieder auf Null zurücksetzen
	INC R2					//Sekunden Einerstelle um Eins erhöhen
	CJNE R2,#10d,weiter			//Entsteht dadurch kein Überlauf (9->10) springe nach weiter
	MOV R2,#0d				//Es gab einen Überlauf, dadurch muss die Einerstelle zurückgesetzt werden
	INC R3					//Die Zehnerstelle der Sekunden muss um Eins erhöht werden
	CJNE R3,#6d,weiter			//Wenn die Zehnerstelle noch nicht 6 anzeigt springe nach weiter
	MOV R3,#0d				//Es gab einen Überlauf, dadurch muss die Zehnerstelle zurückgesetzt werden
	INC R4					//Die Minuten Einerstelle um Eins erhöhen
	CJNE R4,#10d,weiter			//Entsteht dadurch kein Überlauf (9->10) springe nach weiter
	MOV R4,#0d				//Es gab einen Überlauf, dadurch muss die Einerstelle zurückgesetzt werden
	INC R5					//Die Minuten Zehnerstelle um Eins erhöhen
	CJNE R5,#6d,weiter			//Entsteht dadurch kein Überlauf (5->6) springe nach weiter
	MOV R2,#0d				//Es gab einen Überlauf, dadurch muessen Register 2 bis 5
	MOV R3,#0d				//zurückgesetzt werden. Da die Uhr nicht mehr
	MOV R4,#0d				//anzeigen kann
	MOV R5,#0d


weiter:
	RET					//Ruecksprung aus dem Unterpogramm


ausgabe: 
	INC R0					//erhöht die Anzeigennummer
	CJNE R0,#04,rechts			//Ist der Wert ungleich 4 springe nach rechts
	MOV R0,#0				//Setzt den Wert der Anzeigennummer zurück


rechts: 
	CJNE R0,#0,mire 			//Ist die Anzeigennummer ungleich 0 springe nach mire
	MOV A,R2				//Schreibe den berechneten Uhrzeitwert in den Akku
	CALL BCD7Seg				//Ruft Werte für BCD7Seg Anzeige auf
	MOV P1,A				//Gibt den im Akku gespeicherten Wert auf P1 aus
	MOV P2,#00001110b			//gibt die Anzeigenposition auf P2 aus


mire: 
	CJNE R0,#1,mili				//Ist die Anzeigennummer ungleich 1 springe nach mili
	MOV A,R3				//Schreibe den berechneten Uhrzeitwert in den Akku
	CALL BCD7Seg				//Ruft Werte für BCD7Seg Anzeige auf
	MOV P1,A				//Gibt den im Akku gespeicherten Wert auf P1 aus
	MOV P2,#00001101b			//gibt die Anzeigenposition auf P2 aus


mili: 
	CJNE R0,#2,links			//Ist die Anzeigennummer ungleich 2 springe nach links
	MOV A,R4				//Schreibe den berechneten Uhrzeitwert in den Akku
	CALL BCD7Seg				//Ruft Werte für BCD7Seg Anzeige auf
	MOV P1,A				//Gibt den im Akku gespeicherten Wert auf P1 aus
	MOV P2,#00001011b			//gibt die Anzeigenposition auf P2 aus


links: 
	CJNE R0,#3,m1				//Ist die Anzeigennummer ungleich 3 springe nach m1
	MOV A,R5				//Schreibe den berechneten Uhrzeitwert in den Akku
	CALL BCD7Seg				//Ruft Werte für BCD7Seg Anzeige auf
	MOV P1,A				//Gibt den im Akku gespeicherten Wert auf P1 aus
	MOV P2,#00000111b			//gibt die Anzeigenposition auf P2 aus


m1: 
	RET					//Rücksprung aus dem Unterprogramm



BCD7Seg: 					//Wandelt vom BCD-Code in den 7-Segment-Code
	INC A
	MOVC A,@A+PC
	RET
	DB 3Fh, 06h, 5Bh, 4Fh, 66h, 6Dh, 7Dh, 07h, 7Fh, 6Fh
[/COLOR]
 
AW: Stoppuhr mit Assembler

Hi aqtechnik,

-hast du das Programm selbst geschrieben ? 8)

-welche Hardware hast du angeschlossen ?
(du schreibst LCD meinst aber wohl 7Segment-LED oder ?)

-wie ist die Hardware mit dem Prozessor verbunden ?
(welche Leitungen gehen an die Anzeigen)

-ist zwischen dem Prozessor und der Anzeige
noch ein anderes IC ?

-die Software sieht ok aus
(ganz am Ende werden die Zahlen 0...9 in ein 7Segment
LED-Format gewandelt...da ist A,B,C nicht dabei)

-ich kann also deine Fehlerbeschreibung nicht ganz nachvollziehen
(oder testest du es am Debugger ?)


Gruss Uwe
 
AW: Stoppuhr mit Assembler

hallo liebe freunde

ich hab das mit keil geschrieben und es später erst mal mit 8051 win getestet... aber dort zeigt es mit A, B, .... an

ich habe das meinem lehrer erwähnt und er meinte ich soll das in dezimalzahlen umwandeln ich meine ich hab das schon aber weisst nicht mehr weiter...

bitte hilft mir
danke
 
Top