Hallo! Ich habe folgendes Problem, ich soll eine Monitorprogramm schreiben. Dafür muss ich die SFR auslesen können. Das soll durch Eingabe der SFR-Adresse erfolgen. Irgendwie bekomme ich da nicht hin. Hat jemand eine Idee? Assembler oder besser in C.
Häh? Das steht doch in jedem Datenblatt. Nimm Dir also das von Deinem Controller und los geht es. Wer zwingt Dich denn, so ein Programm zu schreiben?
Genau das steht nicht so nicht drin. Klar kann ich in Assembler folgendes machen: mov SBUF, SP oder mov SBUF, 0x81 Nur wenn die Sache variabel werden soll wird schwierig. Also angenommen ich will die SFR's von 0x81h bis 0xFEh ausgeben. Wie realisiert man das?
Eine Schleife und dann jeweils um eins erhöhen? Das Problem sehe ich immer noch nicht.
ganz einfach: du schreibst ein programm bei dem du die start und die endadresse eingeben musst. dann initialisierst du einen byte pointer mit der startadresse und lässt in einer schleife solange alle werte ausgeben bis der pointer auf die endadresse zeigt (mit auto increment natürlich ) mfg, Mathias
Die SFRs lassen sich nur direkt adressieren, d.h. Du brauchst für jede Adresse einen eigenen Befehl, z.B.:
1 | cjne r0, #80h, m80 |
2 | mov a, 80h |
3 | m81: |
4 | cjne r0, #81h, m82 |
5 | mov a, 81h |
6 | m82: |
7 | ... |
8 | cjne r0, 0FFh, mend |
9 | mov a, 0FFh |
10 | mend: |
Peter
Das sich jedes SFR nur über direkte Adressierung auslesen lässt, wage ich zu bezweifeln, zumal hier noch kein Ton über die verwendete Plattform gefallen ist. Vieleicht nochn kleiner Tipp: Es gibt SFRs, die nur WriteOnly sind bzw bei Lesezugriffe andere Werte ausgeben.
Also das Ganze muss auf einem MSC1211 von TI laufen (8051 kompatibler Kern). Meine neue Idee wäre eine Tabelle: . . mov DPTR, #sfread_tab movc A, @A+DPTR . . . .macro sfread ; Erg. in R0 mov A,@1 ret .endmacro sfread_tab: ;(>=128) sfread $80 ; P0 sfread $81 ; SP sfread $82 ; DPL sfread $83 ; DPH . . . Also zuerst einmal Akku erhöhen und abschließend Akku über UART senden. Habee ich nur noch nicht ausprobiert.
@Niels "Das sich jedes SFR nur über direkte Adressierung auslesen lässt, wage ich zu bezweifeln, zumal hier noch kein Ton über die verwendete Plattform gefallen ist." Nun, beim 8051 sind Deine Zweifel falsch, sonst hätte ich es ja nicht geschrieben. Und "SFR", "SBUF", "SP" legen einen 8051 nahe. Daher geht es eben nicht so wie Dirk schreibt bzw. er liest damit immer den indirekten SRAM. Peter
Von hinten durch die Brust ins Auge gehts doch. Voraussetzung: Ein RAM, der sowohl als Daten- als auch als Codespeicher geschaltet ist (mache ich der Bequemlichkeit halber eigentlich immer). Dann kann man den entsprechenden Programmcode ins RAM schreiben und entsprechend verändern. Ist zwar kein "sauberer" Programmierstil, geht aber.
Also ich habe erst einmal folgende Lösung in Assembler gefunden: MAIN_PROG: mov R0, #0x00 Erh: mov A, R0 mov DPTR, #Tabelle LCALL SFRREAD mov SBUF, A inc R0 inc R0 inc R0 sjmp Erh jmp MAIN_PROG SFRREAD: jmp @A+DPTR .segment tabelle, org $9A .macro ReadSFR mov A, @1 ret .endmacro Tabelle: ReadSFR 0x80 //Port 0 ReadSFR 0x81 //SP ReadSFR 0x82 ReadSFR 0x83 ReadSFR 0x84 Vielleicht finde ich noch eine kürzere Variante, die auch unter C zu realisieren ist.
@Dirk Daher geht es eben nicht so wie Dirk schreibt bzw. er liest damit immer den indirekten SRAM. @Thomas also ehe ich da noch nen Haufen Hardware ranpappe, schreibe ich doch lieber ein paar Zeilen Code. Mit einem Repeat-Macro ist das ruckzuck erledigt. Wem die 5 Byte pro SFR zuviel sind, man kanns auch auf 3 Byte ("mov a, sfr" + "ret") reduzieren und indiziert anspringen. Peter
@Dirk, jetzt sehe ich es erst, Du machst es schon so. Du hast bloß nen völlig anderen Assembler, deshalb habe ich es nicht erkannt. Ein Fehler ist aber doch noch drin: Wenn Du alle 128 SFRs lesen willst, dann ergibt 3* "inc R0" einen Überlauf. Dann mußt Du noch DPH erhöhen. Peter
Es gibt nur die Möglichkeit beim 8051 für jedes SFR einen Befehl zu schreiben. Der Ansatz von Dirk ist bestens. Nur noch die 16 Bit Korrektur, dann sollte das tun. @Thomas meinem Namensvetter: Die "von-Neumann" Umbauerei von 8051 geht nur bei externem Programmspeicher. Intern gibt das ein Problem und bei einem "universellen" Monitor sollte das auch dann funktionieren. Gruß THomas
So, hier mal, wie ich das mit dem Keil-Assembler machen würde:
1 | ; input: a = index (0 = sfr 80h ... 7fh = sfr 0FFh) |
2 | ; output: r7 |
3 | getsfr: |
4 | mov dptr, #sfrtab |
5 | mov b, #3 |
6 | mul ab |
7 | jnb ov, _gsf1 ; > 255 ? |
8 | inc dph ; + 256 |
9 | _gsf1: jmp @a+dptr |
10 | |
11 | sfrtab: |
12 | sfrnum set 80h |
13 | rept 128 |
14 | mov r7, sfrnum |
15 | ret |
16 | sfrnum set sfrnum + 1 |
17 | endm |
18 | |
19 | end |
Je nach Derivat sind natürlich nicht alle SFRs belegt, dann kommt meistens 0 oder FFh zurück. "mov a, acc" ist keine gültige Instruktion, deshalb habe ich R7 genommen. Peter
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.