Nutze das PICkit3 im Zusammenhang mit dem pickitminus (http://kair.us/projects/pickitminus/index.html) da ja der offizielle SUpport eingestellt wurde. Der PIC16F1455 steuert ein 2x40 LCD an, und alles funktioniert wie es soll, wenn das PICkit3 angeschlossen ist. Schaltplan im Anhang. Nach dem Flashen, und der "release from reset"-Modus ist aktiviert, erscheinen die Zeichen wie gewuenscht auf dem LCD. Eine Blinke-LED (an Enable-2 angeschlossen) blinkt auch brav und zeigt Programm-Aktivitaet an.
Nun schalte ich VDD ab. Stoepsle das PICkit 3 ab. Schalte VDD wieder zu. LED blinkt (= Programm laeuft) aber das LCD zeigt keine Zeichen an.
Im Code ist Master Clear als IO konfiguriert (#pragma config MCLRE = OFF) sowie LVP deaktiviert (#pragma config LVP = OFF). Lasse den Pin floaten, aber ihn nach GND oder VDD zu ziehen ueber einen 4k7 oder direkt aendert auch nichts.
Ich bin wirklich mit meinem Latein am Ende. Irgendwelche Ideen?
//edit: Betriebsspannung wird ueber 4.5V (3xAA) Batterien bereitgestellt, und ist stabil bei 4.5V. Betrieb ueber lineares Labornetzteil hat gleiches Resultat.
Lass dem LCD mal nach dem Programmstart ein paar 100ms Zeit, um sich zu sortieren, den Oszillator zu starten und die Versorgungsspannungen einschwingen zu lassen. Diese Teile sind nicht immer die schnellsten.
Siehe oben: der Pullup aendert nichts. Zudem ist die Funktion von MCLR per config word auf IO gesetzt. Ausserdem laeuft das Programm ja (die LED blinkt), also kann es das ja nicht sein.
Siehe oben: der Pullup aendert nichts. Zudem ist die Funktion von MCLR
per config word auf IO gesetzt. Ausserdem laeuft das Programm ja (die
LED blinkt), also kann es das ja nicht sein.
Nicht nur MCLR, sondern auch RW und E des Displays.
RS, RW, und E sind an die IOs des PIC16F1455 angeschlossen, siehe Schaltplan, somit ist ein Pullup oder Pulldown nicht notwendig. Ausserdem: warum sollte alles funktionieren, wenn das PICkit angeschlossen ist? RS RW und E haben doch nichts mit den Leitungen vom PICkit zu tun.
PICkit habe ich auf "use external power" eingestellt, es laesst die Spannung unveraendert. Ich habe bisher problemlos LCDs mit 4.5V und PICs betrieben, dies ist das erste Mal, dass es nicht funktioniert. Zum Testen habe ich es an mein lineares Netzteil bei 5V angeschlossen, und ohne PICkit: selbes Ergebnis. Das Programm laeuft, das LCD reagiert nicht.
//edit: Habe hier ein 2x8, 1x16, 2x16, 2x40, 4x20, und sogar 4x40 Display liegen, alle verhalten sich gleich.
Ich würde pauschal mal messen (Oszi), ob alle Leitungen zum Display wie gewünscht "zappeln". Und wenn sie das tun, mit dem Logic-Analyzer (15€ Saleae-Clone reicht) schauen, ob das Timing verschieden ist mit und ohne PICkit.
Meine erste Vermutung wäre auch gewesen: Zu schnelles Startup. Legt das PICkit die Versorgung schon dauerhaft an (so dass das LCD gemütlich hochfahren kann) und lässt später den Controller loslaufen? Kann auch ein floatender Pin sein, der bei der langsamen PICkit-Startsequenz einen anderen Pegel erreicht als bei "Power und los". Oder (fehlende) Abblock-Kondensatoren, so dass einer der Teilnehmer einen Reset bekommt und die sich dann nicht mehr verstehn.
Viele LCD-Libs sind leider fehlerhaft und setzen nicht richtig den 4-Bit Mode. Oft fällt das nicht auf, wenn das LCD nach dem Power-On im 8-Bit Mode startet.
Funktioniert die Schaltung mit PicKit auch beim ersten Mal korrekt?
Ich vermute, dass du das Display nicht korrekt initialisierst, und beim Batteriebetrieb hast du immer einen Kaltstart, bei Pickit-Betrieb ist ab dem zweiten Reset ebendieser ein Warmstart.
Zudem floaten die Portpins zum Display ja nach dem Reset, bis du die Ports initialisiert hast, evtl. spackt es da.
Ein paar Pulldowns (E, RS, Rd) und Pullups (D0-7) helfen evtl.
Viele LCD-Libs sind leider fehlerhaft und setzen nicht richtig den 4-Bit
Mode. Oft fällt das nicht auf, wenn das LCD nach dem Power-On im 8-Bit
Mode startet. [...]
Ich nutze keine Library sondern mache das von Hand (und es funktioniert von einem unbekannten Zustand aus gemaess des von Peter verlinkten Artikels):
Ein nicht korrekt initialisiertes LCD erkennt man oft daran, daß die 2.
Zeile schwarz ist.
Initialisierung ist erfolgreich, so weit ich sehen kann, da die erste Zeile erst komplett weiss ist (nutze blaues LCD) und dann leer ist. Aber es erscheinen keine Zeichen auf dem Display, nur mit angeschlossenem PICkit.
Funktioniert die Schaltung mit PicKit auch beim ersten Mal korrekt?
Ich vermute, dass du das Display nicht korrekt initialisierst, und beim
Batteriebetrieb hast du immer einen Kaltstart, bei Pickit-Betrieb ist ab
dem zweiten Reset ebendieser ein Warmstart.
Interessant! Kaltstart funktioniert tatsaechlich nie, auch mit angeschlossenem PICkit. Nur direkt nach dem Flashen laeuft alles wie erwartet. Bei erneutem Flashen ebenso. Wenn ich danach die Batterien abklemme und wieder dazuschalte, erscheint wieder kein Text.
Allerdings scheint das LCD doch irgendwas zu lesen, da die erste Zeile sich nach Programmbeginn leert.
Zudem floaten die Portpins zum Display ja nach dem Reset, bis du die
Ports initialisiert hast, evtl. spackt es da.
Ein paar Pulldowns (E, RS, Rd) und Pullups (D0-7) helfen evtl.
Naja, stimmt, aber deshalb warte ich ja 250ms bevor ich irgendwas ans LCD sende, das sollte es daher nicht sein.
Bei 4MHz Takt (effektiv 1MHz) braucht es da keine Delays mehr, siehe https://sprut.de/electronic/lcd/index.htm#init . Aber ich habe die auch mal testweise eingefuegt mit einem uebertriebenen __delay_ms(25) fuer alle vier send_nibbles, mit keinem Unterschied.
Um Gottes Willen, das habe ich tatsaechlich uebersehen. Es muss natuerlich so aussehen:
1
voidsend_nibble(unsignedcharn){
2
3
D7=(n>>3)&1;
4
D6=(n>>2)&1;
5
D5=(n>>1)&1;
6
D4=(n>>0)&1;
7
8
EN1=1;
9
EN1=0;
10
11
}
Dass bei D5 weiter oben ein (n >> 2) & 1; stand und es ein (n >> 1) & 1; sein musste, habe ich wirklich nicht gesehen. Nun laeuft alles so wie erwartet.
Ob der Compiler das in "einen" Befehl packt der den Port auf einmal setzen kann?
Oder kommen da tatsächlich 4 Bitsetzer raus, so das die Bits seriell am Port erscheinen?
Beim PIC kann es allerdings Seiteneffekte bei Read-Modify-Write auf das
selbe Portregister geben.
Das ist in dieser Allgemeinheit falsch.
Alte 8-Bit PICs haben nur ein PORT-Register und damit dieses Problem.
Alle halbwegs aktuellen 8-Bit PICs (dazu gehört auch der 16(L)F1455) sowie alle 16- und 32 Bit PICs haben sowohl PORT als auch LAT-Register und damit dieses Problem nicht mehr.
Alle halbwegs aktuellen 8-Bit PICs (dazu gehört auch der 16(L)F1455)
sowie alle 16- und 32 Bit PICs haben sowohl PORT als auch LAT-Register
und damit dieses Problem nicht mehr.
Wie das Nibble respektive die Datenbits wohl definiert sind ;)
Wenn da steht das D4 bis D7 PORTC,4 bis ,7 sind, dann darf der Compiler nicht im LATC rumpfuschen. Mit evtl. o.g. Effekten.
Effektiv ja, ergibt aber Magic Numbers und die sind verpönt, oder?
Wie schreibt man's richtig, übersichtlich und wartbar?
Wie geht man damit um, das Bit 4-7 auch am Port 4-7 sein muss und sich die Reihenfolge nicht ändern darf?
Die Lösung mit D4-D7 ist da ja flexibler, da kann es jeder Pin sein, aber der Code kann Seiteneffekte haben...
Nö.
Ich habe schon mit Bedacht "kann" geschrieben. Wenn man die Problematik nicht kennt und das falsche Register nimmt, kann es dazu kommen.
Der Compiler nimmt nicht von sich aus das entsprechende LAT-Register, sondern macht stur, was der Programmierer hinschreibt.