Hallo alle Zusammen,
erstmal vorweg, ich bin absoluter Anfänger was Assembler-Programmierung
angeht und dies ist mein 1. "Projekt" an dem ich Arbeite.
Ich habe hier einen auf dem 8052 basierenden Mirkocontroller (genauer
gesagt, dieses Teil:
[[http://eitidaten.fh-pforzheim.de/daten/labore/mclt/pdf/TeachDongle.pdf]])
Jedenfalls habe ich vor, dafür einen Countdown/Timer mit folgenden
Funktionen zu schreiben:
- Anzeige auf Display im HH:MM:SS format.
- Mit Taste1 soll die "zu bearbeitende" Cursor Position ausgewählt
werden können.
- Mit Taste2 soll der Wert festgelegt(um 1 erhöht) werden können
(Countdown-Zeit)
- Taste3 ist zum Starten/Stoppen gedacht.
- Wenn die Zeit bei 0 angelangt sollte am besten noch irgendein
Signal(Visuell) ausgegeben werden
Lange Rede kurzer Sinn, hier mal kurz das relevante aus meinem aktuellen
Code für meine unten folgende Frage:
1
;Hier steht meine Timer-Fkt, die im Sekundentakt die Sekunden bzw. ggf. ;Minuten/Stunden erhöht.
2
;Das meine Timer-Fkt momentan noch hochwärts zählt ist erstmal nicht ;relevant
; Sorgt für die Ausgabe & das die Courser Position 1. nach rechts springt
33
_LCD_OUT:
34
push Acc
35
mov DPTR,#pDispS
36
MOV A,#06h
37
movx @dptr,A
38
CALL _Delay_K ; 4.1 ms
39
pop Acc
40
mov DPTR,#pDispD
41
movx @dptr,A
42
CALL _Delay_L ; 10 ms
43
ret
44
;Hier kommt noch Code der lediglich für die Initialisierung des Displays ist.
/dies ist nur ein Code-Ausschnitt, der Komplette Code befindet sich im
Anhang./
Meine eigentlich Frage bezieht sich auf die Ausgabe. Und zwar soll ja
die Zeit wie oben genannt in diesem(HH:MM:SS) Format angezeigt werden.
Was aber bei aktuellen Code angezeigt wird ist lediglich "::". Ich habe
keine Idee, wie ich es hinbekomme meine Variablen (HOURS, MINUTES,
SECONDS) angezeigt zu bekommen.
Ich hoffe hier kann mir jemand weiterhelfen.
mfg
Pohl
Spess53 schrieb:> Was meinst du, welchen Wert der Akkumulator beim Aufruf vom _LCD_OUT> hat?
Aber auch das Einfügen des Funktionsaufrufs wird nicht weiterhelfen:
1
:
2
mov a, #HOURS
3
call _LCD_OUT ; Stunden ausgeben
4
mov a, #':'
5
call _LCD_OUT
6
:
Denn LCD_OUT gibt genau 1 Zeichen aus. Die Stunden, Minuten und Sekunden
haben aber je 2 Zeichen... :-o
Pohl schrieb:> wie ich es hinbekomme meine Variablen (HOURS, MINUTES,> SECONDS) angezeigt zu bekommen.
Es ist sehr ungünstig, hier die Stunden, Minuten und Sekunden von
0..23/59 zu zählen, denn anschliessend musst du diese zweistelligen
Dezimalzahlen in zwei einzelne Stellen für die Ausgabe umrechnen.
Überaus Einfach wird es, wenn du diese Variablen hast:
StdZehner
StdEiner
MinZehner
MinEiner
SekZehner
SekEiner
Dann sieht dein Code nämlich so aus:
1
:
2
mov a, #StdZehner
3
call _LCD_OUT
4
mov a, #StdEiner
5
call _LCD_OUT
6
mov a, #':'
7
call _LCD_OUT
8
:
Und: das ist eigentlich ein sehr einfacher Fehler. Da könnte man mit ein
wenig Nachdenken (Frage: wie kommt ein Zeichen aufs Display?)
tatsächlich selber draufkommen...
HI
>Dann sieht dein Code nämlich so aus:>:>mov a, #StdZehner>call _LCD_OUT>mov a, #StdEiner>call _LCD_OUT>mov a, #':'>call _LCD_OUT>:
Funktioniert auch nur, wenn in ASCII gezählt wird. Oder vor der Ausgabe
noch mal 0x30 zu a addieren.
Es gib noch andere Fehler:
...
call _LCD_OUT
mov a,#SECONDS
;====== LCD-Ausgabe ===================================
; Sorgt für die Ausgabe & das die Courser Position 1. nach rechts
springt
_LCD_OUT:
push Acc
....
CALL _Delay_L ; 10 ms
ret
Das wird unweigerlich zum Absturz führen.
MfG Spess
Lothar Miller schrieb:> Es ist sehr ungünstig, hier die Stunden, Minuten und Sekunden von> 0..23/59 zu zählen, denn anschliessend musst du diese zweistelligen> Dezimalzahlen in zwei einzelne Stellen für die Ausgabe umrechnen.>> Überaus Einfach wird es, wenn du diese Variablen hast:> StdZehner> StdEiner> MinZehner> MinEiner> SekZehner> SekEiner
OK, das ist für einen Beginner erst mal übersichtlicher. Ansonsten
spricht doch nichts dagegen, eine zweistellige BCD-Zahl in einem Byte zu
lassen, denn es spart Speicher.
Dafür gibt es dann z.B. die Befehle PUSH ACC und SWAP ACC, ANL A, #0Fh,
um das Byte leicht in Halbbytes zu zerlegen. So jedenfalls mache ich es
meistens.
Wenn man sehr viele Zahlen in einem Programm hat, dann lohnt es sich
auch, eine Funktion BIN_TO_BCD einmalig im Code zu installieren, und
grundsätzlich nur mit Binärzahlen zu rechnen. Das ist dann noch
platzsparender.
Aber, Assembler bringt auf jeden Fall Spaß mit Dingen, die man in der
Hochsprache nicht mehr hat.
Erstmal herzlichen Dank für die Antworten.
>Denn LCD_OUT gibt genau 1 Zeichen aus. Die Stunden, Minuten und Sekunden>haben aber je 2 Zeichen...
Das klingt natürlich überaus logisch. Hab es gleichmal umgeschrieben.
Jetzt sieht das Ganze tatsächlich so aus:
1
:
2
mov a, #HZehner
3
call _LCD_OUT
4
mov a, #HEiner
5
call _LCD_OUT
6
mov a, #':'
7
call _LCD_OUT
8
mov a, #MZehner
9
call _LCD_OUT
10
:
Und meine Ausgabe so:
"|x:)x:<-x" (x ist hierbei leer/nichts)
Da ist ja offensichtlich immernoch der Wurm drin.
Ich als laie würden den Fehler in meinem Code für den Timer vermuten.
Allerdings sollte ja hierduch:
1
:
2
MOV HZehner,#0 ;Initialize to 0 HZehner
3
MOV HEiner,#0 ;Initialize to 0 HEiner
4
MOV MZehner,#0 ;Initialize to 0 MZehner
5
MOV MEiner,#0 ;Initialize to 0 MEiner
6
MOV SZehner,#0 ;Initialize to 0 SZehner
7
MOV SEiner,#0
8
:
wenigstens ganz zu beginn die Anzeige auf "00:00:00" stehen?!
Nun habe ich vermutet, dass diese Initialisierung fehlerhaft ist.
Wenn ich allerdings
1
:
2
MOV HEiner,#'0'
3
:
schreibe, hätte ich schätzungsweise die richtige Ausgabe, aber meinen
Wert ja nicht initializiert.
Wenn ich
1
:
2
MOV HEiner,#30h ; Meines Wissens nach ASCII 0
3
:
schreibe, verändert sich aber bei der Ausgabe auch nichts:
"|x:)x:<-x" (x ist hierbei leer/nichts)
@Pohl:
Du könntest es, wie von mir schon angedeutet, folgendermaßen machen,
wenn du zwei Ziffern in einem Byte hast, bspw. Minuten:
1
LCD_CHAR: ; ASCII ACC --> LCD-RAM-AREA
2
MOV @R0,A ; Adresse in R0
3
INC R0 ; Auto-Inkrement RAM-Zeiger
4
RET
5
6
LCD_BLANK:
7
MOV A,#' ' ; Sende ein Leerzeichen
8
SJMP LCD_CHAR
9
10
LCD_BYTE:
11
PUSH ACC ; sende BYTE hexadezimal,
12
SWAP A ; ACC wird zerstoert
13
ACALL LCD_NIBBLE
14
POP ACC
15
LCD_NIBBLE: ; LCD-Ausgabe 1 Zeichen 0..F
16
ANL A,#0x0F
17
ADD A,#246
18
JC LCD_HEXOUT
19
ADD A,#58
20
SJMP LCD_CHAR
21
LCD_HEXOUT:
22
ADD A,#65
23
SJMP LCD_CHAR
Die Funktion LCD_BYTE verarbeitet beide Halbbytes in einem Byte
nacheinander.
Die Funktion LCD_CHAR ist bei mir die Ausgabe ans Display, aber sie
schreibt erst mal nur in ein Spiegel-RAM. Woanders wird dann das gesamte
Display in einem Zug komplett geschrieben. Das hat den Hintergrund, daß
ich schlechte Erfahrungen damit habe, hier und da am Display mal ein
Zeichen zu schreiben. Seitlich betrachtet traten am Display
Flimmereffekte auf. Die verschwinden, wenn man immer nur das gesamte
Display in einem Rutsch beschreibt.
Das fand ich in einem Buch zu einem µC-Projekt von 1987 mal. Schon ein
Viertel Jahrhundert alt.
@Ferkes
vielen Dank für deine Mühe. Ich versteh zwar, was du mir sagen willst
und den Sinn dahinter..aber nicht sehr viel von dem Code und noch
weniger davon, wie ich das bei mir einbauen soll.
Nimm mir das bitte nicht übel, ist wie gesagt, mein 1. Projekt.
Ich wäre schonmal ziemlich froh, wenn ich nur meine einfach Varianten
zum funktionieren bekommen würde.
Pohl schrieb:> @Ferkes>> vielen Dank für deine Mühe. Ich versteh zwar, was du mir sagen willst> und den Sinn dahinter..aber nicht sehr viel von dem Code und noch> weniger davon, wie ich das bei mir einbauen soll.
Der ist doch nun wirklich total simpel, übersichtlicher gehts kaum noch.
Notfalls nimm dir ein Blatt Papier, ein Stapel Druckerpapier kostet ja
heute nix, und simuliere einen Programmteil schrittweise auf Papier. So
lernte ich das in EDV im Studium, Objekt war der olle 8085.
Man trägt oben in Spalten die betreffenden Register ein, deren Werte und
Änderungen man haben möchte, und trägt nach jeder Befehlszeile die neuen
Werte der Register in der darunter liegenden Zeile ein. Handsimulation,
wenn man keinen echten Simulator auf dem PC hat. Es ist ein wenig
Schreibarbeit, aber das ist zum Erfolg schon nötig.
Kürzlich simulierte ich einen selbst entworfenen Bubble-Sort-Algorithmus
noch so, da waren 5 Blatt Papier weg. Als ich ihn dann ins Programm
einbaute, lief er prompt, wie erwünscht.
Man kommt dann leicht auch so Dingen auf die Spur, die ich oben sah.
Z.B. als der Akkumulator überschrieben wurde. Da bekommt man aber auf
Dauer einen Blick für.
> Nimm mir das bitte nicht übel, ist wie gesagt, mein 1. Projekt.
Nein, tue ich nicht. Ich nehme nur selten was übel, da muß man schon
richtige Beleidigungen versuchen. So weit wie du jetzt war ich etwa
1992, also vor 20 Jahren.
> Ich wäre schonmal ziemlich froh, wenn ich nur meine einfach Varianten> zum funktionieren bekommen würde.
Das kommt noch, mit der Zeit und der Übung ergibt sich alles.
Bist du etwas weiter gekommen?
Aber wenn du Fragen hast, wir sind hier auf alle Fälle da.
Du mußt die Zahl in Digits zerlegen.
Dafür hat der 8051 den "DIV AB" Befehl (B = 10). Das Ergebnis ist der
Zener, der Rest der Einer.
Und dann #'0' dazu addieren, damit ASCII draus wird.
Du brauchst auch nicht extra die Zeichen weiter zu zählen, das kann das
LCD selber. Einfach im LCD-Init den Mode so setzen.
Du bist der erste, der diesen Mode nicht nutzt.
Peter
Peter Dannegger schrieb:> Du mußt die Zahl in Digits zerlegen.> Dafür hat der 8051 den "DIV AB" Befehl (B = 10). Das Ergebnis ist der> Zener, der Rest der Einer.> Und dann #'0' dazu addieren, damit ASCII draus wird.
Peter, das macht meine oben genannte Funktion LCD_BYTE. Sie macht aus
zwei Nibbles in einem Byte den ASCII-Wert.
Da sind zwar komische Zahlen drin, aber schau mal, was da wirklich
gemacht wird.
Wilhelm Ferkes schrieb:> Peter, das macht meine oben genannte Funktion LCD_BYTE. Sie macht aus> zwei Nibbles in einem Byte den ASCII-Wert.
Nö, die gibt Hex aus.
Aus 59 wird dann "3B".
Als Mensch möchte man es doch lieber dezimal, also "59".
Peter
Peter Dannegger schrieb:> Wilhelm Ferkes schrieb:>> Peter, das macht meine oben genannte Funktion LCD_BYTE. Sie macht aus>> zwei Nibbles in einem Byte den ASCII-Wert.>> Nö, die gibt Hex aus.> Aus 59 wird dann "3B".> Als Mensch möchte man es doch lieber dezimal, also "59".>>> Peter
Nein. Meine Funktion befindet sich augenblicklich in Programmen, und
arbeitet völlig richtig. Bei Hex-Zahlen gibt sie Hex A bis F aus, und
bei Dezimalzahlen 0 bis 9. Das ist doch nicht so schwer, oder?
Wilhelm Ferkes schrieb:> Meine Funktion befindet sich augenblicklich in Programmen, und> arbeitet völlig richtig. Bei Hex-Zahlen gibt sie Hex A bis F aus, und> bei Dezimalzahlen 0 bis 9.
Die Funktion kann nicht wissen, ob die Zahl hex oder dezimal ist, sie
gibt immer hex aus.
Dein Trick wird daher sein, Du zählst anders.
Also nicht mit "INC Zahl", sondern mit:
1
mov a, zahl
2
add a, #1
3
da a ; convert to packed-BCD addition
4
mov zahl, a
In der Praxis ist es effektiver, die CPU immer binär rechnen zu lassen
(ihr Lieblingsformat) und erst zur Ausgabe nach dezimal zu wandeln.
Mit "DIV AB" ist das auch einfacher und weniger Code.
Peter
Peter, nochmal:
Im Byte wird ein Nibble ausgeblendet, und der Rest in 4 Bits kann immer
nur eine Dezimalziffer oder Hexadezimalziffer sein.
Das kannst du jetzt mit mir rauf und runter diskutieren, da ergibt sich
nichts anderes.
Meine Software läuft damit zur höchsten Zufriedenheit.
Probier mein Codebeispiel aus. Auf Papier, oder Simulator.
Ich komm gerade nicht richtig weiter. Arbeite irgendwie an zwei
Baustellen gleichzeitig und an keiner richtig.
Einmal die "einfache" Variante mit HZehner, HEiner, MZehner(...).
und dann noch die "bessere" Variante mit nur jeweils einer Variablen.
Mir persönlich ist die "einfache" Variante lieber, da ich bei ihr
wenigstens mit gutem Gewissen behaupten kann, dass ich einigermaßen
weiß, was ich tue ;)
Mehr hilfe bekomme ich hier aber für die "bessere" Version.
Jetzt nochmal kurz, damit ich weiß, dass nicht beide Baustellen an der
falschen Stelle sind:
djnz TICKS,EXIT_RTC ;Decrement TICKS, if not yet zero we ;exit immediately
10
MOV TICKS,#30 ;Reset the ticks variable
11
INC SECONDS ;Increment the second varaiable
12
MOV A,SECONDS ;Move the seconds variable into the ;accumulator
13
CJNE A,#60,EXIT_RTC ;If we haven't counted 60 seconds, we're done.
14
MOV SECONDS,#0 ;Reset the seconds varaible
15
INC MINUTES ;Increment the number of minutes
16
MOV A,MINUTES ;Move the minutes variable into the ;accumulator
17
CJNE A,#60,EXIT_RTC ;If we haven't counted 60 minutes, we're done
18
MOV MINUTES,#0 ;Reset the minutes variable
19
INC HOURS ;Increment the hour variable
20
EXIT_RTC:
21
POP PSW ;Restore the PSW register
22
POP ACC ;Restore the accumulator
23
RETI ;Exit the interrupt routine
24
:
25
_Main:
26
mov TH1, #HIGH ClkCnt ;High-Teil Counter1
27
mov TL1, #LOW ClkCnt ;Low -Teil Counter1
28
mov TMOD,#10h ;Konfiguration Timer1 als 16bit Counter
29
setb TR1 ;Starte Timer 1
30
MOV HOURS,#00 ;Initialize to 0 hours
31
MOV MINUTES,#00 ;Initialize to 0 minutes
32
MOV SECONDS,#00 ;Initialize to 0 seconds
33
MOV TICKS,#30 ;Initialize countdown tick counter to 30
34
setb ET1 ;Erlaube Timer 1 Interrupt
35
setb EA ;Erlaube global Interrupts
36
:
Dieser Teil sollte ja ordnungsgemäß funktionieren und meine
Sekunden/Minuten/Stunden entsprechen erhöhen. Oder hab ich hier schon
einen Fehler eingebaut?!
Hi
>Oder hab ich hier schon einen Fehler eingebaut?!
8052 kenne ich eigentlich nicht wirklich. Aber was mir bei dem Code
auffällt:
push ACC <<
clr TR1
.....
EXIT_RTC:
POP PSW <<
POP ACC <<
RETI
So etwas bereitet im allgemeinen Probleme.
MfG Spess
Dann hast du im Akku 59 binär drin stehen. Also 0x3B. Sowas doofes aber
auch! Wenn schon, dann 059H, oder 0x59.
Meinetwegen auch 0xAF. Wenn ich AF auf dem Display ausgeben möchte.
Wilhelm Ferkes schrieb im Beitrag #2818950:
> Du kannst den Assembler nicht!
Nö, mache ich ja auch erst seit 1991.
Hier nochmal das komplette Testprogramm mit Deiner Routine:
1
mov r0, #40h
2
mov a, #59
3
call lcd_byte
4
jmp $
5
LCD_CHAR: ; ASCII ACC --> LCD-RAM-AREA
6
MOV @R0,A ; Adresse in R0
7
INC R0 ; Auto-Inkrement RAM-Zeiger
8
RET
9
LCD_BYTE:
10
PUSH ACC ; sende BYTE hexadezimal,
11
SWAP A ; ACC wird zerstoert
12
ACALL LCD_NIBBLE
13
POP ACC
14
LCD_NIBBLE: ; LCD-Ausgabe 1 Zeichen 0..F
15
ANL A,#0Fh
16
ADD A,#246
17
JC LCD_HEXOUT
18
ADD A,#58
19
SJMP LCD_CHAR
20
LCD_HEXOUT:
21
ADD A,#65
22
SJMP LCD_CHAR
23
end
Ergebnis: 40h: '3', 41h: 'B'
Und nun sage nicht, der Simulator lügt.
Hier dagegen ein funktionierendes Programm:
Wilhelm Ferkes schrieb:> Dann hast du im Akku 59 binär drin stehen. Also 0x3B. Sowas doofes aber> auch!
Ja was denn sonst?
"INC Sekunde" zählt nunmal von 0 bis 59 dezimal, also von 0x00 .. 0x3B
hex.
Das ist nicht doof, sondern ganz normales Zählen einer CPU.
Wilhelm Ferkes schrieb:> Wenn schon, dann 059H, oder 0x59.
Das ist wirklich doof.
Wenn Du anders zählst, dann sag es doch auch.
Dazu brauchst Du aber spezielle Zählroutinen, die ein anderes Format
benutzen. "INC" geht da nicht mehr.
.
Nächste Frage: Hoffe die kann mir einer vielleicht beantworten.
1
:
2
MOV HZehner,#30h ;2
3
MOV HEiner,#0
4
MOV MZehner,#0
5
MOV MEiner,#0
6
MOV SZehner,#0
7
MOV SEiner,#0
8
MOV TICKS,#20
9
SETB EA
10
SETB ET1
11
12
lcall _LCD_INI
13
lcall _CLEAR_LCD
14
mov a, #HZehner ;1
15
call _LCD_OUT ;3
16
:
17
_LCD_OUT:
18
push Acc
19
mov DPTR,#pDispS
20
MOV A,#06h
21
movx @dptr,A
22
CALL _Delay_K
23
pop Acc
24
mov DPTR,#pDispD
25
movx @dptr,A
26
CALL _Delay_L
27
ret
28
:
Wenn ich das ganze mit dem Debugger durchgehe habe ich bei Markierung 1
in a 0x01 stehen, anstatt 0x30. Wie kann das sein?
Das gleiche Ergebnis auchnoch, wenn ich bei Markierung 2 verschieden
Versionen ausprobiere (mov HZehner, #0x30 ...)
und bei Markierung 3 dann in a sogar 0x6c, was im übrigen auch dem "l"
entsrpicht, welches ich dann am Display angezeigt bekomme.
Ich verstehe einfach nicht, was da falsch läuft
Peter Dannegger schrieb:> "INC Sekunde" zählt nunmal von 0 bis 59 dezimal, also von 0x00 .. 0x3B>> hex.
Nein. Man muß bei einer Addition um 1 immer den Befehl "DA A" benutzen,
damit die Zahl BCD bleibt. Damit wird eine 9 zur Null, und Carry oder
Halfcarry sind gesetzt, machen dann einen BCD-gerechten Übertrag.
Peter, du kannst mit mir diskutieren bis zum Erbrechen. Mein Programm
mit Zahlenausgaben Ziffernausgaben dezimal oder hexadezimal läuft.
Einwandfrei. Wenn dir was nicht passt, mußt du es nach simulieren, aber
ich befürchte da nichts, weil meine Anwendung ja funktioniert.
Das Herumgebastle mit den BCD Zahlen wäre mir zu aufwendig. Ich würde
die 6 Stellen einfach ASCII '0' bis ASCII '9' zählen, dann erübrigt sich
jegliche Korrektur, weil schon die einzelnen Stellen den richtigen Wert
haben...
Lothar Miller schrieb:> Das Herumgebastle mit den BCD Zahlen wäre mir zu aufwendig. Ich würde> die 6 Stellen einfach ASCII '0' bis ASCII '9' zählen, dann erübrigt sich> jegliche Korrektur, weil schon die einzelnen Stellen den richtigen Wert> haben...
In größeren Assemlerprogrammen hat man eine Funktion installiert, die
skalierbar beliebige Bytelängen von BIN nach BCD wandelt, und umgekehrt.
Wo ist da das wirkliche Problem?
C rechnet intern auch nur binär, und der printf() wandelt BIN nach BCD.
Der printf() ist an Laufzeit auch nicht zu unterschätzen.
Lothar Miller schrieb:> Das Herumgebastle mit den BCD Zahlen wäre mir zu aufwendig.
Danke, so nämlich auch meine Sicht.
Allerdings nochmal zu meiner letzten Frage:
1
:
2
MOV HZehner,#30h
3
:
4
mov a, #HZehner
5
:
Jetzt sollte doch in "a" 0x30 stehen?!
Stadessen steht da aber 0x01.
Ich würde mich sehr freuen, wenn mir jemand hierauf eine einfache
Antwort geben könnte.
Wilhelm Ferkes schrieb:> Man muß bei einer Addition um 1 immer den Befehl "DA A" benutzen,> damit die Zahl BCD bleibt.
Hatte ich ja oben schon vermutet:
Beitrag "Re: Anfängerproblem Assembler 8052"
"Dein Trick wird daher sein, Du zählst anders."
Du bist darauf aber in keinster Weise eingegangen.
Im Gegenteil, Du hast felsenfest behauptet, Deine Routine mache genau
das gleiche, wie "DIV AB":
Beitrag "Re: Anfängerproblem Assembler 8052"
"Peter, das macht meine oben genannte Funktion LCD_BYTE."
Und das macht sie eben nicht.
Wilhelm Ferkes schrieb:> In größeren Assemlerprogrammen hat man eine Funktion installiert, die> skalierbar beliebige Bytelängen von BIN nach BCD wandelt
Macht aber auch schon in kleinen Programmen Sinn, statt extra
Zählroutinen zu entwickeln.
Insbesondere, da es für 8Bit-Werte besonders einfach geht.
Peter
Peter Dannegger schrieb:> "Peter, das macht meine oben genannte Funktion LCD_BYTE."> Und das macht sie eben nicht.
Mach es. Diese Funktion funktioniert bei mir seit Jahren. Du kannst sie
nicht weg diskutieren.
Seit mir nicht böse, aber könntet ihr eure ewige Diskussion vielleicht
privat weiterführen, ich habe jedesmal die Hoffnung, jemand Antwortet
auf meine Frage und dann sowas.
Pohl schrieb:> Seit mir nicht böse, aber könntet ihr eure ewige Diskussion vielleicht> privat weiterführen, ich habe jedesmal die Hoffnung, jemand Antwortet> auf meine Frage und dann sowas.
Sorry, Pohl, wenn mich jemand angreift, der keine Ahnung hat.
>> Jetzt sollte doch in "a" 0x30 stehen?!> Stadessen steht da aber 0x01.>> Ich würde mich sehr freuen, wenn mir jemand hierauf eine einfache> Antwort geben könnte.
Der Schlüssel liegt im #: das zweite Mal darf kein # da stehen...
Aber es wäre auch besser, HZehner nicht an Adresse 0x01 zu definieren...
Pohl schrieb:> Ich würde mich sehr freuen, wenn mir jemand hierauf eine einfache> Antwort geben könnte.
Der #-Operator sagt dem Assembler, es ist eine Zahl.
Ohne # ist es eine Adresse.
Aber warum probierst Du ständig was anderes?
Es bringt nichts, wenn man planlos rumprobiert.
Dein erster Code war doch schon ganz gut.
Jetzt nur noch "DIV AB" benutzen, um die Zahl in 2 Ziffern zu zerlegen
und fertig.
Siehe 2. Codebeispiel:
Beitrag "Re: Anfängerproblem Assembler 8052"
Und wenns läuft, dann noch das Auto-Increment des LCD einschalten und
das manuelle Increment streichen.
Nochn Tip:
Wenn Du was änderst, dann poste den neuen gesamten Code als Anhang.
Es kostet Dich nichts und wir können alle Änderungen sehen.
Immer nur ein Schnipselchen zu sehen, ist ziemlich blöde. Das macht
keinen Spaß.
Peter
In diesem abschnitt ist auch schon mein nächstes Problem
Die Ausgabe erfolgt jetzt fast richtig:
"00:00:0III" Warum er das aber bei letzten Stelle nicht richtig macht,
ist mir ein Rätsel...
Hat das was damit zu tun, dass er die Sekunden ja direkt hochzählt?(Die
Anzeige verändert sich aber auch nach mehreren Minuten nicht)
@Peter, diesmal hab ich auch den gesamten Code angehängt :-)
PS: langsam komm ich mir richtig blöd vor, weil ich hier ja so garnichts
auf die Reihe bekomme.
Hab kurz mal versucht, das ganze in C zu machen, allerdings gestalltet
sich da die Display-Initialisierung äusserst schwierig, da ich nur
lcd-Steuer & Datenregisteradresse und keinerlei Port angaben für die
Initialisierung des Displays habe(Warte da noch auf eine Mail) aber
egal, ich will das jetzt in Assembler durchziehen.
Sei doch nicht so schusselig.
Code läuft immer der Reihe nach ab.
Wenn Du was einfügst, wird es genau dort auch ausgeführt.
Unterfunktionen fügt man also nicht ein, sondern hängt sie an.
Pohl schrieb:> Hab kurz mal versucht, das ganze in C zu machen, allerdings gestalltet> sich da die Display-Initialisierung äusserst schwierig
Warum?
Du mußt die Adresse doch nur nach xdata casten, damit ein MOVX gemacht
wird:
Wilhelm Ferkes schrieb:> Mach es. Diese Funktion funktioniert bei mir seit Jahren. Du kannst sie> nicht weg diskutieren.
Du zählst ja auch im packed-BCD Format.
Wenn aber offensichtlich ist, daß der TO binär zählt, dann kannst Du ihm
doch keine Ausgaberoutine andrehen, die nur packed-BCD kann.
Und dann noch behaupten "Passt scho".
Wie wenn jemand ein Wort aus dem Englischen übersetzten will und Du
gibst im aber ein chinesisch Wörterbuch.
Er kann damit auch rein garnichts anfangen, um sein Problem zu lösen.
Da kannst Du noch so störrisch das Gegenteil behaupten.
Peter
@Peter
/call _LCD_OUT ; and after this call ???/
Hat das einen Sinn, eine LCD_REFRESH Funktion zu schreiben und hier
aufzurufen?
Muss ich so eine Funktion nicht sowieso früher oder später schreiben,
damit sich auf dem display überhaupt was tut, oder ändert sich das
automatisch, wenn die Variablen geändert werden?
Pohl schrieb:> @Peter> /call _LCD_OUT ; and after this call ???/
Damit ist gemeint, Du rufst sie erst auf und läufst danach in sie
hinein.
Das kann in Ausnahmefällen gewollt sein, aber definitiv nicht im Main.
Im Main gibt ein RET einen Stackunderflow, d.h. Du springst sonstwo hin.
Das Main darf nirgends nicht in ein RET hinein laufen!
Pohl schrieb:> oder ändert sich das> automatisch, wenn die Variablen geändert werden?
Nö, Magie gibt es beim Programmieren nicht.
Wenn Du in der Schule was ausgerechnet hast, dann erscheint das nicht
magisch auf der Tafel.
Du mußt aufstehen, hingehen und es ran schreiben.
Die Ausgabefunktion muß also jedesmal aufgerufen werden, wenn was neues
angezeigt werden soll.
Peter
Also ich komm mit dieser mircoController/Assembler Programmierung nicht
auf einen grünen Zweig. Es hat einfach noch immer nicht CLICK in meinem
Kopf gemacht.
Hab jetzt nochmal ein bisschen was verändert.
Was jetzt passiert.. die Anzeige kommt ordnungsgemäß im HH:MM:SS format
und startet direkt mit dem Hochzählen. Hierbei aber noch ein paar
Probleme.
Problem 1:
nach 00:00:09 folgt 00:00:11 // nach 00:00:19 folg 00:00:21 usw.
Problem 2:
Das ganze läuft etwas zu schnell, sprich nicht im Sekunden-Takt.
Schade, denn der Code-Teil, welcher für dies zuständig ist, ist der
Teil, bei dem ich mir am Sichersten war, dass er korrekt funktioniert.
Problem 3:
Das ganze läuft Unkonstant, dh. manchmal wird am ende noch eine
zusätzliche Ziffer angezeigt, manchmal startet es einfach von neu.
EDIT: Inzwischen läuft es konstant, schon bei 00:09:30 ohne Fehler
yipieeh :-)
Problemchen 4:
So wie es jetzt ist, sieht das ganze sehr unschön aus, da nach jeder
Sekunde die komplette Anzeige "neu aufgebaut" wird.
Ja, wo soll man da anfangen.
Ausgabe im Interrupt ganz böses Foul. Ausgaben immer im Main. Sonst hast
Du bei größeren Programmen mehrere LCD-Instanzen, d.h. ein
Textdurcheinander.
Am besten machst Du die Zeitzählung auch im Main. Der Interrupt setzt
nur ein Flag, daß eine Sekunde rum ist.
Ansonsten mußt Du alle Zeitbytes unter Interruptsperre zwischenspeichern
(atomar), damit sie konsistent sind und dann diese Kopie ausgeben.
Und was soll die Ausgabe nach Sekundeneiner zählen?
Da kriegst Du natürlich Mist angezeigt.
Entweder vor oder nach der Zeitberechnung, aber nicht mittendrin.
Und LCD-Datenblatt lesen, Ausgaben dauern nicht 10ms, sondern etwa 50µs.
Man muß die CPU doch nicht absichtlich ausbremsen.
Und schmeiß endlich das manuelle Increment raus. Du bist wirklich der
einzigste, der es benutzt.
Das Flackern kommt vom LCD-Clear, daher benutzt das in der Praxis
keiner. Man überschreibt einfach den alten Text mit dem neuen.
Das LCD-Init macht man natürlich auch nur einmal.
Peter
Guck mal auf Seite 65 des ADuC832-Datenblattes.
Der MC hat doch schon einen fix und fertigen TIME INTERVAL COUNTER
(TIC).
Das Ding enablen und die Register auslesen.
Einfacher gehts nun wirklich nicht.
Peter
Wenn du wüsstest, wie viele Stunden ich schon hier reingesteckt habe und
das dann mit meinem aktuellen code bzw können vergleichst, würdest du
mich zweifellos für völlig zurückgeblieben halten.
Das mit dem TIC habe ich bereits ziemlich zu beginn gesehen gehabt,
wusste damit aber nichts anzufangen.
Ich habe sogar ein beispiel-Programm für die TIC's des ADuC832,
allerdings weiß weder ich noch mein Compiler (keilµVision3) was damit
anzufangen.
Was dir nicht gelingt ist dem Ganzen eine Struktur zu geben. Eigentlich
brauchst du in "main" ja nur die Uhrzeit auszugeben. Vor der "main"
machst du die Initialisierung etc. und in der ISR wird die Uhrzeit in
deine Hilfsregister geschrieben.
Beispiel:
1
...DisplayInitialisieren
2
...Timersetzen
3
...etcetc.
4
5
_AUSGABE:[CursorandieAusgabePositiondesDisplays]
6
mova,HZehner
7
call_LCD_OUT
8
mova,HEiner
9
call_LCD_OUT
10
mova,#':'
11
call_LCD_OUT
12
mova,MZehner
13
call_LCD_OUT
14
mova,MEiner
15
call_LCD_OUT
16
mova,#':'
17
call_LCD_OUT
18
mova,SZehner
19
call_LCD_OUT
20
mova,SEiner
21
call_LCD_OUT
22
ljmp_AUSGABE;endlessloop
Ich hoffe du kommst dahinter. In Assembler geht alles der Reihe nach,
eigentlich ganz einfach.
@Bernd vielen Dank, das hilft mir zumindest vom Verständnis schonmal
sehr weiter und ich hab das auch direkt versucht im Code umzusetzen.
@Peter Hab meinen Code umgeschrieben und verwende jetzt den internen
TIC.
Jetzt stimmt auch das Zählen im SekundenTakt.
So, wie ging das jetzt nochmal mit dem, dass wenn ich z.B. MIN als
2-stellige Zahl hab diese dann ausgeben kann?
..wenn ich da nochmal nach oben in die alten Kommentar schaue..
werd ich wohl (z.B) MIN irgendwie mittels
1
div ab
in die Zehner und Einer aufspalten müssen.
Und/Oder eine neue LCD_OUT schreiben?!
Werd jetzt noch ein bisschen daran tüfteln, der Tag ist ja noch jung :-)
Pohl schrieb:> werd ich wohl (z.B) MIN irgendwie mittels div ab> in die Zehner und Einer aufspalten müssen.
Ja.
> Und/Oder eine neue LCD_OUT schreiben?!
Ja, und/oder diese Aufteilung dann dort reinpacken...
Oder (wie schon erwähnt) gleich im BCD-Format zählen. Dann musst du nur
noch die beiden Nibbles mittels swap und Bitoperationen (Ausmaskieren)
in die beiden Stellen (Zehner/Einer) zerlegen...
Lothar Miller schrieb:> Oder (wie schon erwähnt) gleich im BCD-Format zählen.
Ist beim TIC keine Option, das zählt binär.
Man kann nur auswählen, ob die Stunden bis 23 zählen oder bis 255.
Einfach mal im Befehlssatz die Beschreibung von "DIV AB" durchlesen,
dann fällt einem die Lösung wie Schuppen von den Augen.
Peter
Hier mal meine div ab - Funktion, die könnte so funktionieren?!
1
LCD_Hour:
2
mov r0, 40h
3
mov a, Hour
4
call DIV_AB
5
ljmp Ausgabe
6
DIV_AB:
7
mov b,#10
8
div ab
9
call LCD_ASCII
10
mov a,b
11
LCD_ASCII:
12
add a, #'0'
13
LCD_CHAR:
14
mov @r0,a
15
inc r0
16
ret
Frage 1: Die Funktion ist wie sie ist, doch eine Endlosschleife? sie
soll aber doch nur 2mal ausgeführt werden, oder täusche ich mich?!
Frage 2: Wie baue ich das ganze in mein LCD_OUT ein?
EDIT:
Habs hinbekommen. Funktioniert jetzt.
So, jetzt brauch ich noch die ganze Button-belegung,
1button: cursorposition
2button: aktuelle cursorposition um 1 erhöhen (Zeit einstellen)
3button: start/stop.
Für jegliche Tipps, bin ich sehr dankbar.
Achja, das ganze sollte dann natürlich noch rückwärts laufen...
Code ist jetzt wesentlich kürzer und besser kommentiert, hoffe damit
fällt das helfen vielleicht leichter.
Für meine Buttons hab ich folgendes geschrieben:
1
:
2
Ausgabe:
3
jb button1, next1 ; springe zu next1, wenn button1 nicht gedrückt
4
;noch keine funktion
5
next1:
6
jb button2, next2 ; springe zu next2, wenn button2 nicht gedrückt
7
mov a, hour ; schiebe hour in a
8
inc a ; erhöhe a um 1 (und damit auch hour?!)
9
;sollte sich später der cursorposition anpassen
10
next2:
11
jb button3, next3 ; springe zu next3, wenn button3 nicht gedrückt
12
ANL TIMECON, #0FDh ; Clear TIEN bit to stop the counter
13
ANL TIMECON, #0FEh ; Clear the TCEN bits to clear the registers(hour,min,sec)
14
mov hour, #0 ; hour auf 0 setzen
15
mov min,#0 ; min auf 0 setzen
16
mov sec,#0 ; sec auf 0 setzen
17
18
next3:
19
lcall _CP ;Cursor an die Ausgabe Position des Displays
20
mov a,Hour ; Ausgabe Stunden
21
:
Allerdings passiert garnichts, die uhr läuft immer einfach fröhlich
weiter.
(Sie ist nach einem reset am mircroController auch nicht resetet,
sondern läuft beim alten wert weiter)
Ich hoffe ihr könnt mir sagen, was ich falsch mache.
Pohl schrieb:> next1:> jb button2, next2 ; springe zu next2, wenn button2 nicht gedrückt> mov a, hour ; schiebe hour in a> inc a ; erhöhe a um 1 (und damit auch hour?!)> ;sollte sich später der cursorposition anpassen
Wenn du die Stunde an A um 1 erhöht hast, solltest du das dann aber auch
wieder zurück nach 'hour' verschieben. Ansonsten kannst du in A erhöhen
bis du schwarz wirst. 'hour' interessiert das nicht was du in A machst
und nur 'hour' ist letztendlich der Wert mit dem deine Uhr tatsächlich
operiert.
> > inc a ; erhöhe a um 1 (und damit auch hour?!)
Um auf den Kommentar einzugehen.
Warum soll das gemacht werden. Der Befehl lautet 'Increment A' und genau
das wird gemacht. A hat mit 'Hour' nichts zu tun. Das sind 2
verschiedene Dinge. Steht in hour der Zahlenwert 17, dann steht nach
einem
mav a, hour
ebenfalls der Zahlenwert 17. D.h. da ist einfach ein Wert von einem
Speicher in einen anderen Speicher umkopiert worden. Kopie! Nur
deswegen, weil du den Wert umkopiert hast, gibt es keine irgendwie
magische Verbindung zwischen A und Hour.
Du interpretierst immer noch zuviel in die Dinge hinein! Der µC macht
genau, und zwar 100% genau, das was der Befehl aussagt. Nicht mehr und
nicht weniger. In einem µC passiert nichts irgendwie 'magisch'.
jb button2, next2 ; springe zu next2, wenn button2 nicht gedrückt
2
mov a, hour ; schiebe hour in a
3
inc a ; erhöhe a um 1
4
mov hour, a ; schiebe a in hour
So sollte das dann also klappen?
Und zu den Interrupts, wie kann ich die denn für diese Zeit
deaktivieren?
STI / CLI lösen bei mir einen SYNTAX ERROR aus, gibt es sowas auch für
den 8051(bzw. 8052)?
Ich meine mich zu erinnern, daß man den TIC anhalten muß, um schreiben
zu dürfen.
Man muß auch nicht nach A laden und zurück, INC geht auch auf Adressen.
Peter
Peter Dannegger schrieb:> Ich meine mich zu erinnern, daß man den TIC anhalten muß, um schreiben> zu dürfen.
Gut, denn im fertigen Programm soll das schreiben ja auch nur im
"angehaltenen" Modus funktionieren.
Mal ne konkrete Frage:
1
Ausgabe:
2
jb button1, next1 ; springe zu next1, wenn button1 nicht gedrückt
3
lcall restart ; startet counter
Wenn ich das ganze so im Programm hab steht meine Anzeige Ordnungsgemäß
bei 00:00:00. Sie sollte dann aber anfangen zu laufen, wenn ich button1
drücke.
Da passiert aber nichts(auch nicht bei gedrückt halten).
Komischerweise Startet die Anzeige aber sofort wenn ich ich statt "jb"
"jnb" verwende:
1
Ausgabe:
2
jnb button1, next1 ; springe zu next1, wenn button1 nicht gedrückt
3
lcall restart ; startet counter
Mir ist klar, warum, dass so ist, aber mich interessiert, warum es dann
bei "jb" + Knopfdruck nicht funktioniert.
(Kompletter Quellcode im Anhang)
beheben lassen, komisch, denn clr buttonX stand ganz am Anfang im Code.
Jetzt versuche ich erstmal Button3 so zu belegen, dass beim
1x drücken, gestoppt wird, beim 2x drücken, angehalten.
Und am besten noch bei längeren drücken auf 0 gesetzt.
Für Tipps aller Art, wie ich das machen könnte, wäre ich sehr dankbar.
Achja, gibt es eine Möglichkeit, dass man einen Befehl nur ausführen
lässt, wenn man 2 Knöpfe gleichzeitig drückt?
Sowas in der Art wie:
1
jb button1, button3, next1 ; springe zu next 1, wenn button 1 und 3 nicht gedrückt sind
Wie gesagt, für Hilfe aller Art, die mir ewige Rumtüftelei ersparen, bin
ich sehr dankbar.
Es gibt schon gute Tastenlösungen, die sind allerdings in C geschrieben:
Beitrag "Universelle Tastenabfrage"
Ich sehe gerade im ersten Post, Du willst ja runter zählen, das kann der
TIC nicht.
Ist aber kein Problem, Du zieht vor dem Anzeigen die Zeit einfach von
23:59:59 ab.
Peter
Peter Dannegger schrieb:> Es gibt schon gute Tastenlösungen, die sind allerdings in C geschrieben:>> Beitrag "Universelle Tastenabfrage"
Vielen dank, allerdings ist das schon sehr komplex und ergibt für mich
gerade wenig Sinn. Werd morgen mal versuchen mich da reinzudenken.
Wenn jemand aber was vergleichbares in assembler hat, wäre das eine
riesen Hilfe für mich.
Hab meine Anforderungen jetzt (vorerst) etwas runtergeschraubt:
button1 erhöht die Stunden
button2 die Minuten
und button3 die Sekunden.
Jetzt muss ich nur noch durch langes oder doppeltes drücken von tasten
die Start-Funktion einbauen.
Peter Dannegger schrieb:> Ist aber kein Problem, Du zieht vor dem Anzeigen die Zeit einfach von> 23:59:59 ab.
Wie stelle ich das am besten an? denn,
1
:
2
Ausgabe:
3
lcall _CP ;Cursor an die Ausgabe Position des Displays
4
mov a,255
5
subb a,Hour ; Ausgabe Stunden
6
call LCD_HOUR
7
mov a,#':' ; ...
8
call _LCD_OUT
9
mov a, 59
10
subb a, MIN
11
call LCD_MIN
12
:
so funktioniert das ganze schonmal nicht, wenn nach einstellen einer
Zeit gestartet wird, resetet die Uhr auf 00:00:00 und beginnt dann wie
gewohnt hochzuzählen.
Ach und eine Sache noch:
Bei dem eingebauten TIC kann man ja laut datenblatt zwischen 255h und
24h umstellen. Wie genau aber stell ich denn auf 24h?
Alles was ich habe, ist das
MOV TIMECON, #03h ; initialise timecon to count in 1/128s
; -set TCEN to enable the time clock
; -set TIEN to enable the TIC
; -clear STI to allow automatic relaod
; of interval timeout
; -clear TFH to disable 24 hr counting
was aber genau das Gegenteil macht, sprich statt auf 24 auf 255 stellt.
Und das aus dem Datenblatt:
[[http://www.analog.com/static/imported-files/data_sheets/ADUC832.pdf]]
(tabelle S65)
BIT | Name | DISCRIPTION
[6] | TFH | Twenty-four hour select bit. Set by the user to enable the
h our counter to count from 0 to 23. Cleared by the user to
enable the hour counter to count from 0 to 255.
Womit ich aber leider auch nichts anfangen kann, da ich keine Ahnung
habe, wie ich das Bit setzte
An dieser Stelle möchte ich mich auch mal recht Herzlich bei euch allen
bedanken!
Ihr wart mir eine sehr große Hilfe! Ohne euch, wäre ich nie soweit
gekommen. Vielen Dank.
(Ein paar Fragen werd ich wohl noch Stelle, dann habt ihr aber bald ruhe
vor mir smile )
Gibt es einen Befehl, ähnlich cjne (Compare and Jump if not equal)
nur das verglichen wird, ob ein Operande größer bzw kleiner vom anderen
ist?
oder wäre es möglich den cjne befehl irgendwie so zu verwenden?
Frage:
ist es "einfacher", wie ich es bisher versuche, einen Knopf mit 2
Funktionen zu belegen(also langes und kurzes drücken zu unterscheiden)
oder
eine Funktion zu schreiben, die bei Knopfdruck weiterspringt (Hier von
Stunden zu Minuten zu Sekunden) und den aktuell ausgewählten wert, dann
mit einem 2. Knopf zu verändern?
Bitte helft mir weiter, mit Ideen, wie ich das machen könnte, oder am
besten beispielcode.
Ich zerbrech mir schon seit stunden den Kopf, hab beides ausprobiert,
bin aber zu keinem zufriedenstellenden Ergebnis gekommen.
Ich hab das ganze jetzt auf eine völlig andere Art gelöst.
Das ist aber ja auch egal.
Eine (hoffentlich) letzte Frage habe ich noch immer:
Pohl schrieb:> Bei dem eingebauten TIC kann man ja laut Datenblatt zwischen 255h und> 24h umstellen. Wie genau aber stell ich denn auf 24h?> Alles was ich habe, ist das>
1
> MOV TIMECON, #03h ; initialise timecon to count in 1/128s
2
> ; -set TCEN to enable the time clock
3
> ; -set TIEN to enable the TIC
4
> ; -clear STI to allow automatic relaod
5
> ; of interval timeout
6
> ; -clear TFH to disable 24 hr counting
7
>
> was aber genau das Gegenteil macht, sprich statt auf 24 auf 255 stellt.
Und die Informationen aus dem Datenblatt (Seite 65)
http://www.analog.com/static/imported-files/data_sheets/ADUC832.pdf
Der Befehl muss ja quasi dieser sein
MOV TIMECON, #XXX
nur mit den richtigen XXX.
Ich hoffe, das sich ein "Wissender" (smile) kurz die Mühe machen
könnte und mir die Richtigen XXX nennen kann. Oder zumindest kurz
erklärt, wie ich sie herausfinden kann.
Pohl schrieb:>> ; -clear TFH to disable 24 hr counting>> > was aber genau das Gegenteil macht, sprich statt auf 24 auf 255 stellt.
Nein.
Es macht ganz genau das, was im Kommentar steht.
Du machst den Eindruck, als ob Du sehr zerstreut bist.
Du gehst sehr planlos vor und das fällt Dir ständig auf die Füße.
Hast Du schonmal was anderes programmiert, außer 8051 Assembler?
Der Trick beim Programmieren ist, man schreibt kleine Module
(Funktionen) und wenn eins fertig ist, dann fast man es auch nicht mehr
an, sondern ruft es nur auf.
In Assembler muß man zu jedem Modul einen Header als Kommentar
schreiben. Also was geht in welchen Registern hinein, was macht sie und
was geht in welchen Registern hinaus, welche Register werden zerstört.
Module mitten im Programm und drumherum springen fördert in keinster
Weise den Durchblick. Am besten ganz nach hinten damit, hinter die
Mainloop.
Pohl schrieb:
>> clr button1>> jb button1, next1 ; springe zu next1, wenn button1 nicht gedrückt
Das ist schonmal ganz großer Mist.
Der Pin ist damit Ausgang low, da kann nichts mehr eingelesen werden
bzw. nur bei sehr hohem Kurzschlußstrom.
Lies Dir mal die Portbeschreibung durch.
Tasten müssen immer gegen GND schalten, dann fließt nur der Pullup-Strom
(50µA).
Peter
Was macht es denn dann?
Für mich steht da relativ eindeutig, dass das TFH-Bit auf 0 gesetzt wird
und somit der TIC auf 255h. Das gegenteil (TFH auf 1) würde den TIC doch
auf 24h setzten.
Was ist dann mein Denkfehler?
C, C++, ein bisschen LISP(das ist aber eine andere Geschichte)
Das Problem ist nicht, dass ich Planlos vorgehe, das mag vielleicht den
eindruck erwecken, da ich hier ständig meine Taktik ändere. Das liegt
aber daran, dass mein Plan A oft für mich einfach nicht zu realisieren
war, mangels (Grund)verständnis von Assembler.
Das durcheinander sehe ich ein, muss mich aber auch hier rechtfertigen,
dass das an dem vielen herumprobieren von mir liegt(wo wir wieder beim
Grundverständnis wären) Da der Code mit ~200Zeilen da relativ kurz ist,
habe ich als Programmierer keineswegs den überblick verloren.
Peter Dannegger schrieb:>>> clr button1>>> jb button1, next1 ; springe zu next1, wenn button1 nicht gedrückt>> Das ist schonmal ganz großer Mist.
So großer Mist ist das garnicht, bei diesem MicroController wird mit
clr button1 button1 auf Input gesetzt. Da bin ich mir sicher.
Ohne das clr spricht der button nicht mal an.
So jetzt wurde viel geredet, meine Frage steht allerdings noch immer im
Raum.
Ich will doch nur wissen mit welchen Befehl (/wie ich darauf komme in
einfachen Worten) ich das "TFH" Bit auf High setzten kann und somit die
24h aktiviere.
>> Das ist schonmal ganz großer Mist.> So großer Mist ist das garnicht, bei diesem MicroController wird mit> clr button1 button1 auf Input gesetzt. Da bin ich mir sicher.
Der Port 1 des AduC832 hat keine Ausgangstreiber, und laut Datenblatt
ist der Port für digitalen Input zu löschen, deine Aussage ist somit
korrekt.
Aber du darfst eins nicht vergessen: Peter kennt den 8052-Core zwar sehr
gut, aber er kann nicht unbedingt wissen, dass sich der AduC832 in
dieser Hinsicht anders verhält! Bei einem 100% 8052 kompatiblen Core
würde der von ihm beschriebene Effekt auftreten und das Ausgangslatch
auf low gehen.
Diese Abweichungen erschweren es zusätzlich, da Peter (wie ich anfangs
auch) von einem 100%-Core ausgeht.
Ralf
Ok.
Pohl schrieb:> Ich will doch nur wissen mit welchen Befehl (/wie ich darauf komme in> einfachen Worten) ich das "TFH" Bit auf High setzten kann und somit die> 24h aktiviere.
Woran liegt es, dass mir hier keiner eine Antwort geben kann?
Sind zu wenig Informationen gegeben? (ich hab aber auch nicht mehr)
Könnt das selbst ihr nicht beantworten?
Wollt ihr es nicht beantworten, weil das zu Zeitaufwändig wäre?
- dann würde ich mich freuen, wenn mir jemand in einfachen
Worten sagt, wie ich es selbst herausfinden kann?
Pohl schrieb:> Woran liegt es, dass mir hier keiner eine Antwort geben kann?
Wohl daran, daß keiner weiß, was Deine Schwierigkeit ist.
Ich vermute mal, die Zuordnung der Bitstelle zu einem Wert.
TFH ist Bit 6, also Wert 040h
1
ORL TIMECON, #040h
und schon ist es gesetzt.
Man kann auch schreiben:
1
ORL TIMECON, #1 shl 6
In C würde man schreiben:
1
TIMECON|=1<<6;
Die Kenntnis der Bitmanipulationen wird eigenlich bei jedem
Programmierer vorausgesetzt, daher sieht niemand ein Problem darin.
Peter