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
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 :(
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?
Ich kann dir leider nicht weiterhelfen. Aber das war einer der Gründe, warum ich zu Atmels AVR's gewechselt habe. :-)
Und ich dachte immer, ein Compiler nimmt mir diese Probleme ab :(
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
Und wieso funktioniert dann oben Deine erste Variante? Da kommt doch auch kein LATB vor.
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
"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
Die Pins schaffen maximal 29mA bei Kurzschluß, also bricht die Ausgangsspannung entsprechend zusammen (und die LED möge überleben?). Bernd
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?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.