Rieccomi. Non vorrei aprire un'altra discussione visto che è correlata al display (@mods: magari cambiare titolo?)
Ho una paranoia sui tempi di esecuzione dei comandi del display. In pratica, dopo ogni esecuzione, per chi ha provato questi driver HD-compatibli, deve dare un impulso che fa campionare i dati sul suo fronte di discesa. Dopo di che, ammesso di aver rispettato le tempistiche, è possibile fare un'operazione di lettura sul display pe rcontrollare un bit di busy/#ready (BF).
Il display come bit BF risponde, testato all'oscilloscopio e sulla pratica: senza il controllo, è inusabile, dunque è corretto. Almeno sembra. Perché non sempre mette il cursore all'inizio, è come se saltasse un carattere, ma stiamo parlando di una cosa probabilistica che ha a che fare con errori in tempi di inizializzazione, succede 1 volta su 5.
Debuggando qua e la ho scoperto che nel mio codice, dopo lo spostamento del cursore nella posizione iniziale, la letura del BF non funziona. Lo spostamento è un'operazione lenta, che chiede >1.52ms, pensavo che il BF venisse letto: inserendo 2ms manuali si risolve tutto. Mi chiedo come mai, cosa mi sfugge.
Lo so, è un prurito, più che una necessità.
PS: l'inizializzazione manuale non la faccio, se con questa pausa funziona sempre e il display parte bene, l'inizializzazione automatica interna funziona bene. La implementerò, ora non ho voglia...
Vi lascio il main() e la funzione del display. (magari vi torna utile anche, o mi potete correggere su alcune cose :P)
main() ->
- Codice: Seleziona tutto
void main(void) {
ConfigureOscillator();
InitApp();
int i;
for(i=0; i<50; i++)
__delay_ms(2); // ASPETTO UN PO
write_comm(LCD_FUNCTIONSET|LCD_8BITMODE|LCD_2LINE|LCD_5x8DOTS);
while (write_comm(LCD_BUSYCHECK) != 0);
write_comm(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKON);
while (write_comm(LCD_BUSYCHECK) != 0);
write_comm(LCD_ENTRYMODESET|LCD_ENTRYLEFT);
while (write_comm(LCD_BUSYCHECK) != 0);
write_comm(LCD_RETURNHOME);
__delay_ms(2); // <- QUELLO MISTERIOSO!
while (write_comm(LCD_BUSYCHECK) != 0);
// uint16_t a = 0b0000000001001000; // H
write_comm(LCD_WRITEDATA|'x');
while (write_comm(LCD_BUSYCHECK) != 0);
write_comm(LCD_WRITEDATA|'u');
while (write_comm(LCD_BUSYCHECK) != 0);
write_comm(LCD_WRITEDATA|'@');
while (write_comm(LCD_BUSYCHECK) != 0);
while (1) {
} // while
}//main
La write_comm() e pulse()
- Codice: Seleziona tutto
void pulse(){
PORTCbits.RC2 = 0;
__delay_us(1); // 1us enable cycle time
PORTCbits.RC2 = 1;
__delay_us(1);
PORTCbits.RC2 = 0;
__delay_us(100);
}
bool write_comm(uint16_t comando){
if (comando == LCD_BUSYCHECK)
{
bool flag = 1;
TRISD = 0xFF; //8 bit data
PORTCbits.RC0 = comando >> 9;
PORTCbits.RC1 = comando >> 8;
pulse();
flag = PORTD & (1 << 8);
TRISD = 0x00; //8 bit data
return flag; // for checking purposes, ready flag
}
PORTD = comando;
PORTCbits.RC0 = comando >> 9; //RS
PORTCbits.RC1 = comando >> 8; // R/W
pulse();
return 0; // scarta
}
Macros (per velocità violentemente prese e modificate da una libreria di Arduino)
- Codice: Seleziona tutto
#define LCD_CLEARDISPLAY 0x0001
#define LCD_RETURNHOME 0x0002
#define LCD_ENTRYMODESET 0x0004
#define LCD_DISPLAYCONTROL 0x0008
#define LCD_CURSORSHIFT 0x0010
#define LCD_FUNCTIONSET 0x0020
#define LCD_SETCGRAMADDR 0x0040
#define LCD_SETDDRAMADDR 0x0080
#define LCD_BUSYCHECK 0x0100
#define LCD_WRITEDATA 0x0200
pps: all'inizio ho lavorato sulle porte B con LCD alimentato a 5V, dotato di tanto di pullup... ho paura a ri-testare l'ADC. I Santi mi avranno sentito.