Seltsamer "LCD Fehler"

OP #4294739
Lesenswert?

Hi,

spiel hier grad mit nem PIC18F25K22 rum.
[laber]
Bei der Gelegenheit wollte ich der bisher hervorragend funktionierenden 
LCD-Routine, das dämliche 2ms warten austreiben. Ergebnis Display tot. 
Ziemlich dumm auf den wahrscheinlich funktionierenden Code gestarrt... 
OK alles retoure (Backup), noch mehr blöd guck... Als der Hamster wieder 
auf dem Rad war, hab ich das fehlende Häkchen im Codeconfigurator 
eindeckt... grr.. Erst mal'n Pfeif... ähh ne Zigarette angezündet.
So ab nu wird's lustig. Alles, bis auf eine Kleinigkeit, funktioniert 
alles wie vorher.
[/laber]

Folgender Code produziert nicht wie gehabt die Ausgabe:
"xx.x°C"
Sondern:
"xx.x°B"
Also ASCII+1. Alle anderen Ausgaben auf dem LCD, sind Korrektor.

Ich habe nicht die geringste Idee wo ich da den Fehler suchen sollte?
1
void Temp_LCD_Ausgabe(char tab) {
2
    char PBuff[5], buffer, n;
3

4
    temperatur = Temp_messen();
5
    utoa(PBuff, temperatur, 10);
6
    n = strlen(PBuff) - 1;
7
    buffer = PBuff[n];
8
    PBuff[n] = '.';
9
    PBuff[++n] = buffer;
10
    PBuff[++n] = 0xdf; // "°"
11
    PBuff[++n] = 'C';
12
    PBuff[++n] = NULL;
13
    LCD_Tab(tab);
14
    LCD_Print(PBuff);
15
}
OP #4294806
Lesenswert?

Jörg W. schrieb:
> Wie viele Zeichen möchtest du da gleich ausgeben, einschließlich
> des terminierenden Nullzeichens?

3(char) + 2(.,C) + 1(NULL) = 6
...°
Naja, die Rechnung stimmt wenigstens :(
DANKE
(kann mich garnicht erinnern da rumgepfuscht zu haben. Zeiger... hat 
wahrscheinlich bisher nur zufällig funktioniert)

Jörg W. schrieb:
> NULL ist per Konvention ein Zeiger, aber kein Nullzeichen.  Das heißt
> entweder einfach 0, oder wenn du's kompliziert magst, '\0'.

Hmm... laut Manual vom XC8 ist das auch (?) der Nullterminator für 
"Strings"
#4294825
Lesenswert?

Teo D. schrieb:

> Hmm... laut Manual vom XC8 ist das auch (?) der Nullterminator für
> "Strings"

Ja. Numerisch sind NULL, 0, '\0' alles dasselbe. Eine binäre 0.

Aber die Intention von NULL ist es, einen ungültigen Pointer Wert 
anzuzeigen. Die Betonung liegt auf Pointer. NULL wird also per 
Konvention im Umfeld von Pointern verwendet. Niemand klopft dir auf die 
Finger, wenn du es in einem anderen Umfeld benutzt. Aber die Verwirrung 
ist gross. Denn was hat denn der Inhalt einer char Variablen mit einem 
Pointer zu tun? Gar nichts.

Das ist ungefähr so, wie wenn du schreibst
1
  double radius = 'a';
2
  double umfang = 2 * radius * 3.1415926;

kannst du machen. Als Character hat 'a' einen Ascii Code, diese Codezahl 
wird zu einem double gewandelt und zugewiesen. Syntaktisch ist da nichts 
falsch drann.
Trotzdem ist es wohl in den meisten Fällen verwirrend.

Solche Dinge fallen unter den Oberbegriff der 'aktiven 
Arbeitsplatzsicherung'.
OP #4294919
Lesenswert?

Nö, hat er nich. Egal, schreib den Mist ja eh nur für mich.

Momentan nervt mich mehr daß mir das,
1
bool LCD_Bussy(void) {
2
    bool x;
3
    LCD_D3_SetDigitalInput();
4
    LCD_RS_LAT = 0;
5
    LCD_RW_LAT = 1;
6
//        __delay_us(25);
7
    x = LCD_D3_PORT;
8
    LCD_D3_SetDigitalOutput();
9
    return (x);
10
  }
scheinbar kein BussyFlag aus dem LCD entlockt. Liest ständig Hi ein!
Nicht mein Tag Heute, steh sicher wiedermal nur auf'm Schlauch :(

PS:Dabla nach Besonderheiten der Pins durchforstet! Nix.
Morgen mal den "Code Configurator" überprüfen, ob der auch wirklich 
alles so wie gewollt generiert hat. Wär nicht das erste mal das nicht.
OP #4295142
Lesenswert?

neuer PIC Freund schrieb im Beitrag #4295017:
> Müsste es nicht
>
> 3(char) + 3(.,C,°) + 1(NULL) = 7
>
> heißen?

Jup und dank Jörg W. ist's mir auch aufgefallen das da was fehlt.
Lustig ist halt, das das mehrere Tage problemlos funktioniert hat (trotz 
ständigen Programmänderungen).
Gast #4295477
Lesenswert?

Teo D. schrieb:
> Hmm... laut Manual vom XC8 ist das auch (?) der Nullterminator für
> "Strings"

Ich wette da steht "NUL" und nicht "NULL".

Teo D. schrieb:
> Momentan nervt mich mehr daß mir das,
>   bool LCD_Bussy(void) {
>     bool x;
>     LCD_D3_SetDigitalInput();
>     LCD_RS_LAT = 0;
>     LCD_RW_LAT = 1;
>   //        __delay_us(25);
>     x = LCD_D3_PORT;
>     LCD_D3_SetDigitalOutput();
>     return (x);
>   }
> scheinbar kein BussyFlag aus dem LCD entlockt. Liest ständig Hi ein!

Busy schreibt mal üblicherweise mit nur einem s.

Funktioniert es wenn das 25us Delay NICHT ausgeklammert ist? Ich kenne 
zwar dein uC nicht, aber kann mir vorstellen das er sich ein bisschen 
Zeit nehmen möchte um die Port-Richtung zu ändern.
Gast #4295550
Lesenswert?

beric schrieb:
> Busy schreibt mal üblicherweise mit nur einem s.
Ubs, (danke)


Klar hab ich das getestet, deshalb steht das ja auch noch da. Kommt zum 
weiter testen aber wieder rein. Hab kein original Dabla, nur 
Pinbelegung, Spannungen und "kompatibel mit HD47...". Pollin Zeugs halt. 
Wer weiß wie lang das teil zum umladen der Gatekapazität braucht.
#4295624
Lesenswert?

beric schrieb:

Ich weis ja nicht, welches LCD du benutzt, aber das kommt mir komisch 
vor
1
bool LCD_Bussy(void) {
2
    bool x;
3
    LCD_D3_SetDigitalInput();
4
    LCD_RS_LAT = 0;
5
    LCD_RW_LAT = 1;
6
//        __delay_us(25);
7
    x = LCD_D3_PORT;
8
...

kein Übernahmepuls? Oder sonst irgendeine Benachrichtigung nach dem 
Muster 'jetzt gilts'?
Einfach nur R/S auf 0 setzen, RW auf 1 und das wars?
Kann ich mir nicht vorstellen.
#4295626
Lesenswert?

Karl H. schrieb:
> beric schrieb:
>
> Ich weis ja nicht, welches LCD du benutzt, aber das kommt mir komisch
> vor
>
1
> bool LCD_Bussy(void) {
2
>     bool x;
3
>     LCD_D3_SetDigitalInput();
4
>     LCD_RS_LAT = 0;
5
>     LCD_RW_LAT = 1;
6
> //        __delay_us(25);
7
>     x = LCD_D3_PORT;
8
> ...
9
>
>
> kein Übernahmepuls? Oder sonst irgendeine Benachrichtigung nach dem
> Muster 'jetzt gilts'?
> Einfach nur R/S auf 0 setzen, RW auf 1 und das wars?
> Kann ich mir nicht vorstellen.

Schaun wir mal, wie Grossmeister Fleury das macht
1
static uint8_t lcd_waitbusy(void)
2

3
{
4
    register uint8_t c;
5
    
6
    /* wait until busy flag is cleared */
7
    while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}

ok. also die Funktion lcd_read macht das.
1
static uint8_t lcd_read(uint8_t rs) 
2
{
3
    uint8_t data;
4
    
5
    
6
    if (rs)
7
        lcd_rs_high();                       /* RS=1: read data      */
8
    else
9
        lcd_rs_low();                        /* RS=0: read busy flag */
10
    lcd_rw_high();                           /* RW=1  read mode      */
11

12
bla bla bla
13
    
14
        lcd_e_high();
15
        lcd_e_delay();        
16
        data = PIN(LCD_DATA0_PORT) << 4;     /* read high nibble first */
17
        lcd_e_low();
18

19
...

AHA!!!
Also doch einmalig mit dem E-Pin wackeln.
Ist auch logisch so.
Woher soll denn das LCD wissen, wann du fertig bist mit dem Einstellen 
der Steuerleitungen.
OP #4295791
Lesenswert?

Karl H. schrieb:
> AHA!!!
> Also doch einmalig mit dem E-Pin wackeln.

Davon steht aber in meinem Dabla nix :(
OK, sorry, ist kein original HD47... Hat wohl etwas gelitten, beim 
abschreiben und übersetzen. Sieht aber dem Original zum verwechseln 
ähnlich. Werd das mal genauer vergleichen.

Werd's später mal wackeln lassen :)


> Ist auch logisch so.
> Woher soll denn das LCD wissen, wann du fertig bist mit dem Einstellen
> der Steuerleitungen.

Ich dachte, das hat wohl nichts direkt mit dem Prozessor zu tun, sondern 
da antwortet ein einfaches Logikgatter.
Moderator Persönliche Seite #4295848
Lesenswert?

Teo D. schrieb:
> Ich dachte, das hat wohl nichts direkt mit dem Prozessor zu tun, sondern
> da antwortet ein einfaches Logikgatter.

Das Datenblatt ist da etwas seltsam.  Zum einen suggeriert es das,
was du da rausgelesen hast, andererseits siehe Bild, die read operation
bekommt in den Timing-Diagrammen ganz normal ihre Timing-Werte.

Ich hab' sie jedenfalls bisher auch immer als kompletten Buszyklus
(mit E-Impuls und allem) behandelt, und das hat funktioniert. ;-)
Angehängte Dateien:
Gast #4295885
Lesenswert?

Ach, ihr streitet euch mal wieder um des Kaisers Bart.
Offenbar geht es darum, daß der TO eine Art Dezimalpunkt in seine 
Zeichenfolge haben möchte, aber sich scheut, deswegen auf float 
umzusteigen. Nun ja, dann eben so:
1
void CharInsert (char* Buffer, int maxlen, int pos, char was)
2
{ int i;
3
  char a, b;
4
  i = 0;
5
  while (i<pos)
6
  { if (Buffer[i]==0) return;
7
    ++i;
8
  }
9
  a = was;
10
  while (i<maxlen)
11
  { b = Buffer[i];
12
    Buffer[i] = a;
13
    if (a==0) return;
14
    a = b;
15
    ++i;
16
  }
17
}
Hab's mal aus einem steinalten Projekt herausgekramt.

Aber nochwas: Der Titel des Threads ist voll daneben. Sowas hat mit 
LCD's überhaupt nichts zu tun, sondern nur mit des TO's Problem beim 
Einfügen eines Zeichens. Besser: "wie füge ich ein Zeichen in eine 
Zeichenkette ein?"

W.S.
OP #4296222
Lesenswert?

W.S. schrieb:
> Ach, ihr streitet euch mal wieder um des Kaisers Bart.
Äh.. NÖ
> Offenbar geht es darum, daß der TO eine Art Dezimalpunkt in seine
> Zeichenfolge haben möchte,
Nein, ging es NIE!
> aber sich scheut, deswegen auf float umzusteigen.
NUR um da einen Dezimalpunkt zu erhalten und dann doch noch die zwei 
extra Zeichen dazu pfuschen? NEIN, da stell ich mich doch lieber 
neben's LCD und pinsle das mit der Hand drauf ;)

W.S. schrieb:
> Aber nochwas: Der Titel des Threads ist voll daneben.
Ämmm... JA.

> Besser: "wie füge ich ein Zeichen in eine
> Zeichenkette ein?"
NEIN, darum ging's hier NIE



Jörg W. schrieb:
> Teo D. schrieb:
>> Ich dachte, das hat wohl nichts direkt mit dem Prozessor zu tun, sondern
>> da antwortet ein einfaches Logikgatter.
>
> Das Datenblatt ist da etwas seltsam.  Zum einen suggeriert es das,
> was du da rausgelesen hast, andererseits siehe Bild, die read operation
> bekommt in den Timing-Diagrammen ganz normal ihre Timing-Werte.

Dazu kommt noch die Angabe von 0µs als Antwortzeit!? Ist aber sicher 
ein Fehler in meinem Ausdruck, da hat sich wohl ne Zahl verflüchtigt 
:)

Alles wackeln am Enable-Pin, auf die eine o. andren Art, hat erst mal 
nix genutzt.

Werde da erstmal ein vertrauenswürdigeres LCD dranhängen.
OP #4296232
Lesenswert?

Hier das verwendete Display:
http://www.pollin.de/shop/dt/NzczOTc4OTk-/Bauelemente_Bauteile/Aktive_Bauelemente/Displays/LCD_Modul_C0802_04.html
Falls da einer Erfahrung damit hat und es eventuell doch Abweichungen 
zum HD4780 gibt. Glaub ich zwar nicht, der eigentliche Fehler hat sich 
sicher über die Tastatur eingeschlichen aber die Hoffnung stirbt 
zuletzt. Da wird's sicher noch einen geben, dem ich das in die Schuhe 
schieben kann :)
OP #4296396
Lesenswert?

Hab obiges noch im Original gefunden.
Ergibt bei mir sicher >7µs. Da bisher nicht beachtet, haut das natürlich 
in meinem Progrämmchen nicht hin (höchstens 2-4µs).

Übrigens lässt mich der Original Dabla wieder glauben das da nicht am 
Enable gewackelt werden muss. Da ist noch ein Blockschaltbild zu sehen, 
in dem die Enable-Funktion als gesonderter Block dargestellt wird!?
http://www.alldatasheet.com/datasheet-pdf/pdf/63673/HITACHI/HD44780.html
Angehängte Dateien:
Moderator Persönliche Seite #4300947
Lesenswert?

Teo D. schrieb:
> Hab obiges noch im Original gefunden.

Das ist aber nur der Update des Adresszählers, falls du ihn
abfragen willst.

Eine Seite davor ist die interessante Stelle (ich bin jetzt gerade
anderweitig drüber gestolpert):
1
Table 6       Instructions
2
                                                                                     Execution Time
3
                                 Code                                                (max) (when f cp or
4
Instruction RS  R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0  Description                     f OSC is 270 kHz)
5
6
Read busy    0    1  BF  AC  AC  AC  AC  AC  AC  AC  Reads busy flag (BF)            0 µs
7
flag &                                               indicating internal operation
8
address                                              is being performed and
9
                                                     reads address counter
10
                                                     contents.

Das heißt, dass das Lesen des Busy-Flags (und des Adresszählers)
ein ganz normaler Befehl wie jeder andere ist, also RS = 0 (da Befehl
und nicht Daten), R/W = 1 (da gelesen werden soll).  Implizit ist
dabei wie bei jeder anderen Aktion ein Impuls an E.  Wesentlicher
Unterschied gegenüber allen anderen Befehlen ist, dass er keine
eigene Ausführungszeit benötigt, d. h. es darf sofort danach ein
neuer Befehl gesendet werden.

Aber einfach nur RW auf 1 setzen und RS auf 0 genügt nicht.
Moderator Persönliche Seite #4301271
Lesenswert?

So, inzwischen läuft meine eigene Implementierung auch auf dem SAMD20.

Da ich sowieso zum Vergleich noch das Diagramm meiner älteren
AVR-Implementierung auf dem LA hatte, hier dieses mal zur Illustration.
Es wird zuerst das Zeichen 'A' (0x41) ausgegeben, jeweils beide
Halbbytes.  Danach werden immer zwei Halbbytes gelesen, die das Busyflag
sowie den aktuellen Adresszähler beinhalten.  Man sieht gut, wie das
von anfangs 0x84 auf danach 0x05 weitergeht.
Angehängte Dateien:
OP #4302934
Lesenswert?

Danke für die Infos :)

Hatte bisher keinen Bock mich mit dem Mist zu beschäftigen.
Tabelle 6 klärt fast alles auf. Auf Grund meiner bisherigen 
Versuche, stellt sich mir noch die Frage:
Welches Nibble purzelt den da zuerst raus?
Ich bin bisher davon ausgegangen das es das Hi-Nbble ist. Das Dabla 
schweigt sich darüber leider aus.
Moderator Persönliche Seite #4302949
Lesenswert?

Teo D. schrieb:
> Ich bin bisher davon ausgegangen das es das Hi-Nbble ist.

Wenn du dir den LA-Trace oben ansiehst, kannst du recht gut erkennen,
dass es genau so auch ist.  Da kommt eine 4 gefolgt von einer 1 (0x41
für den Buchstaben 'A'), danach 8 - 4, 8 - 4, 0 - 5.

Ich hab' nochmal rote Striche an die relevanten Zeitpunkte gezeichnet.
Angehängte Dateien:
OP #4303038
Lesenswert?

Jörg W. schrieb:
> Da kommt eine 4 gefolgt von einer 1 (0x41
> für den Buchstaben 'A'), danach 8 - 4, 8 - 4, 0 - 5.

Jup, Danke.
(Die 1 dazwischen kommt sicher von deinem Prozi (letztes Write))

So, genug gelöchert, nu wird's Zeit mich da mal wieder selber zu 
bemühen. Hab schon einen Verdacht, wo noch so ein "ich dachte", 
zugeschlagen hat. Aber was will man sonst auch tun, wenn das Dabla nicht 
mehr hergibt :(
Muss nur noch alle größeren Werkzeuge, explizit die Hämmer, verräumen :)
Moderator Persönliche Seite #4303040
Lesenswert?

Teo D. schrieb:
> (Die 1 dazwischen kommt sicher von deinem Prozi (letztes Write))

Ja, der schaltet ja anschließend die Pins wieder auf Ausgang, damit
sie nicht „in der Luft hängen“.  In dem Moment wird dann wieder das
auf den Bus gelegt, was als letztes ausgegeben worden war.

Entscheidend ist immer nur, was zum Zeitpunkt des E-Impules passiert.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren