Forum: Mikrocontroller und Digitale Elektronik PIC 12F675 Kuriosum beim Pinumschalten GPIO


von Wilhelm F. (Gast)


Lesenswert?

Hallo PIC-Freunde,

also, wie in der Überschrift steht: Da bemerkte ich seltsame Dinge, die 
ich mir nicht erklären kann.

Und zwar experimentiere ich gerade mit ultraniedrigen Taktfrequenzen, 
dem externen RC-Oszillator, wobei ich diesem mit ca. 1 Hz Taktfrequenz 
zuschauen kann, wie die Maschinenbefehle gaaaaanz langsam nacheinander 
in einer kurzen Main-Schleife abgearbeitet werden. Fast so gut wie 
Single-Step, nur automatisch.

Ich schalte nur 2 LEDs um.

Laut Datenblatt ist der PIC ja statisch, und arbeitet ab DC 
Taktfrequenz.

In der Main-Schleife zähle ich bei jedem Lauf eine Variable hoch, und 
verwende diese mit Bit-Test-Befehlen, um zwei LEDs wechselweise ein- und 
auszuschalten. Das niedrigste Bit reicht ja, es toggelt mit jeder 
Zählung.

Also, es werden da je nach dem niedrigsten Counterbit jeweils die LEDs 
umgeschaltet.

Einmal wechseln die LEDs so, daß beide sichtbar Takt für Takt 
nacheinander umschalten. Im zweiten Fall schalten beide LEDs 
gleichzeitig, obwohl die Schaltbefehle genau wie im ersten Fall 
nacheinander folgen. Genau das ist der Punkt, den ich nicht verstehe. 
Jeweils mit den Bitsetzbefehlen bsf und bcf für beide Fälle vertauscht.

Bei einem hochfrequenten Programm z.B. mit Megaherzen wäre mir das gar 
nicht aufgefallen.

Hat mal jemand eine Idee, was das sein könnte?

Natürlich glaube ich schon, den PIC-Assembler etwas zu können. Wenn 
jemand anderer Meinung ist, poste ich gerne auch den kleinen 
Programmschnipsel. Vielleicht habe ich ja heute Tomaten auf den Augen, 
manchmal sieht man simpelste Dinge nicht. ;-)

Den Simulator habe ich allerdings noch nicht bemüht, sollte aber 
grundsätzlich gehen.

von Chris (Gast)


Lesenswert?

Aktiviere mal Clockout und monitoriere diesen.
Du wirst feststellen, daß wenn du eine Led einschaltest, die Spannung
einbricht und dadurch der intern Komparator einen weiteren Clock Impuls
generiert. Passiert eigentlich nur bei sehr geringem Clock.

von Wilhelm F. (Gast)


Lesenswert?

Chris schrieb:

> Aktiviere mal Clockout und monitoriere diesen.
> Du wirst feststellen, daß wenn du eine Led einschaltest, die Spannung
> einbricht und dadurch der intern Komparator einen weiteren Clock Impuls
> generiert. Passiert eigentlich nur bei sehr geringem Clock.

Dabei habe ich die I/O doch schon als rein digitale I/O initialisiert, 
wobei ADC und Komparator abgeschaltet werden.

Aber da kennt sich jemand offenbar damit aus.

Ja, es gibt noch mehr: Die Blinkfrequenz ist im Tastverhältnis auch 
nicht gut. Der eine Zustand dauert 15 Sekunden, der andere 9 Sekunden. 
Wobei beide nach Programm gleich sein müßten. Wirklich rätselhaft.

Also muß ich mal Clockout frei schalten, und wirklich das Oszi anhängen. 
Notfalls an einem weiteren I/O noch den zweiten Oszi-Kanal anhängen.

Die Stromversorgung des PIC sehe ich jetzt nicht als kritisch, der soll 
bis 2V herunter spielen, also mit fast leeren Batterien. Aktuell sind da 
halb volle 4 Mignonzellen mit 4,9V dran, und ein paar Elkos.

Langer Rede, kurzer Sinn: Ich poste auch mal das kleine Programm:
1
;====================================================================
2
; File name: extrctest.asm
3
;====================================================================
4
 list        p=12F675, F=INHX8M ; List Direktive
5
 #include    <p12f675.inc>      ; Include-File
6
 errorlevel  -302               ; Unterdrückung Message 302 vom List-File
7
8
 __CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _EXTRC_OSC_NOCLKOUT
9
10
; Test externer RC-Oszillator mit 1µF und 100kOhm.
11
; Die Zeitkonstante ergibt 100ms.
12
13
; Es geht um eine Energieverbrauchsminimierung.
14
15
#define  BANK1    banksel 0x80   ; Select BANK1
16
#define  BANK0    banksel 0x00   ; Select BANK0
17
18
; Definitionen
19
#define LED1     GPIO,GP0       ; Blink-LED
20
#define LED2     GPIO,GP1       ; Blink-LED
21
22
; RAM
23
    udata_shr
24
COUNTER     res 1               ; Universalzaehler
25
;====================================================================
26
    org 00
27
    goto    start
28
;
29
;====================================================================
30
    org 04
31
isr:
32
    retfie
33
;====================================================================
34
35
; Achtung!
36
; Die Taktfrequenz ist sehr gering, durch die externe RC-Kombination
37
; vielleicht um die 10 Hz.
38
39
start:
40
;
41
    bcf     STATUS,RP0          ; Bank 0
42
    clrf    GPIO
43
    movlw   03h                 ; GP<1:0> sind
44
    movwf   CMCON               ; digitale IO
45
    bsf     STATUS,RP0          ; Bank 1
46
    movlw   b'11111100'         ; GP0 und GP1 Output LED-Signalisierung
47
    movwf   TRISIO              ; sonst alle Input
48
;
49
    clrf    ANSEL               ; Nur PIC12F675
50
;
51
    bcf     STATUS,RP0          ; Bank 0
52
    clrf    COUNTER
53
;
54
loop:
55
;
56
    incf    COUNTER,f
57
    btfss   COUNTER,0
58
    goto    loop_2
59
    bsf     LED1
60
    bcf     LED2
61
    goto    loop_done
62
loop_2:
63
    bcf     LED1
64
    bsf     LED2
65
;
66
loop_done:
67
    goto    $+1                 ; Hier kann noch mal der Watchdog mit
68
    goto    loop                ; hinein, und sonst was
69
;
70
;====================================================================
71
    END

von hä? (Gast)


Lesenswert?

> Ja, es gibt noch mehr: Die Blinkfrequenz ist im Tastverhältnis auch
> nicht gut. Der eine Zustand dauert 15 Sekunden, der andere 9 Sekunden.
> Wobei beide nach Programm gleich sein müßten. Wirklich rätselhaft.

Hä?

Da sind doch 1. Sprungbefehle, die dauern 2 Takte und Du hast 2. noch 
incf COUNTER,f und btfss COUNTER,0 drin

von Wilhelm F. (Gast)


Lesenswert?

hä? schrieb:

> Da sind doch 1. Sprungbefehle, die dauern 2 Takte und Du hast 2. noch
> incf COUNTER,f und btfss COUNTER,0 drin

Das tut sich in der Zahl der Taktzyklen nichts. Der incf Counter sowieso 
gar nicht.

von B. S. (bestucki)


Lesenswert?

hä? schrieb:
> Da sind doch 1. Sprungbefehle, die dauern 2 Takte und Du hast 2. noch
> incf COUNTER,f und btfss COUNTER,0 drin

goto benötigt 2 Taktzyklen
incf benötigt 1 Taktyklus
btfss benötigt 1 Taktzyklus wenn das Bit nicht gesetzt ist und 2 wenn es 
gesetzt ist.

Ich erhalte für einen Durchlauf durch Loop2 10 Taktzyken und andersrum 
11 Taktzyklen.

von Chris (Gast)


Lesenswert?

Naja, wenn LED2 eingeschalten wird, sind es 10 clk, hingegen wenn
LED1 eingeschalten wird, verbraucht der loop 11 clk.

Ich sprach vom Komparator des RC-OSC. Bei ungünstiger Beschaltung 
passiert
sowas, wobei dein Code nicht zu deiner Aussage passt.

von Peter D. (peda)


Lesenswert?

2 Bitbefehle hintereinander geht nicht, da muß ein NOP dazwischen.
Auf Sprut wird das erklärt, warum.

von Wilhelm F. (Gast)


Lesenswert?

Peter Dannegger schrieb:

> 2 Bitbefehle hintereinander geht nicht, da muß ein NOP dazwischen.
> Auf Sprut wird das erklärt, warum.

Danke, ich werde das so einfach mal testen.

Findet man das denn nicht in PIC-Manuals? Wenn nein, warum nicht? Oder 
war ich zu blöd, die Stelle zu finden?

Aber wie schon gesagt, wenn das nicht gerade mit 1 Hz passiert, sondern 
1 MHz, stört es sicherlich meistens gar nicht.

von Chris B. (dekatz)


Lesenswert?

Peter Dannegger schrieb:
> 2 Bitbefehle hintereinander geht nicht, da muß ein NOP dazwischen.
> Auf Sprut wird das erklärt, warum.

Stimmt nicht.
Weiss nicht auf WAS sich Sprut dabei genau bezieht, aber ich habe noch 
nie zwischen Bitbefehlen ein NOP geschrieben.

von Wilhelm F. (Gast)


Lesenswert?

Chris B. schrieb:

> aber ich habe noch
> nie zwischen Bitbefehlen ein NOP geschrieben

Ich bisher auch nicht. Bis Peter kam, und behauptet, irgendwo auf der 
Welt wäre es erklärt. Ohne konkrete Quellenangaben und Links natürlich. 
;-)

Meint der eigentlich, ich würde jetzt Sprut komplett absuchen? ;-)

von (prx) A. K. (prx)


Lesenswert?

Wilhelm Ferkes schrieb:
> Meint der eigentlich, ich würde jetzt Sprut komplett absuchen? ;-)

Klar. Irgendeiner muss es ja machen. ;-)

von Chris B. (dekatz)


Lesenswert?

Sprut selbst zeigt ja selbst genug Codeschnipsel mit "bsf", "bcf" in ein 
und dem selben Register OHNE "nop" dazwischen.
Vermutlich sind in irgend welchen Listings zwischen 2 Bitbefehlen ein 
NOP eingefügt wenn eine Leitung getaktet wird etc.

von Chris B. (dekatz)


Lesenswert?

Habe es gefunden: es geht um die "I/O speed Falle" - dürfte aber bei 10 
Hz nicht ausschlaggebend sein
http://www.sprut.de/electronic/pic/fallen/fallen.html

von Wilhelm F. (Gast)


Lesenswert?

Also Jungs, herzlichen Dank noch mal an alle.

Der Fehler lag natürlich bei mir. Und das auch noch bei einem Winzling 
8-Pinner, der was um nen Euro herum kostet!

Das Register CMCON war falsch initialisiert. Es ist nach Reset auf 0x00, 
muß aber nach nochmaligem genauem Hinschauen ins Datenblatt auf 0x07 
initialisiert sein, damit der Komparator aus ist, und die zugehörigen 
drei GPIO-Pins digitale I/O werden. Auch das Register ANSEL muß nach 
Reset gelöscht werden, damit die I/O digital sind. Es steht nach Reset 
auf 0x0F. Also anders herum als bei CMCON.

CMCON und ANSEL müssen also nach Reset initialisiert werden. Wenn man es 
nicht tut, wie auch in einigen Beispielcodes, dann funktionieren die I/O 
trotzdem auch digital. Mir fiel da über die Jahre wirklich nichts auf.

In Beispielen wurde das CMCON oft auch gar nicht beachtet, und bei 
höheren Taktfrequenzen fällt die von mir beobachtete Funktionsweise ja 
auch gar nicht auf.

Die Sache mit den NOPs versuchte ich noch mal, das spielt aber überhaupt 
gar keine Rolle. Jetzt nach der richtigen Initialisierung wird jeder 
Befehl an I/O genau so ausgeführt, wie es sein soll.

Die Hauptschleife vereinfachte ich noch mal wie folgt:
1
loop:
2
    bsf     LED1
3
    bcf     LED2
4
    nop
5
    nop
6
    nop
7
    nop
8
    bsf     LED2
9
    bcf     LED1
10
    nop
11
    nop
12
    goto    loop

Sie läuft in etwas mehr als 10 Sekunden einmal durch, ich verlängerte 
noch mal die Zeitkonstante des RC-Gliedes auf 320ms. Damit hat ein 
Taktzyklus ungefähr 0,8 Hz bzw. ca. 1,25 Sekunden Dauer. Man kann bei 
jeder Befehlsausführung bequem auf den Sekundenzeiger der Uhr schauen, 
und es so mit verfolgen.

Wie schon gesagt, es war nicht ausgesprochen lebenswichtig. Niemand 
betreibt in der Regel einen µC mit 1 Hz Taktzyklus. Auf meine Art habe 
ich aber jetzt was gelernt, was anderen erst gar nicht auffällt.

Fast gleichzeitig umschalten lassen sich beide Pins bei dieser 
Geschwindigkeit natürlich nicht. Ich werde es auch noch mal mit einem 
Bytebefehl zum Portzugriff versuchen, ob sich die Sache da genau so 
bemerkbar macht, oder nicht.

Kürzlich betrieb ich ja auch noch einen Parallelportbaustein mit 5 Pins 
Interface an den I/O, aber mit Normalspeed 1 MHz. Das ging ganz gut. 
Hier wurden die Ports wieder mit Bytebefehlen gesetzt.

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.