PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Ram mit PIC18F4455 ansprechen



Foederation
14.05.2010, 10:20
Hallo zusammen,
ich möchte den Ramspeicher mit o.g. PIC ansprechen. Ich möchte aber anders als im Datenblatt beschrieben eine indirekte Adressierung mit Variablen, die die Adresse beinhalten, durchführen. Nur klappt das leider nicht. Ich habe unter anderem versucht, mit
lfsr 0,0x800
movf SpeicherZähler,0
Addwf FSR0,1
.. die 12- Adresse mit der 8 Bit Adresse, die im WREG steht zu addieren und in die 12-Bit Adresse zu speichern. Ohne Erfolg!!??
Kann mir jemand weiterhelfen?
Gruss..

Siro
14.05.2010, 16:38
Ich bin mir nicht ganz sicher, ob ich dein Problem richtig verstanden habe,
aber ich vermute schon...

Die folgende Variable soll eine beliebige Adresse festhalten, die später auf deine Ramstelle zeigen soll. Ist also ein 16 Bit Variable welche später deine 12 Bit Adresse auf eine RAM Speicherstelle beinhalten soll. Ich lege sie einfach mal bei Adresse 0x0100 Low Byte und 0x0101 High Byte ab:
var_Address_Low EQU 0x0100
var_Address_High EQU 0x0101

; nun müssen wir erstmal festlegen worauf die Variable zeigen soll.
; var_Address soll zum Beispiel auf die Speicherstelle 0x0300 zeigen

movlw LOW 0x0300
movff WREG,var_Address_Low
movlw HIGH 0x0300
movff WREG,var_Address_High

; das FSR Register bekommt nun die Adresse worauf die Variable zeigt
movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H


; nun wird ein Wert aus dem RAM geladen, danach wird das FSR0 Register automatisch um eins erhöht
movf POSTINC0,W

; irgend was damit machen
movf POSTINC0,W ; jetzt wird das nächste Byte aus dem RAM geladen
; zudem wird das FSR0 Register um
; irgend was damit machen

Folgenden Code kannst Du NICHT benutzen
LFSR FSR0,var_Address_Low
movf POSTINC0,W
; hier wird FSR0 mit der Adresse von var_Address_Low geladen und nicht mit dem Wert wo die Variable hinzeigt


Ich hoffe ich konnte Dir etwas weiterhelfen.
mfg. Siro

Foederation
25.05.2010, 07:52
Hallo und danke!
Bin gerade aus dem Urlaub wieder da und werde es im Laufe des Tages ausprobieren....

Foederation
25.05.2010, 08:12
.... und das beschreiben des RAM-Speichers würde nach der Adressierung doch mit z.B.
movlw D'3'
movwf INDF0
funktionieren müssen oder??
Also ich habe folgendes probiert um die Adresse 900 mit 9 zu beschreiben und 800 mit 8:
movlw D'0'
movwf var_Address_Low
movlw D'8'
movwf var_Address_High

movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H
movlw D'8'
movwf POSTINC0;INDF0

movlw D'9'
movwf var_Address_High

movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H
movlw D'9'
movwf POSTINC0;INDF0


;auslesen:
movlw D'0'
movwf var_Address_Low
movlw D'8'
movwf var_Address_High

movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H


movf POSTINC0,W
movwf Zeichen
call SendeZeichen
call WarteLänger

movlw D'0'
movwf var_Address_Low
movlw D'9'
movwf var_Address_High

movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H


movf POSTINC0,W
movwf Zeichen
call SendeZeichen
call WarteLänger

und es funktioniert nicht !
Ich erhalte 2x die 9 zurück

Siro
26.05.2010, 13:41
Hallo,
ich hoffe doch der Urlaub war okay.
Ja, das kann so noch nicht funktionieren aus mehreren Gründen.

1) Der PIC18F4455 hat ab Adresse 0x800 gar keinen RAM mehr, er besitzt nur 2048 Bytes und damit endet der RAM bei 0x07FF.
Siehe Datenblatt Seite 60

2) Der Ram ist unterteilt in verschiedene Blöcke. Um entsprechend darauf zuzugreifen benötigt man ein sogenanntes BANKSELECT.
Zuständig ist dafür das Register BSR
Solange Du mit MOVFF arbeitest, brauchst Du Dir keine Gedanken um das Bankselect machen. Sobald aber MOVWF oder MOVF ins Spiel kommt, musst Du sicherstellen, daß auch die richtige Rambank aktiv ist.

ich hab mal deinen Code abgeändert und ausprobiert. So geht es dann:



#include P18F4455.inc

org 0
goto main


var_Address_Low EQU 0x0100
var_Address_High EQU 0x0101

Zeichen EQU 0x102

main:
; ich schreibe in diesem Beispiel an die Adresse 0x0600 eine 6
; und an die Adresse 0x0700 eine 7

BANKSEL var_Address_Low ; so kannst Du dafür sorgen, daß MPLAB (der Assembler) automatisch die richtige Bank auswählt
movlw D'0'
movwf var_Address_Low
movlw D'6'
movwf var_Address_High

; hier brauchen wir kein Bankselect wegen dem MOVFF
movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H
movlw D'6'
movwf POSTINC0;INDF0

; hier setze ich z.B die BANK mal direkt mit dem BSR Register,
; eigentlich brauche ich es nicht mehr, da die Bank immer noch richtig steht
; nur zur Verdeutlichung...
bsf BSR,0 ; BANK 1 Speicherbereich 100..1FF auswählen
movlw D'7'
movwf var_Address_High

movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H
movlw D'7'
movwf POSTINC0;INDF0

;auslesen:
movlw D'0'
movwf var_Address_Low
movlw D'6'
movwf var_Address_High

movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H


movf POSTINC0,W
movwf Zeichen
; call SendeZeichen
; call WarteLänger

movlw D'0'
movwf var_Address_Low
movlw D'7'
movwf var_Address_High

movff var_Address_Low,FSR0L
movff var_Address_High,FSR0H


movf POSTINC0,W
movwf Zeichen
; call SendeZeichen
; call WarteLänger

end

ich hoffe, ich konnte Dir damit helfen.
Siro

Foederation
28.05.2010, 08:30
ich habe es jetzt so gelöst:


Speichern
;speichern: // Bank 1-6: 1=Position1LowIst;2=Position1HighIst;3=Position2Lo wIst;4=Position2HighIst;5=MessWertLow;6=MessWertHi gh

movlw D'1'
movff WREG,FSR0H
movff SpeicherZähler, FSR0L
movff Position1LowIst,INDF0

movlw D'2'
movff WREG,FSR0H
movff Position1HighIst,INDF0


movlw D'3'
movff WREG,FSR0H
movff Position2LowIst,INDF0

movlw D'4'
movff WREG,FSR0H
movff Position2HighIst,INDF0

movlw D'5'
movff WREG,FSR0H
movff MessWertLow,INDF0

movlw D'6'
movff WREG,FSR0H
movff MessWertHigh,INDF0

return
;;************************************************ **************
SpeicherAuslesen
;Istpositionen retten:
movff Position1LowIst,Position1LowIstKopie
movff Position1HighIst,Position1HighIstKopie
movff Position2LowIst,Position2LowIstKopie
movff Position2HighIst,Position2HighIstKopie


SpeicherAuslesenLoop

movlw D'1'
movff WREG,FSR0H
movff SpeicherZähler, FSR0L
movff INDF0,Position1LowIst

movlw D'2'
movff WREG,FSR0H
movff INDF0,Position1HighIst

movlw D'3'
movff WREG,FSR0H
movff INDF0,Position2LowIst

movlw D'4'
movff WREG,FSR0H
movff INDF0,Position2HighIst

movlw D'5'
movff WREG,FSR0H
movff INDF0,MessWertLow

movlw D'6'
movff WREG,FSR0H
movff INDF0,MessWertHigh

call Sende6BytePositionsUndMesswerte

decf SpeicherZähler,1
movlw D'0'
CPFSEQ SpeicherZähler
goto SpeicherAuslesenLoop

clrf SpeicherZähler

;Ab hier ist der Speicher ausgelesen:
;aktuellen Ist-Wert zurücklesen:
movff Position1LowIstKopie,Position1LowIst
movff Position1HighIstKopie,Position1HighIst
movff Position2LowIstKopie,Position2LowIst
movff Position2HighIstKopie,Position2HighIst
;call ADWandlung
;call Sende6BytePositionsUndMesswerte ;letzte Istposition dem PC mitteilen
return


Ich habe zwar noch einen scheinbar sporadischen Fehler bei der Messwertaufnahme, der sich so äußert, dass ein Positionswert mal nicht stimmt, aber dass wird wohl an etwas anderem liegen....

Vielen Dank für Deine Hilfe!!! =D>

Siro
28.05.2010, 20:33
Hallo nochmal,
das sieht ja etwas merkwürdig aus, aber wenns dann geht okay.
Kannst Du mal etwas genauer erklären was Du machen möchtest.
Sieht aus als wenn Du eine Tabelle von Messwerten irgendwo ablegen willst und diese dann später zum PC senden willst.
Fragst Du mehrere ADU Kanäle ab. Ich blick da nicht ganz durch.
Was sind denn die Position1LowIst und Position1HighIst und
Position2LowIst und Position2HighIst.
Ich denke mal das sollen zwei 16 Bit Variablen sein.
Du benutzt anscheinend FSR0L als index um innerhalb einer RAM Bank zuzugreifen. Kannst damit also 256 Werte adressieren.
Während Du mit FSR0H die Bank auswählst. Dagegen gibt es eigentlich auch nichts zu sagen, nur etwas ungewohnt. Ich denke mal das geht alles etwas eleganter, wenn Du mir dein Problem genauer schilderst, werd ich Dir gern weiter helfen. Das Wochenende ist noch lang :-)

mfg. Siro

Foederation
29.05.2010, 11:15
Also...
Ich möchte mit einem XY-Schlitten der mit Schrittmotoren ausgestattet ist Messwerte aufnehmen. Die Positionsdaten müssen also den Messdaten zugeordnet sein. Die Positionsdaten setzen sich aus High/Low werten zusammen. Also für 2 Schrittmotoren werden 4 Byte Sollpositionsdaten zum Pic übertragen, die er anfahren soll. Der Rasterwert wurde dem Pic vorher durch den PC(Anwendersoftware die ich in VB6 schreibe) mitgeteilt. Es wird also ein vordefiniertes zweidimensionaltes Feld gerastert und abgetastet. Anfangs hatte ich die Positionsdaten und Messwerte (auch 2Byte) mit jedem Schrittmotorschritt per rs232 übertragen, was das ganze langsam werden lies... . Nun nutze ich 6x 256Byte für die 4 Positionsdaten und 2 Messdaten. Das geht nun deutlich schneller. Bei der feinsten Abrasterung (12µm pro Schritt) dauert es natürlich etwas länger.
Aber dank Dir klappt es ja nun mit der Zwischenspeicherung.
Ich hatte das ganze schonmal mit dem 16F876-20 gemacht, der war aber bis an seine Grenzen ausgelastet. Ich musste sogar den Messkanal andauernd umschalten.. - ich hatte einfach nicht genügend Ports....
Den PIC18F.. programmiere ich zu ersten Mal. Eigendlich müsste ich mich bei solchen recht grossen Programmen auf C -Compiler umgewöhnen aber ich komme im Moment noch nicht klar mit dem C-Compiler von CSS.
Hast Du damit Erfahrung?
MFG

Foederation
29.05.2010, 11:16
Also...
Ich möchte mit einem XY-Schlitten der mit Schrittmotoren ausgestattet ist Messwerte aufnehmen. Die Positionsdaten müssen also den Messdaten zugeordnet sein. Die Positionsdaten setzen sich aus High/Low werten zusammen. Also für 2 Schrittmotoren werden 4 Byte Sollpositionsdaten zum Pic übertragen, die er anfahren soll. Der Rasterwert wurde dem Pic vorher durch den PC(Anwendersoftware die ich in VB6 schreibe) mitgeteilt. Es wird also ein vordefiniertes zweidimensionaltes Feld gerastert und abgetastet. Anfangs hatte ich die Positionsdaten und Messwerte (auch 2Byte) mit jedem Schrittmotorschritt per rs232 übertragen, was das ganze langsam werden lies... . Nun nutze ich 6x 256Byte für die 4 Positionsdaten und 2 Messdaten. Das geht nun deutlich schneller. Bei der feinsten Abrasterung (12µm pro Schritt) dauert es natürlich etwas länger.
Aber dank Dir klappt es ja nun mit der Zwischenspeicherung.
Ich hatte das ganze schonmal mit dem 16F876-20 gemacht, der war aber bis an seine Grenzen ausgelastet. Ich musste sogar den Messkanal andauernd umschalten.. - ich hatte einfach nicht genügend Ports....
Den PIC18F.. programmiere ich zu ersten Mal. Eigendlich müsste ich mich bei solchen recht grossen Programmen auf C -Compiler umgewöhnen aber ich komme im Moment noch nicht klar mit dem C-Compiler von CSS.
Hast Du damit Erfahrung?
MFG

Siro
29.05.2010, 13:14
Vorab, ich benutze auch keinen C-Compiler, programmiere die PICs seit zig Jahren in Assembler.

Also wenn ich es richtig verstanden habe, dann sendet deine PC-Software eine Serie von X und Y Position an den PIC.
Also eine gerasterte Strecke. Diese wird zunächst im PIC in einer Tabelle gespeichert.
Der PIC soll nun mittels zweier Schrittmotoren die Positionen bzw. die Strecke abfahren und je einen Messwert zu jeder Position zum PC zurücksenden.
Trifft das in etwas dein Vorhaben ?

Da ist deine Idee mit der Aufteilung der Daten in den einzelnen RAM-Banken garnicht schlecht, gefällt mir sogar ganz gut.
So hast Du immer ein gleiches Indexregister FSR0L und die Tabelle wird über FSR0H gewählt.
Ehrlich gesagt, da würd ich auch garnichts dran ändern, das past gut zu deinem Problem.

Ich hatte nur die Idee, da Du im PIC18xx drei solcher Indexregister hast, könnte man die Adressen
separat über jeweils einen Satz der Indexregister ansprechen. Hab das mal eben so aufgeschrieben,
ist aber auch nicht viel effektiver.

Wir benutzen eine FSR-Registersatz für die X Position
den zweiten für die Y Position
und den dritten für die Messwerte

So kannst Du nun alle Adressen deiner 3 Tabellen in die FSR0 bis FSR2 Register laden.
Für den Messwertzähler benutze ich mal das Register TBLPTRL, das ist wahrscheinlich in deiner Software noch unbenutzt.

Wenn Du jetzt deine Daten an den PC senden willst, würde es im Prinzip so aussehen:



LFSR FSR0,0x100 ; Adresse X-Koordinaten
LFSR FSR1,0x300 ; Adresse Y-Koordinaten
LFSR FSR2,0x500 ; Adresse Messwerte

movl D'255' ; 256 Positionen und Messwerte sollen gesendet werden
movwf TBLPTRL ; ich benutze gerne dieses 8 Bit Register zum zählen

Sende_Schleife:
movf POSTINC0,W ; X Position Low Byte laden, x-index +1
call Sende_W_Register ;
movf POSTINC0,W ; X Position High Byte laden, x-index +1
call Sende_W_Register

movf POSTINC1,W ; Y Position Low Byte laden, Y-index +1
call Sende_W_Register
movf POSTINC1,W ; Y Position High Byte laden, Y-index +1
call Sende_W_Register

movf POSTINC2,W ; Messwert Low Byte laden, Messindex +1
call Sende_W_Register
movf POSTINC2,W ; Messwert High Byte laden, Messindex +1
call Sende_W_Register
decfsz TBLPTRL,F ; Zähler -1, scip if zero (überspringe nächste Zeile wenn 0 rauskommt)
goto Sende_Schleife ; Schleifen bis alle Messwerte gesendet wurden


;;;;;;;;;; mal zu Vergleich mit deiner Idee:


movl D'127' ; 127 Positionen und Messwerte sollen gesendet werden
movwf TBLPTRL ; ich benutze gerne dieses 8 Bit Register zum zählen

movlw 1 ; Ram Bank für Position X Low Byte wählen
movwf FSR0L ;

Sende_Schleife:

movf INDF0,W ; X Position Low Byte laden
call Sende_W_Register ;
incf FSR0H,F ; Ram Bank für Position X High Byte wählen
movf INDF0,W ; X Position High Byte laden
call Sende_W_Register ;
incf FSR0H,F ; Ram Bank für Position Y Low Byte wählen
movf INDF0,W ; Y Position Low Byte laden
call Sende_W_Register ;
incf FSR0H,F ; Ram Bank für Position Y High Byte wählen
movf INDF0,W ; Y Position High Byte laden
call Sende_W_Register ;
incf FSR0H,F ; Ram Bank für Messwert Low Byte wählen
movf INDF0,W ; Messwert Low Byte laden
call Sende_W_Register ;
incf FSR0H,F ; Ram Bank für Messwert High Byte wählen
movf POSINC0,W ; Messwert High Byte laden, !!! und gleich den Zähler eins hoch setzen
call Sende_W_Register ;

decfsz TBLPTRL,F ; Zähler -1, scip if zero (überspringe nächste Zeile wenn 0 rauskommt)
goto Sende_Schleife ; Schleifen bis alle Messwerte gesendet wurden


; FAZIT: eigentlich ist das eine gute Idee, wie Du es gelöst hast.
Ich denke mal die Hauptzeit geht eh in die Datenübertragung und nicht in der Code-Optimierung.
So wünsche ich Dir noch ein schönes Wochenende.
Siro

Foederation
30.05.2010, 20:12
Auch schönes Wochenende, gehabt zu haben..
also die Rasterwerte übertrage ich nicht alle zugleich.
Ich habe mit meiner Anwendersoftware mehrere Modi eingeplant. Einmal die Möglichkeit die Motoren direkt zu steuern (rechts/links, Voll/Halbschritt, Enable, Reset) dann die Möglichkeit auf dem Bildschirm in einem Fenster zu klicken, das dem möglichen Anfahrfeld entspricht und die Position wird angefahren und dann der "AbrastMode" in dem ich in der AnwenderSoftwareein ein Feld definiere. Dabei wird dem PIC nur mitgeteilt, dass er zwischenspeichern soll und die nächste Position(immer nur eine Zeile). Nach einer Zeile sendet der PIC dem PC dann zurück das er die Position erreicht hat. Daraufhin berechnet der PC die nächste Position also nächst Zeile. Der PIC zählt die Abrastschritte und je nach Abtastrate Speicherplatz werden die Positions-und Messdaten gespeichert und ggf. ausgelesen. Das heisst ich kann 256 Messwerte mit den Positionswerten speichern und muss dann erst auslesen. Ich habe im Moment ca. 2000 bis 10000 Messwerte die ich zum PC übertragen möchte. In der Weiterentwicklung wäre also vielleicht nochmal interessant, einen externen Speicher anzusprechen.... Aber erstmal bin ich zufrieden, wenn ich so damit arbeiten kann...
MfG