Archiv verlassen und diese Seite im Standarddesign anzeigen : Ram mit PIC18F4455 ansprechen
Foederation
14.05.2010, 11: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..
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, 08:52
Hallo und danke!
Bin gerade aus dem Urlaub wieder da und werde es im Laufe des Tages ausprobieren....
Foederation
25.05.2010, 09: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
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, 09: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>
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, 12: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, 12: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
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, 21: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
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.