Capire i datasheet

Ciao, sto cercando di capire come si sviluppa una libreria partendo dal datasheet di un determinato componente. Ho pensato quindi di riscrivermi la libreria per comandare l'LCD, ma sto avendo qualche problema con l'inizializzazione.

Per prima cosa vorrei inizializzare l'LCD per farlo funzionare a 4 bit. Guardando questo post, Display LCD HD44780: reset software vedo che è stata usata questa routine:

// Reset, 4 bits operation:
  delay(20);
  command(0x30);  // function set: 8 bits
  delay(10);
  command(0x30);  // function set: 8 bits
  delay(10);
  command(0x30);  // function set: 8 bits
  delay(10);
  command(0x20);  // function set: 4 bits
  
  command(0x28);  // function set: 4 bits, 1 line, 5x8 dots
  command(0x0C);  // display control: turn display on, cursor off, no blinking
  command(0x06);  // entry mode set: increment automatically, display shift, right shift
  clear();

Il problema è che non capisco come mai siano state fatte quelle scelte, perché dal datasheet , io leggo(o forse capisco?) tutt'altro.

Prima cosa, nel post viene detto questo "Eseguendo un reset software ora non c'è più alcun problema, è sufficiente inserire nel source file LiquidCrystal.cpp il reset software raccomandato alle pgg. 40 e 41 prima di inizializzare." ma a quelle pagine viene mostrata l'inizializzazione usata dal circuito di reset interno, che però funziona solo se la tensione di alimentazione ha determinate caratteristiche; mentre l'inizializzazione software viene documentata poco più sotto, a pag. 45 e 46 ed è diversa... Detto questo, i timing usati qui sopra risultano errati, o meglio mi sembrano molto più alti del necessario e anche la sequenza di comandi mi pare errata.

La mia sequenza:

digitalWrite(LCD_E, LOW); // Si assicura che Enable sia 0
digitalWrite(LCD_RS, LOW); // Abilita RS per comando
    delayMicroseconds(42000); // Dopo l'alimentazione, aspetta un minimo di 40 ms (datasheet fig.24 pag 46)
    lcdWriteH(3); // scrive 0011 su DB7,DB6,DB5,SB4 (datasheet fig.24 pag 46)
    delayMicroseconds(4500); // aspetta un min di 4,1ms (datasheet fig.24 pag 46)
    lcdWriteH(3);
    delayMicroseconds(150); // aspetta minimo 100us (datasheet fig.24 pag 46)
    lcdWriteH(3);
    lcdWriteH(2); // scrive 0010 su DB7,DB6,DB5,SB4 (datasheet fig.24 pag 46)
    // Now is 4 bit mode
    lcdSetFunction(0, 1, 0); // 4 bit, 2 lines, 5x8 fonts
    lcdSetDisplay(0,0,0); // display off,  no cursor, no blink
    lcdClear();
    lcdSetMode(1,0); // move cursor right, no display shift

Se stampo su seriale i bit che mando come comando risultano perfettamente uguali a quelli del datasheet. NOTA: dopo ogni write c'è ovviamente un impulso su Enable.

DB7|DB6|DB5|DB4
0|0|1|1|
0|0|1|1|
0|0|1|1|
0|0|1|0|
-----------------
0|0|1|0|
1|0|0|0|
-----------------
0|0|0|0|
1|0|0|0|
-----------------
0|0|0|0|
0|0|0|1|
-----------------
0|0|0|0|
0|1|1|0|
-----------------

Non capisco però come mai non funziona, lo schermo si comporta in modo random, eppure mi sembra di aver seguito quello che il datasheet dice. Le funzioni che uso per mandare i comandi o dati all'lcd sono corrette, perché se uso l'inizializzazione della libreria LiquidCrystal, poi posso scrivere quello che voglio sull'lcd con i miei metodi.

Guardando la libreria LiquidCrystal, vedo che l'inizializzazione è simile alla mia, per i 4bit:

    // this is according to the hitachi HD44780 datasheet
    // figure 24, pg 46

    // we start in 8bit mode, try to set 4 bit mode
    write4bits(0x03);
    delayMicroseconds(4500); // wait min 4.1ms

    // second try
    write4bits(0x03);
    delayMicroseconds(4500); // wait min 4.1ms
    
    // third go!
    write4bits(0x03); 
    delayMicroseconds(150);

    // finally, set to 4-bit interface
    write4bits(0x02);

anche qui non capisco alcune scelte fatte:

  • Come mai aspetta per ben due volte 4500us quando invece il datasheet dice di attendere prima almeno 4100us e poi solo 100us?
  • Coma mai dopo il terzo comando 0x3 aspetta nuovamente 150us quando il datasheet invece non fa riferimento a nessun tempo di attesa prima di mandare il comando 0x2?

Con questo post non voglio assolutamente dire che le scelte fatte qui sopra siano sbagliate, anzi, voglio proprio capire come mai siano state fatte, da dove posso capire leggendo solamente la documentazione dell'HD44780 come poter prendere certe decisioni invece che altre.

Probabilmente mi sta sfuggendo qualcosa...

Trovato il problema... la mia funzione che scriveva i comandi non metteva a LOW il segnale RS, per cui veniva sempre interpretato come dato. Ora funziona, rimane comunque il fatto che non capisco come mai siano state fate quelle scelte, io reputo la mia routine la più corretta, o almeno la più corretta se consideriamo il datasheet.

ciao

ti rispondo per la parte timing: sicuramente sono stati scelti valori più "sicuri" per la grande eterogeneità di controller per display che si trovano sul mercato e che si dicono "hitachi compatibili". A volte infatti ci si accorge che rispettando "alla lettera" i timing dati nel datasheet non si ottengono i comportamenti voluti.

Ciao, ti ringrazio, una risposta più che ragionevole.

Il HD44780 avrebbe un Bit che segnala che é ancora occupato per esempio per eseguire un reset. Visto che per risparmiare PIN non si usa il pin che definise lettura/scrittura non si puó sapere lo stato di quel PIN. Per questo si aspetta un tempo sicuro perche il HD44780 abbia eseguito il comando. Ciao Uwe