Nabend,
ich habe auf meinem Tisch ein kleines Board für PIC-Controller, das u.a.
alle Portzustände über LED's anzeigt ( 5V = Led an, 0V = Led aus).
Testweise habe ich mal ein einfachen Binärzähler mit Warteschleife
laufen lassen. Dabei fiel mir auf, das die an Bit 7 angeschlossene LED
nie aufleuchtet.
Auch auf dem Scope war nix zu sehen. Led an Bit 7 blieb aus. Schaltete
man alle LED's in Software ein (ohne Zähler, sprich statisch) dann
leuchteten auch alle.
--> Kein Verbindungsfehler
Es musste also an der Software liegen.
Die "LED-Schreibroutine" sah dabei so aus, das PORTA ("Register") ins
Arbeitsregister geladen und in diesem inkrementiert wird.
Der Wert wird dann in alle anderen Register gespiegelt.
Kurz und präzise ausgedrückt sieht es so aus:
1
[ Init ]
2
3
movlb 0xFF
4
incf PORTA,w
5
movwf PORTA
6
movwf PORTB
7
movwf PORTC
8
movwf PORTD
9
[usw usf]
RA6 und RA7 werden für den Externen Quarz genutzt, daher tat sich die
Vermutung auf, dass diese Bits evtl. deaktiviert werden.
Tatsächlich hat es sich herausgestellt, das das Problem nicht auftritt,
wenn ich den Wert in PORTD inkrementiere und dann weiterspiegele.
Sprich: Wird der Externe Quarzoszillator genutzt, so lässt sich RA7
nicht schreiben, RA6 allerdings schon (!!!).
Nach Umschalten auf Internen RC-Oszillator lässt sich auch RA7
beschreiben.
Das die Ausgänge für RA6 und RA7 im Externen Oszillator Modus nicht
(digital) funktionieren ist klar.
Aber warum lässt sich das PORTA-"Register" nicht komplett beschreiben?
Und vor allem: Warum lässt sich RA6 beschreiben, aber RA7 nicht?
Wenn schon, dann müssten beide nicht funktionieren (IMO).
Mit freundlichen Grüßen
Danish Belal
Sorry, habs vergessen zu Erwähnen.
Board ist eine Eigenentwicklung.
PIC ist der PIC18F45K22 im 40-Pin DIP Gehäuse.
Eingesteckt ist derzeit ein 16MHz Quarz.
Vor dem Code noch ein paar Hinweise:
- Die Zeile um die es oben geht ist entsprechend markiert.
- Ich habe einen Teil der Warteschleife auskommentiert, um nicht immer
~6sec. warten zu müssen bis RA7 dran ist.
- "dl" = delay
Wilhelm S. schrieb:> Hast du mal versucht das LATA Register für den INC Befehl zu nutzen,> anstatt PORTA?
Mittlerweile habe ich es probiert. Keine Änderung.
Der Hinweis auf die Latch-Register hat allerdings einige Erinnerungen
wieder hervorgebracht.
Bei Schreibzugriffen auf LATx oder PORTx spielt es keine Rolle, ob man
LATx oder PORTx schreibt. Beide setzen den Zustand des
Ausgangsflip-flops.
Bei Lesezugriffen allerdings, liest
- LATx den Zustand des Ausgangsflip-flops.
- PORTx den tatsächlichen Zustand des Ausganges.
(Siehe Anhang ganz oben und ganz unten)
Noch einer schrieb:> Im Oszillator Mode ist RA6 Ausgang und RA7 Eingang. Warum erwartest du,> dass sich die beiden gleich verhalten?
Ich benutze sie weder als Eingang, noch als Ausgang (abgesehen vom
Oszillator natürlich).
Ich bin davon ausgegangen, das die Oszillatorfunktion die Flip-Flops,
die den digitalen Ausgangszustand speichern nicht beeinflusst. Der
Ausgang ist natürlich deaktiviert, sprich ob das Flip-Flop nun intern
umschaltet oder nicht ist dem Oszillator egal.
Ich verstehe allerdings nicht, warum der Oszillatorblock trotzdem
Schreibzugriffe auf RA7 deaktiviert.
Im Datenblatt steht
"When they are not used as port pins, RA6 and RA7 and their associated
TRIS and LAT bits are read as ‘0’."
Würde ich so verstehen - ganz egal was du schreibst, es passiert nichts.
Bei beiden Pins bekommst du immer '0' zurück, auch wenn du '1'
geschrieben hast.
So verstehe ich den anderen Punkt nicht. Warum werden Schreibzugriffe
auf A6 nicht blockiert?
Danish B. schrieb:> Bei Schreibzugriffen auf LATx oder PORTx spielt es keine Rolle, ob man> LATx oder PORTx schreibt.
Nene, umgekehrt wird'n Schuh daraus.
Beim Schreiben liest der Pic erstmal den gesamten Port(!) ein und
schreibt nach der Änderung, diesen auch komplett zurück. Setz also alle
Ports, die du nicht änderst, auf den realen Zustand der am Portpin
herrscht.
Daher die Einführung des LATRegisters, wenn nicht vorhanden, ne
Hilfsvariable verwenden. Oder anders, den PORT nicht als Datenspeicher
nutzen.
Noch einer schrieb:> Im Datenblatt steht> "When they are not used as port pins, RA6 and RA7 and their associated> TRIS and LAT bits are read as ‘0’.">> Würde ich so verstehen - ganz egal was du schreibst, es passiert nichts.> Bei beiden Pins bekommst du immer '0' zurück, auch wenn du '1'> geschrieben hast.>> So verstehe ich den anderen Punkt nicht. Warum werden Schreibzugriffe> auf A6 nicht blockiert?
Ich habe oben nicht die ganze Wahrheit erzählt, RD6 leuchtete dunkler
als alle anderen LED's.
Ich ging davon aus, das sich mit der Erhöhung der Bitzahl jedesmal der
Tastgrad halbiert und habe das damit begründet. Das ist Schwachsinn.
Um dennoch herauszufinden warum die LED an RD6 nun leuchtet habe ich:
- PORTA mit 0xFF beschrieben
- PORTA in W geladen
- W nach PORT D geschrieben
- Sleep (um dahinterliegende Zählschleife zu blocken)
RD6 leuchtete gar nicht mehr. Sprich RA6 und RA7 werden wie im
Datenblatt beschrieben immer mit 0 gelesen.
Allerdings leuchtet RD6, wenn man die Zählschleife (siehe oben) laufen
lässt. Wenn auch bei weitem nicht so hell, wie die Nachbarn.
RD0 - RD5 : 50% Tastgrad
RD6 : <1,2% Tastgrad (laut Rigol Scope).
Verwirrend ist allerdings, das der High-Puls von RD6 genau auf die
fallende Flanke von RD5 fällt.
Sprich es sieht so aus, als würde RD6 hochzählen und dann wieder
herunterfallen.
Danish B. schrieb:> loop>> movlb 0xFF> incf PORTA,w ; <-- Um diese Zeile geht es> movwf PORTA> movwf PORTD>> goto loop> end
Du hast also einen Binaerzaehler "programmiert" der mit maximaler
Geschwindigkeit laeuft? Ich sehe keinerlei delays oder was auch immer.Da
muss dir ja schwindlig werden beim Betrachten der Leds.Bei einem
4MHz-Quarz/Takt wuerde die Led an RA0 ca. 1us-Takt an und aus gehen.Also
halbe Helligkeit (50% DutyCycle....)
Bei dieser hohen Taktrate,waere es mehr als angebracht das LATA-Register
zu verwenden oder besser noch eine simple Verzogerungsschleife
einzubauen,damit man die Leds auch schoen tanzen sieht und damit auch
fuer klare Verhaeltnisse sorgt.
Nun - vielleicht habe ich ja auch was uebersehen oder in anderen Posts
noch nicht gelesen.
Ich verstehe nicht, was es an der Sache noch zu Rätseln gibt? Der Grund
für den Effekt wurde doch längst genannt: RA6 und RA7 sind immer 0!
Wenn in der Schleife Port A den Wert 0b00111111 erreicht hat, wird
dieser Wert durch "incf PORTA,W" von Port A gelesen, auf 0b01000000
incrementiert und ins WREG geladen und dann sowohl nach Port A, als auch
Port D ausgegeben (RD6 high), im nächsten Durchlauf wird 0b00000000 aus
Port A gelesen und auf 0b00000001 erhöht und an beide Ports
ausgegeben...
Danish B. schrieb:> movlb 0xFF
?
> incf PORTA,w ; <-- Um diese Zeile geht es
Überlege doch mal, was die Zeile genau macht. Es wird der PORTA
eingelesen, der Wert um 1 erhöht und das Ergebnis im W gespeichert.
> movwf PORTA
Danach wird W auf PORTA ausgegeben.
> movwf PORTD
Und das gleiche mit PORTD.
Diese Vorgehensweise ist nicht sinnvoll. Man sollte niemals einen Port
einlesen und manipulieren wenn man die Operation auch intern mit einem
Register machen kann.
Jetzt kommen wir zum interessanten Teil der Sache. Was passiert, wenn
die gewünschten Bits gar nicht als digitale I/Os zur Verfügung stehen?
Sie sind undefiniert und werden beim Lesezugriff meist als 0 gelesen.
Steht so glaube ich irgendwo im DB.
> Eingesteckt ist derzeit ein 16MHz Quarz.
Ach, wo ist der den angeschlossen? Ich wette jetzt mal, wenn es ein
normales Quarz ist an PORTA,6 und PORTA,7. Falls es ein ext. Oszillator
ist, dann mindestens an PORTA,7. Also steht dieser Port für dich als I/O
bei externem Takt niemals zur Verfügung und die LED wird nicht leuchten.
Du kannst ihn nur nutzen, wenn du mit dem internen RC arbeitest.
Danish B. schrieb:> Das die Ausgänge für RA6 und RA7 im Externen Oszillator Modus nicht> (digital) funktionieren ist klar.>> Aber warum lässt sich das PORTA-"Register" nicht komplett beschreiben?> Und vor allem: Warum lässt sich RA6 beschreiben, aber RA7 nicht?> Wenn schon, dann müssten beide nicht funktionieren (IMO).
Worauf basiert überhaupt Deine Annahme, daß RA6 trotz externen Oszi
funktioniert? Dürfte eigentlich nicht sein...
Ich denke, Du hast die grundsätzliche Funktionsweise der Port-Logik noch
nicht durchblickt:
- Lesezugriffe auf PORTx lesen nicht den Inhalt von irgendwelchen
Registern (im Sinne von Speicherflipflops, die durch Schreiboperationen
verändert werden könnten), sondern direkt den Logikpegel an den
Portpins. Mit externem Quarzoszi oder bei Konfiguration der Ports auf
"analog" sind die entsprechenden Porteingänge aber nicht mehr digital
lesbar und liefern 0.
- Schreibzugriffe auf PORTx gehen tatsächlich in die entsprechenden
Register-Flipflops, d.h. in das jeweilige LATx-Register.
Alle "Read-Modify-Write" Operationen auf PORTx (INCF, DECF, BSF, BCF...
, also alles, außer MOVWF) lesen also zunächst den tatsächlichen Pegel
an den Port-Pins (oder ggf. eben 0), modifizieren die Daten und
schreiben das Ergebnis dann nach LATx (oder nach W). Für sowas ist es
also besser, die Operationen gleich auf LATx, statt auf PORTx
anzuwenden, und nur für das reine Einlesen von digitalen Eingängen die
PORTx-Adressen zu verwenden.
Thomas E. schrieb:> Wenn in der Schleife Port A den Wert 0b00111111 erreicht hat, wird> dieser Wert durch "incf PORTA,W"
Ich hab nicht daran gedacht, das PORTA im W inkrementiert wird.
Beim nächsten Mal werden ich wohl vor einer Frage im Forum ne Nacht
drüber schlafen.
Dankeschön.