Forum: Mikrocontroller und Digitale Elektronik PIC-Register Verhalten


von Danish B. (danishbelal)


Lesenswert?

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

von Christian M. (Gast)


Lesenswert?

Welcher PIC? Welches Board? Ganzer Code?

Gruss Chregu

von Danish B. (danishbelal)


Lesenswert?

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

1
list p=18f45
2
include "p18f45k22.inc"
3
4
; Lauflicht auf allen Ports
5
6
; CONFIG1H
7
  CONFIG  FOSC =   HSHP        ; Oscillator Selection bits (External Crystal oscillator)
8
  CONFIG  PLLCFG = OFF          ; 4X PLL Enable (Oscillator used directly)
9
  CONFIG  PRICLKEN = ON         ; Primary clock enable bit (Primary clock is always enabled)
10
  CONFIG  FCMEN = OFF           ; Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
11
  CONFIG  IESO = OFF            ; Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
12
13
  ; Data in Bank
14
cnt1  equ   00
15
cnt2  equ   01
16
17
    org    0x00
18
    goto   main
19
20
    org    0x04
21
    main
22
23
24
    movlb   0x0F
25
    clrf    PORTA
26
    clrf    ANSELA
27
    clrf    TRISA
28
29
    clrf    PORTB
30
    clrf    ANSELB
31
    clrf    TRISB
32
33
    clrf    PORTC
34
    clrf    ANSELC
35
    clrf    TRISC
36
37
    clrf    PORTD
38
    clrf    ANSELD
39
    clrf    TRISD
40
    
41
    ;movlw   0xFF
42
    ;movwf   PORTA
43
    ;movwf   PORTB
44
    ;movwf   PORTC
45
    ;movwf   PORTD
46
    ;sleep
47
48
loop
49
    
50
    movlb   0x00
51
    movlw   0xFF
52
    movwf   cnt1
53
    movwf   cnt2
54
    
55
    movlb   0xFF
56
    incf    PORTA,w ; <-- Um diese Zeile geht es
57
    movwf   PORTA
58
    movwf   PORTB
59
    movwf   PORTC
60
    movwf   PORTD
61
62
dl  decfsz  cnt1
63
    goto    dl
64
    
65
    
66
    movlb   00
67
    movlw   0xFF
68
    movwf   cnt1
69
    decfsz  cnt2
70
    ;goto    dl
71
    
72
    
73
    
74
    goto    loop
75
    goto    endloop
76
endloop
77
    goto    endloop
78
79
80
    end                         ;das Ende des Programms

: Bearbeitet durch User
von Mc M. (mcmix)


Lesenswert?

Hast du mal versucht das LATA Register für den INC Befehl zu nutzen,
anstatt PORTA?

von Noch einer (Gast)


Lesenswert?

Im Oszillator Mode ist RA6 Ausgang und RA7 Eingang. Warum erwartest du, 
dass sich die beiden gleich verhalten?

von Tony (Gast)


Lesenswert?

PORTA hat nur 6 Bit

von Teo D. (teoderix)


Lesenswert?

Tony schrieb:
> PORTA hat nur 6 Bit

Ne da is im Dabla, nur die Seite zu ende :D

von Danish B. (danishbelal)


Angehängte Dateien:

Lesenswert?

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.

: Bearbeitet durch User
von Noch einer (Gast)


Lesenswert?

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?

von Teo D. (teoderix)


Lesenswert?

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.

: Bearbeitet durch User
von Danish B. (danishbelal)


Angehängte Dateien:

Lesenswert?

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.

von Danish B. (danishbelal)


Lesenswert?

Hier nochmal ein Minimalprogramm, mit dem das Verhalten reproduzierbar 
ist.
1
list p=18f45
2
include "p18f45k22.inc"
3
4
; Lauflicht auf allen Ports
5
6
; CONFIG1H
7
  CONFIG  FOSC =   HSHP        ; Oscillator Selection bits (External RC oscillator)
8
  CONFIG  PLLCFG = OFF          ; 4X PLL Enable (Oscillator used directly)
9
  CONFIG  PRICLKEN = ON         ; Primary clock enable bit (Primary clock is always enabled)
10
  CONFIG  FCMEN = OFF           ; Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
11
  CONFIG  IESO = OFF            ; Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
12
13
14
    org    0x00
15
    goto   main
16
17
    org    0x04
18
    main
19
    
20
    movlb   0x0F
21
    clrf    PORTA
22
    clrf    ANSELA
23
    clrf    TRISA
24
25
    clrf    PORTD
26
    clrf    ANSELD
27
    clrf    TRISD
28
    
29
loop
30
    
31
    movlb   0xFF
32
    incf    PORTA,w ; <-- Um diese Zeile geht es
33
    movwf   PORTA
34
    movwf   PORTD
35
    
36
    goto    loop
37
    end

von Teo D. (teoderix)


Lesenswert?


von Danish B. (danishbelal)


Lesenswert?

Teo D. schrieb:
> Danish B. schrieb:
>> movlb   0xFF
>
> http://www.sprut.de/electronic/pic/

Störst du dich hier daran, dass statt den eigentlich ausreichenden 0x0F 
0xFF steht?

von Toxic (Gast)


Lesenswert?

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.

von Thomas E. (picalic)


Lesenswert?

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...

von Jens P. (picler)


Lesenswert?

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.

von Thomas E. (picalic)


Lesenswert?

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.

von Danish B. (danishbelal)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.