He estado tratando de inicializar mi LCD durante aproximadamente una semana, y me avergüenza decir que hasta ahora no he tenido éxito. He hecho esto en el pasado, y recuerdo que fue un poco complicado obtener la secuencia de inicialización correcta, pero en este punto creo que he examinado completamente la implementación y simplemente no funciona.
Configuración:
Aquí hay cosas que he hecho hasta ahora para probar:
for
Las rutinas de temporización son bucles semi "calibrados".Sin embargo, después de todo esto, ¡no puedo mostrar nada en la pantalla LCD! Asi que aqui están mis preguntas:
Mi código se ve así:
void InitializeLcd()
{
DelayTicks( 10000);
// 4 bit interface, 2 lines, 5x8 characters
// the spec sheet shows the 0x20 part of 0x28 getting sent an extra time
// so I used a special function to deal with this case. This just sends
// the 0x20 part and ignores the 0x08 part.
SendLcdUpperNibble( COMMAND, 0x28);
SendLcdByte( COMMAND, 0x28);
DelayTicks( 1000);
// Display on, cursor off, blink off
SendLcdByte( COMMAND, 0x0C);
DelayTicks( 1000);
// clear display
ClearLcd();
// Entry mode set - increment cursor, no display shift
SendLcdByte( COMMAND, 0x02);
DelayTicks( 1000);
// Set write to DDRAM mode since we'll just be sending data from now on
SendLcdByte( DATA, 0x48);
SendLcdByte( DATA, 0x65);
SendLcdByte( DATA, 0x6C);
SendLcdByte( DATA, 0x6C);
SendLcdByte( DATA, 0x6F);
}
void ClearLcd()
{
// Clear display
SendLcdByte( COMMAND, 0x01);
DelayTicks( 1000);
}
void SetRS( int value)
{
if( value == 0)
P2OUT &= ~RS;
else
P2OUT |= RS;
}
void SetRW( int value)
{
if( value == 0)
P2OUT &= ~RW;
else
P2OUT |= RW;
}
void SetE( int value)
{
if( value == 0)
P1OUT &= ~E;
else
P1OUT |= E;
}
void DelayMs( int delay)
{
int ctr;
int ms = delay * 100;
for( ctr=0; ctr<ms; ctr++);
}
void DelayTicks( int ticks)
{
int ctr;
for( ctr=0; ctr<ticks; ctr++);
}
void SendLcdByte( unsigned char command_0_or_data_1, unsigned char command)
{
SendLcdUpperNibble( command_0_or_data_1, command);
// send the lower nibble next
// special thank you to ToyBuilder for catching my missed bit-shift in the following line
// I also had the mask on P1OUT incorrect, presumably because I messed up the command mask and just made it match that.
P1OUT = ((command & 0x0F) << 4) | (P1OUT & 0x0F);
Strobe( command_0_or_data_1);
}
void SendLcdUpperNibble( unsigned char command_0_or_data_1, unsigned char upper_nibble)
{
P1OUT = (upper_nibble & 0xF0) | (P1OUT & 0x0F);
Strobe( command_0_or_data_1);
}
void Strobe( unsigned char command_0_or_data_1)
{
SetRS( command_0_or_data_1);
SetRW( 0);
DelayTicks( 1000);
SetE( 1);
DelayTicks( 1000);
SetE( 0);
}
Lo único que puedo decir es que parece que la pantalla LCD parpadea cuando paso por encima de SendLcdByte y le envío datos de caracteres. Cuando analizo todo, parece que estoy volteando los bits correctamente...
EDITAR: soldé una nueva pantalla LCD, y esta vez intenté dejar los pines de datos no utilizados (D0-D3) desconectados (es decir, flotando). No hubo diferencia. La pantalla LCD todavía parpadea cuando inicializo. Ahora estoy esperando 100 ms para todas las demoras, incluida una demora cuando se enciende la luz estroboscópica E. También desconecté el Vcc proveniente de la sección FET del Launchpad y ahora solo estoy alimentando el MSP430 y la pantalla LCD desde la fuente de alimentación de mi laboratorio.
EDICIÓN n. ° 2: fui a una pantalla LCD de 3.3 V y todo comenzó a funcionar mágicamente. Gracias a ToyBuilder por detectar un estúpido error de código cuando estaba depurando con la pantalla LCD de 5V. Después del intercambio, la pantalla LCD se inicializó correctamente. Actualmente estoy mostrando basura en lugar de "Hola", pero eso no está relacionado con esta pregunta.
EDICIÓN n. ° 3: encontré mi error de visualización: estaba enviando 0x06 para el modo de entrada en lugar de 0x02. No estoy seguro de por qué hice eso, debe haber sido un error tipográfico.
Oh, duh, no leí tu código cuidadosamente, tu envío SendLcdByte es incorrecto:
void SendLcdByte( unsigned char command_0_or_data_1, unsigned char command)
{
SendLcdUpperNibble( command_0_or_data_1, command);
// send the lower nibble next
// AS WRITTEN:
P1OUT = (command & 0x0F) | (P1OUT & 0xF0);
// SHOULD BE:
P1OUT = ((command & 0x0F) << 4) | (P1OUT & 0xF0);
Strobe( command_0_or_data_1);
}
P1OUT = ((command & 0x0F) << 4) | (P1OUT & 0x0F);
Desearía poder poner una excusa, como "soy disléxico", pero no puedo. Verifiqué los bits del bus de datos en el osciloscopio, pero necesito volver a verificar los bits que se activan porque todavía no funciona. Ahora estoy probando en la propia pantalla LCD, en lugar de pinchar la placa de prueba.Vuelva a verificar los voltajes de salida alto/bajo de la señal del MSP430 y los mínimos para las entradas en la pantalla LCD.
Otra cosa es si está golpeando un poco demasiado rápido: su lista de fuentes no muestra cómo está jugando con los datos y las señales E. Si gira E demasiado pronto después de cargar los bits de datos, no funcionará. Si no mantiene presionado E el tiempo suficiente para que la pantalla LCD enganche los datos entrantes, no funcionará. Intente agregar un retraso de tiempo entre escribir D0-D7, y luego entre afirmar y luego anular la afirmación de la línea E.
Supongo que las líneas se usan estrictamente para las pantallas LCD, por lo que no hay problemas de tiempo de espera. Si también usa las líneas como un bus para otros dispositivos, deberá asegurarse de que sus datos se retengan el tiempo suficiente antes de que el bus se use para otras cosas.
También una cosa que me engañó una vez fue que la luz de fondo era tan baja que no podía ver que estaba funcionando.
El soporte técnico de Newhaven Display me recomendó reemplazar la pantalla LCD y volver a intentarlo. Es posible que lo haya dañado durante la configuración inicial, así que veremos cómo va. Publicaré los resultados aquí.
¿Será posible que tengas los pines conectados al revés?
De vez en cuando, me encontraba con pantallas LCD con los números de pin invertidos en la pieza misma o en la hoja de datos o en ambos.
Sé que esto puede parecer un "¿Está enchufado?" pregunta - pero personalmente me ha pillado por sorpresa con esto.
* EDITAR *
Uf, en mi comentario anterior, dije que escribiera 0x80; lo que pretendía era que tratara de mantener el valor 0x40 o 0x60 en las líneas de datos.
Si resulta que los pines están invertidos, escribir 0x40 aplicaría energía y tierra a través de los pines de datos a la pantalla LCD, lo que le daría la oportunidad de reiniciarse automáticamente. Esto es posible porque un módulo LCD de caracteres típico solo consume de 1 a 5 mA de corriente, dentro de la capacidad de conducción de la mayoría de las salidas.
Lo que sospecho que puede estar sucediendo es que está escribiendo algunos valores 0x6X y 0x4X en su pantalla LCD durante un breve período de tiempo mientras inicializa la pantalla LCD, y que la pantalla LCD se está encendiendo durante ese breve período; pero cuando comienza a escribir otros valores, efectivamente lo está desactivando.
* EDITAR 2 *
Mientras buscaba la hoja de datos de otra pantalla LCD para verificar los requisitos actuales, noté que es posible que haya intercambiado sus pines Vcc y Vcontrast. ¡Asegúrate de comprobar eso también!
Acabo de mirar y vi en la hoja de datos NHT-C0220AZ-FWS-FTW (donde obtuvo su dibujo esquemático arriba) que el contraste es el pin 2 y el voltaje de suministro es el pin 3. Que es el reverso de las partes de Vishay y Optrex donde el contraste es el pin 3 y el voltaje de suministro es el pin 2.
Bueno, diablos, incluso el NHD-0420DZ-FSW-FBW de NewHaven tiene contraste en el pin 3 y suministro en el pin 2.
dave