Forum: Mikrocontroller und Digitale Elektronik Trivial: LED blinken lassen mit C18 ?


von Thorsten (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bin gerade am verzweifeln und hoffe auf ein Tip von euch. Ziemlich
triviale Sache eigentlich: ich möchte PB0 eines PIC18F2550 blinken
lassen, ich programmiere mit dem C18. Vorweg, TRISB etc. ist gesetzt,
der Controller läuft. Das blinken klappt (ca. 2Hz) auch mit folgendem
Code (Variante 1):

while(1)
{
  PORTB &= 0xf0;      // PB3..0 auf 0 setzen
  Delay10KTCYx(255);
  PORTB |= 0x01;      // PB0 auf 1
  Delay10KTCYx(255);
}

Soweit so gut. Wenn ich jetzt folgenden Code benutze, blinkt nichts
mehr (Variante 2):

while(1)
{
  PORTB ^= 0x01;     // PB0 toggeln
  Delay10KTCYx(255);
}

Im Simulator funktioniert jedoch alles einwandfrei. Im Anhang ist der
vom Compiler erzeugte Code. Der obere Teil zeigt den Assemblercode von
Variante 1, der untere Teil ist für Variante 2. Es ist offensichtlich
so, daß der Controler den BTG-Befehl (bit toggle) nicht ausführt. Hat
der etwa ne macke? Die Teile sind von eBay, der Datecode endet mit UD
(siehe http://www.mikrocontroller.net/forum/read-1-189045.html#new). Ob
es was damit zu tun hat?

Was meint ihr dazu?

Gruß
Thorsten

von Thorsten (Gast)


Lesenswert?

Hab jetzt nochmal was anderes probiert:

...
PORTB &= 0b11110000;

_asm BTG PORTB, 0, 0 _endasm    // inline assembler
_asm BTG PORTB, 0, 0 _endasm

while(1);
...

Zuerst wird PB0 auf 0 gesetzt. Nach dem ersten BTG müßte PB0 auf 1
gehen, was auch geschieht. Nach dem zweiten BTG müßte PB0 wieder aif 0
gehen und genau das geschieht nicht. Es wird immer nur ein einziger
BTG-Befehl ausgeführt, alle weiteren ändern das Bit nicht mehr :(

von Thorsten (Gast)


Lesenswert?

Ok, hab den Fehler gefunden. Es liegt daran, daß der Compiler das
Banking nicht beachtet, mit "BTG PORTB, 0, 1" funktioniert es. Nur
wie macht man dem Compiler klar, daß er es eben genau so machen soll?

von Bri (Gast)


Lesenswert?

Ich kann dir leider nicht weiterhelfen. Aber das war einer der Gründe,
warum ich zu Atmels AVR's gewechselt habe. :-)

von Thorsten (Gast)


Lesenswert?

Und ich dachte immer, ein Compiler nimmt mir diese Probleme ab :(

von Thorsten (Gast)


Lesenswert?

So, es war doch nicht das Banking, der Compiler macht das schon richtig.
Es lag mal wieder (wie fast immer) am dummen Programmierer der das
Datenblatt nicht richtig lesen konnte. Die neueren PICs haben außer
z.B. TRISB und PORTB noch ein LATB. TRIS setzt die Richtung der Pins,
PORT dient zum lesen der Pins und LAT zur Ausgabe. Die älteren PICs
hatten dieses LAT-Register nicht :( Mit

while(1)
{
  LATB ^= 0x01;
  Delay();
}

ist die Welt wieder in Ordnung.

Gruß
Thorsten

von Michi (Gast)


Lesenswert?

Und wieso funktioniert dann oben Deine erste Variante?
Da kommt doch auch kein LATB vor.

von Thorsten (Gast)


Lesenswert?

Da hast du allerdings recht...

von martinwisi (Gast)


Lesenswert?

Hallo

Es funktioniert deswegen, weil dort der Wert nicht in das PORT Register
geschrieben wird sondern der PIC direkt in das LAT Register schreibt,
auch wenn man im Programm PORTB schreibt...

Wenn man das Bit jedoch toggeln will dann wird der Wert der aktuell am
PORT anliegt ausgelesen und dann dort das jeweilige Bit getoggelt und
dann wieder ins LAT Register geschrieben!
Und eine Led reicht oft schon aus, dass der PIC bei High Ausgang Low
einliest....
Deswegen verwendet man dann zum toggeln das LAT Register, weil da die
Spannungswerte an den Pins keinen einfluss auf das LAT Register
haben...

MfG Martin W

von Peter Dannegger (Gast)


Lesenswert?

"Und eine Led reicht oft schon aus, dass der PIC bei High Ausgang Low
einliest...."


Huch, wer macht denn bloß sowas, eine LED ohne Begrenzerwiderstand
anschließen ?


Bei nem AVR würden dann lt. Datenblatt mindestens 75mA fließen, schade
um die LED.


Peter

von bernd (Gast)


Lesenswert?

Die Pins schaffen maximal 29mA bei Kurzschluß, also bricht die
Ausgangsspannung entsprechend zusammen (und die LED möge überleben?).

Bernd

von Thorsten (Gast)


Lesenswert?

Ich hab an dem Pin ne low current LED über nen 750 Ohm Widerstand
hängen. Hab ich vielleicht zu viel parasitäre Kapazität an dem Pin, so
das er beim einlesen noch den falschen Wert kriegt?

von bernd (Gast)


Lesenswert?

@Thorsten:
Wieso, klappt das mit LATx nicht?

von Thorsten (Gast)


Lesenswert?

Doch, denn bei LATx wird der Port ja nicht eingelesen nur mit PORTx
klappt es aber nicht, obwohl es ja eigentlich auch klappen müßte.
Martin meinte ja, daß evtl. die LED Schuld sein könnte. Ich hab auch
leider zur Zeit kein Scope da, um mir mal anzusehen was da am Pin so
abgeht.

von Thorsten (Gast)


Lesenswert?

Meine Güte, wie peinlich. Es funktioniert natürlich auch mit PORTB nur
ist das Problem, daß Port B auch als Input für den ADC fungiert und per
Default sind diese Portpins eben als ADC-Eingänge geschaltet und dies
bleibt auch so, obwohl durch TRISB diese Bits als Ausgang festgelegt
wurden. Und wenn die ADC-Eingänge aktiviert sind, so wird IMMER Null
vom Port gelesen, dies wird getoggelt, anschließend wird also der
entsprechende Pin IMMER auf High gesetzt (read-modify-write). Genau das
deckt sich auch mit meiner Beobachtung, nach der der Pin auf High geht
und so bleibt.

Man muß - wenn man diese Pins als digitale IOs nutzen will - dies noch
zusätzlich in ADCON1 einstellen. Alternativ kann man auch ein
Konfigurationsbit setzen, durch welches RB[4:0] per Default auf
digitale IOs gesetzt wird.

Zusammengefaßt läßt also folgender Code PB0 blinken:

...
ADCON1 = 0x0F;  // Alle Pins als digitale IOs nutzen

TRISB &= 0xF0;
PORTB &= 0b11110000;
LATB &= 0b11110000;

while(1)
{
   PORTB ^= 0x01;
   Delay10KTCYx(255);
}
...

So jetzt bin ich beruhigt und kann mich aufs Wochenende freuen :)

Gruß
Thorsten

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.