¿Cómo comunicarme "sin tapujos" con un LCD compatible con HD44780?

1

Tengo una pantalla lcd compatible con HD44780 (QC1602A). Investigué mucho y encontré algunas cosas útiles, pero ninguna de ellas parecía haber funcionado realmente. No estoy usando ninguna biblioteca lcd (C), solo la libra wiringPi para activar / desactivar los pines (RaspberryPi).

Para probar mi lcd escribí este programa:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiringPi.h>


#define P0  0
#define P1  1
#define RS  2//RS Pin
#define En  3//Data Enable
#define DB4 4//Data Bus DB4-DB7 (4-bit)
#define DB5 5
#define DB6 6
#define DB7 7
#define C0 10//Yellow Led


void waitAndPrint(unsigned int sec)
{
    while(sec) {
        printf("%d", sec);
        printf(" Second(s)\r");
        delay(1000);
        sec--;
    }
}

void writeToBus(char var1, char var2)//Hex value. writeToBus(lowNybble,highNybble)
{
    int binary1[4];
    switch(var1) {
        case 0x0: binary1[0]=0; binary1[1]=0; binary1[2]=0; binary1[3]=0; break;
        case 0x1: binary1[0]=0; binary1[1]=0; binary1[2]=0; binary1[3]=1; break;
        case 0x2: binary1[0]=0; binary1[1]=0; binary1[2]=1; binary1[3]=0; break;
        case 0x3: binary1[0]=0; binary1[1]=0; binary1[2]=1; binary1[3]=1; break;
        case 0x4: binary1[0]=0; binary1[1]=1; binary1[2]=0; binary1[3]=0; break;
        case 0x5: binary1[0]=0; binary1[1]=1; binary1[2]=0; binary1[3]=1; break;
        case 0x6: binary1[0]=0; binary1[1]=1; binary1[2]=1; binary1[3]=0; break;
        case 0x7: binary1[0]=0; binary1[1]=1; binary1[2]=1; binary1[3]=1; break;
        case 0x8: binary1[0]=1; binary1[1]=0; binary1[2]=0; binary1[3]=0; break;
        case 0x9: binary1[0]=1; binary1[1]=0; binary1[2]=0; binary1[3]=1; break;
        case 0xA: binary1[0]=1; binary1[1]=0; binary1[2]=1; binary1[3]=0; break;
        case 0xB: binary1[0]=1; binary1[1]=0; binary1[2]=1; binary1[3]=1; break;
        case 0xC: binary1[0]=1; binary1[1]=1; binary1[2]=0; binary1[3]=0; break;
        case 0xD: binary1[0]=1; binary1[1]=1; binary1[2]=0; binary1[3]=1; break;
        case 0xE: binary1[0]=1; binary1[1]=1; binary1[2]=1; binary1[3]=0; break;
        case 0xF: binary1[0]=1; binary1[1]=1; binary1[2]=1; binary1[3]=1; break;
    }
    int binary2[4];
    switch(var2) {
        case 0x0: binary2[0]=0; binary2[1]=0; binary2[2]=0; binary2[3]=0; break;
        case 0x1: binary2[0]=0; binary2[1]=0; binary2[2]=0; binary2[3]=1; break;
        case 0x2: binary2[0]=0; binary2[1]=0; binary2[2]=1; binary2[3]=0; break;
        case 0x3: binary2[0]=0; binary2[1]=0; binary2[2]=1; binary2[3]=1; break;
        case 0x4: binary2[0]=0; binary2[1]=1; binary2[2]=0; binary2[3]=0; break;
        case 0x5: binary2[0]=0; binary2[1]=1; binary2[2]=0; binary2[3]=1; break;
        case 0x6: binary2[0]=0; binary2[1]=1; binary2[2]=1; binary2[3]=0; break;
        case 0x7: binary2[0]=0; binary2[1]=1; binary2[2]=1; binary2[3]=1; break;
        case 0x8: binary2[0]=1; binary2[1]=0; binary2[2]=0; binary2[3]=0; break;
        case 0x9: binary2[0]=1; binary2[1]=0; binary2[2]=0; binary2[3]=1; break;
        case 0xA: binary2[0]=1; binary2[1]=0; binary2[2]=1; binary2[3]=0; break;
        case 0xB: binary2[0]=1; binary2[1]=0; binary2[2]=1; binary2[3]=1; break;
        case 0xC: binary2[0]=1; binary2[1]=1; binary2[2]=0; binary2[3]=0; break;
        case 0xD: binary2[0]=1; binary2[1]=1; binary2[2]=0; binary2[3]=1; break;
        case 0xE: binary2[0]=1; binary2[1]=1; binary2[2]=1; binary2[3]=0; break;
        case 0xF: binary2[0]=1; binary2[1]=1; binary2[2]=1; binary2[3]=1; break;
    }

    digitalWrite(DB4, binary2[0]);
    digitalWrite(DB5, binary2[1]);
    digitalWrite(DB6, binary2[2]);
    digitalWrite(DB7, binary2[3]);
    digitalWrite(En, 1);
    delay(20);
    digitalWrite(En, 0);
    digitalWrite(DB4, binary1[0]);
    digitalWrite(DB5, binary1[1]);
    digitalWrite(DB6, binary1[2]);
    digitalWrite(DB7, binary1[3]);
    digitalWrite(En, 1);
    delay(20);
    digitalWrite(En, 0);
    digitalWrite(DB4, 0);
    digitalWrite(DB5, 0);
    digitalWrite(DB6, 0);
    digitalWrite(DB7, 0);
    delay(20);
}

// suggested wrapper method for Mattia_98's writeToBus function -- MarkU
void sendHD44780command(char data)
{
    digitalWrite(RS, 0);//Turn RS Mode off
    writeToBus(
            ((data >> 0) & 0x0F),    // low nybble is send second
            ((data >> 4) & 0x0F)     // high nybble is sent first
        );
}
// suggested wrapper method for Mattia_98's writeToBus function -- MarkU
void sendHD44780data(char data)
{
    digitalWrite(RS, 1);//Turn RS Mode on
    writeToBus(
            ((data >> 0) & 0x0F),    // low nybble is send second
            ((data >> 4) & 0x0F)     // high nybble is sent first
        );
}

void initHD44780_4bit(void)
{
    // D7-D4 connected, D3-D0 no connect. High nybble is sent first. Function set DL=0.

    // HD44780 command 0x30-0x33 = Function set: DL=1_8 bit interface, N=0_1 line,  F=0_5x7 font
    sendHD44780command(0x30); 

    // HD44780 command 0x20-0x23 = Function set: DL=0_4 bit interface, N=0_1 line,  F=0_5x7 font
    sendHD44780command(0x20); 

    // HD44780 command 0x28-0x2B = Function set: DL=0_4 bit interface, N=1_2 lines, F=0_5x7 font
    sendHD44780command(0x28); //4-bit, 2 line, 5x7 dots

    // HD44780 command 0x0C = Display On/Off Control: D=1_display enabled, C=0_hide cursor, B=0_unblinking cursor
    sendHD44780command(0x0C); // Display ON cursor OFF

    // HD44780 command  0x06 = Entry mode set: I/D=1_increment, S=0_noShift no display shift
    sendHD44780command(0x06); // Set entry mode (Auto increment)

    // HD44780 command  0x80-0xBF = display line 1
    sendHD44780command(0x80); // Bring cursor to line 1
}

int main(void)
{
    printf("|------------------------|\n");
    printf("|-----LCD HelloWorld-----|\n");
    printf("|------By Mattia_98------|\n");
    printf("|--------GPL 2015--------|\n");
    printf("|------------------------|\n");

    printf("Initializing... ");
    setbuf(stdout, NULL);//No buffer
    wiringPiSetup();//WPi Setup-Method
    pinMode(P0, OUTPUT);//Set Input or Output
    pinMode(P1, OUTPUT);
    pinMode(RS, OUTPUT);
    pinMode(En, OUTPUT);
    pinMode(DB4, OUTPUT);
    pinMode(DB5, OUTPUT);
    pinMode(DB6, OUTPUT);
    pinMode(DB7, OUTPUT);
    pinMode(C0, OUTPUT);
    digitalWrite(P0, 0);//Put everything to Off
    digitalWrite(P1, 0);
    digitalWrite(RS, 0);
    digitalWrite(En, 0);
    digitalWrite(DB4, 0);
    digitalWrite(DB5, 0);
    digitalWrite(DB6, 0);
    digitalWrite(DB7, 0);
    digitalWrite(C0, 0);
    initHD44780_4bit();//LCD Init-Method
    printf("Done!\n");


    //Send 'Hello world!' to the lcd
    sendHD44780data('H');
   sendHD44780data('e');
   sendHD44780data('l');
   sendHD44780data('l');
   sendHD44780data('o');
   sendHD44780data(' ');
   sendHD44780data('w');
   sendHD44780data('o');
   sendHD44780data('r');
   sendHD44780data('l');
   sendHD44780data('d');
   sendHD44780data('!');

    waitAndPrint(10);

    return 0 ;
}

No da ningún error pero no hace nada. Por supuesto que responderé todas las preguntas que me hagas;)

Las hojas de datos que encontré dicen que es un LCD de 5V.

Cuando está activada, la primera fila se llena con cuadrados. Después de ejecutar el código anterior, ambas filas se llenan de cuadrados.

El código anterior ahora muestra algunos caracteres aleatorios.

    
pregunta Mattia_98

1 respuesta

1

A su código le faltan algunos comandos de inicialización.

lcd_init de enlace en realidad envía esta secuencia:

void initHD44780_4bit(void)
{
    // D7-D4 connected, D3-D0 no connect. High nybble is sent first. Function set DL=0.

    // HD44780 command 0x30-0x33 = Function set: DL=1_8 bit interface, N=0_1 line,  F=0_5x7 font
    sendHD44780command(0x30); 

    // HD44780 command 0x20-0x23 = Function set: DL=0_4 bit interface, N=0_1 line,  F=0_5x7 font
    sendHD44780command(0x20); 

    // HD44780 command 0x28-0x2B = Function set: DL=0_4 bit interface, N=1_2 lines, F=0_5x7 font
    sendHD44780command(0x28); //4-bit, 2 line, 5x7 dots

    // HD44780 command 0x0C = Display On/Off Control: D=1_display enabled, C=0_hide cursor, B=0_unblinking cursor
    sendHD44780command(0x0C); // Display ON cursor OFF

    // HD44780 command  0x06 = Entry mode set: I/D=1_increment, S=0_noShift no display shift
    sendHD44780command(0x06); // Set entry mode (Auto increment)

    // HD44780 command  0x80-0xBF = display line 1
    sendHD44780command(0x80); // Bring cursor to line 1
}

Tenga en cuenta que en "modo nybble" (interfaz de 4 bits), primero se envía el nybble más significativo. Por lo tanto, te sugiero que intercambies tus argumentos de writeToBus, poniendo primero el MSB ... que facilita la comprensión al leer la hoja de datos del HD44780.

// suggested wrapper method for Mattia_98's writeToBus function -- MarkU
void sendHD44780command(char data)
{
    digitalWrite(RS, 0);//Turn RS Mode off
    writeToBus(
            ((data >> 0) & 0x0F),    // low nybble is send second
            ((data >> 4) & 0x0F)     // high nybble is sent first
        );
}
// suggested wrapper method for Mattia_98's writeToBus function -- MarkU
void sendHD44780data(char data)
{
    digitalWrite(RS, 1);//Turn RS Mode on
    writeToBus(
            ((data >> 0) & 0x0F),    // low nybble is send second
            ((data >> 4) & 0x0F)     // high nybble is sent first
        );
}

Luego, después de la llamada inicial a initHD44780_4bit() , deberías enviar algunos datos, para que puedas ver si la pantalla realmente funciona.

// send test message to HD44780
void helloWorld(void)
{
    sendHD44780data('H');
    sendHD44780data('e');
    sendHD44780data('l');
    sendHD44780data('l');
    sendHD44780data('o');
    sendHD44780data(' ');
    sendHD44780data('w');
    sendHD44780data('o');
    sendHD44780data('r');
    sendHD44780data('l');
    sendHD44780data('d');
    sendHD44780data('!');
}

Esto debería ser suficiente para que comiences. Saludos - Mark

    
respondido por el MarkU

Lea otras preguntas en las etiquetas