Tengo un proyecto en el que necesito usar un módulo LCD, así que empecé a reflexionar con uno (1602A).
Hasta ahora lo he conectado con mi microcontrolador, que es un Atmega168PA, y he escrito un código de inicialización basado en las instrucciones encontradas here .
Creo que he hecho exactamente lo que se dice en esa instrucción (estoy tratando de usar una interfaz de 4 bits), pero todavía no he conseguido que la cosa funcione correctamente.
A mi parecer, por alguna razón, el módulo LCD no se inicializa correctamente, ya que después de que tanto la MCU como la LCD se hayan encendido, solo veo una (primera) línea llena de caracteres de puntos completos (0xFF) y la segunda línea es en blanco, aunque la pantalla se debe borrar durante la inicialización y el cursor debe estar visible.
He incluido mi código a continuación:
#ifndef F_CPU
#define F_CPU 8000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
void lcdLatchEnable (void)
{
PORTC |= (1<<4); // enable latch pin
_delay_us(2); // wait specified time
PORTC &= ~(1<<4); //disable latch pin
}
void lcdWriteNibble (uint8_t byte) // set data line according to upper nibble in function parameter 'data'
{
if (byte & 0x10) // copy fourth bit value on the output pin
PORTC |= (1<<0);
else
PORTC &=~(1<<0);
if (byte & 0x20) // copy fifth bit value on the output pin
PORTC |= (1<<1);
else
PORTC &=~(1<<1);
if (byte & 0x40) // copy sixth bit value on the output pin
PORTC |= (1<<2);
else
PORTC &=~(1<<2);
if (byte & 0x80) // copy seventh bit value on the output pin
PORTC |= (1<<3);
else
PORTC &=~(1<<3);
}
void lcdSendByte(uint8_t byte)
{
lcdWriteNibble(byte); // send upper nibble
lcdLatchEnable(); // latch the upper nibble
byte <<= 4; // shift bits in byte left 4 positions so lower nibble would be sent next
lcdWriteNibble(byte); // send lower nibble
lcdLatchEnable(); // latch the upper nibble
}
void lcdSendNibble(uint8_t byte)
{
lcdWriteNibble(byte); // write nibble to output pins
lcdLatchEnable(); // latch the values into LCD module
}
void lcdInit (void)
{
PORTC &= ~(1<<5); // configure LCD module into instruction mode (R/S line = 0)
_delay_ms(150); // wait more than 100ms after power on
lcdWriteNibble(0x30); // special case function set
lcdLatchEnable(); // latch in the values
_delay_ms(5); // wait more than 4.1ms
lcdWriteNibble(0x30); // special case function set
lcdLatchEnable(); // latch in the values
_delay_ms(1); // wait more than 100us
lcdWriteNibble(0x30); // special case function set
lcdLatchEnable(); // latch in the values
_delay_ms(1); // wait more than 100us
lcdWriteNibble(0x20); // initial function set to change interface
lcdLatchEnable(); // latch in the values
_delay_ms(1); // wait more than 100us
lcdSendByte(0x28); // send function set
_delay_ms(1); // wait more than 53us
lcdSendByte(0x08); // display off, cursor off, blinking off
_delay_ms(1); // wait more than 53us
lcdSendByte(0x01); // clear display;
_delay_ms(5); // wait more than 3ms
lcdSendByte(0x06); // Entry mode set to increment and shift off
_delay_ms(10); // wait more than 53us
lcdSendByte(0x0C); // display on, cursor on
}
int main(void)
{
DDRC |= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5); // configure pins as output for LCD module communication
PORTC = 0x00; // make sure that all the pins are configured as low
_delay_ms(150);
lcdInit();
_delay_ms(100);
lcdSendChar(0x30);
while(1)
{
}
}
Y una imagen de la pantalla debe inicializarse e imprimirse con el carácter 48:
ACTUALIZACIÓN:
Esquemaagregadodemicableado: