Forum: Mikrocontroller und Digitale Elektronik PIC16F1455 treibt LCD nur mit angeschlossenem PICkit3


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Jens B. (nixiefreak)


Angehängte Dateien:

Lesenswert?

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.

: Bearbeitet durch User
von Frank K. (fchk)


Lesenswert?

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.

fchk

von Jens B. (nixiefreak)


Lesenswert?

250ms ist drin, zeitweise auch auf 1s erhöht, ohne Unterschied. Würde 
aber nicht erklären, warum es nur mit angeschlossenem PICkit3 
funktioniert.

von Mobile (mobileteser)


Lesenswert?

Kann es sein, dass das Pic Kit einen Pull up oder Pull down Funktion 
übernimmt? Miss mal die Pegel der entsprechenden Leitungen.

von Jens B. (nixiefreak)


Lesenswert?

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.

von Arno M. (morri65)


Lesenswert?

Jens B. schrieb:
> 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.

von Jens B. (nixiefreak)


Lesenswert?

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.

von Peter G. (metalfranke)


Lesenswert?

Bis zu welcher Spannung kann das Display arbeiten? Hebt das Pickit die 
4,5V vielleicht leicht an?

von Jens B. (nixiefreak)


Lesenswert?

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.

: Bearbeitet durch User
von Uwe (uhi)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

Hier mal der korrekte Ablauf, um das LCD aus einem unbekannten Zustand 
sauber in den 4-Bit Mode zu setzen:
https://www.avrfreaks.net/s/topic/a5C3l000000ULG2EAO/t095508

Ein nicht korrekt initialisiertes LCD erkennt man oft daran, daß die 2. 
Zeile schwarz ist.

von Jens M. (schuchkleisser)


Lesenswert?

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.

von Jens B. (nixiefreak)


Lesenswert?

Peter D. schrieb:
> 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):
1
// wait for LCD to power up 
2
__delay_ms(250);
3
    
4
// initialize LCD in 4-bit mode 
5
RS=0; RW=0; send_nibble(0b0011); __delay_ms(5);
6
RS=0; RW=0; send_nibble(0b0011); __delay_ms(1);
7
RS=0; RW=0; send_nibble(0b0011);
8
RS=0; RW=0; send_nibble(0b0010);
Meine send_nibble-Routine ist wiefolgt ausgelegt:
1
void send_nibble (unsigned char n) {
2
    
3
    D7 = (n >> 3) & 1;
4
    D6 = (n >> 2) & 1;
5
    D5 = (n >> 2) & 1;
6
    D4 = (n >> 0) & 1;
7
    EN1 = 1;
8
    EN1 = 0;
9
10
}

Peter D. schrieb:
> 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.

Jens M. schrieb:
> 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.

Jens M. schrieb:
> 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.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Jens B. schrieb:
> Ich nutze keine Library sondern mache das von Hand (und es funktioniert
> von einem unbekannten Zustand aus gemaess des von Peter verlinkten
> Artikels):

Es fehlen aber die Delays nach dem 3. und 4. Nibble.

von Jens B. (nixiefreak)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

Jens B. schrieb:
> Meine send_nibble-Routine ist wiefolgt ausgelegt:

D5 dürfte falsch sein.

von Jens B. (nixiefreak)


Lesenswert?

Um Gottes Willen, das habe ich tatsaechlich uebersehen. Es muss 
natuerlich so aussehen:
1
void send_nibble (unsigned char n) {
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.

von Jens M. (schuchkleisser)


Lesenswert?

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?

von Peter D. (peda)


Lesenswert?

Jens M. schrieb:
> Ob der Compiler das in "einen" Befehl packt der den Port auf einmal
> setzen kann?

Nein, das darf er nicht:

https://learn.microsoft.com/de-de/cpp/c-language/c-sequence-points?view=msvc-170

Beim PIC kann es allerdings Seiteneffekte bei Read-Modify-Write auf das 
selbe Portregister geben.

: Bearbeitet durch User
von Jens B. (nixiefreak)


Lesenswert?

Dem LCD duerfte das egal sein weil es erst bei der negativen 
Enable-Flanke die Daten einliest.

von Frank K. (fchk)


Lesenswert?

Peter D. schrieb:

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

Und man könnte den Code umformulieren:
1
LATC=(LATC&0xf0)|n;
mit 0≤n≤15.

fchk

von Jens M. (schuchkleisser)


Lesenswert?

Peter D. schrieb:
> Nein, das darf er nicht:

Also ergibt sich Bloatware...

Peter D. schrieb:
> Beim PIC kann es allerdings Seiteneffekte bei Read-Modify-Write auf das
> selbe Portregister geben.

Genau das waren meine Bedenken.

Frank K. schrieb:
> 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.

Frank K. schrieb:
> Und man könnte den Code umformulieren:

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

von Peter D. (peda)


Lesenswert?

Frank K. schrieb:
> Das ist in dieser Allgemeinheit falsch.

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.

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.