Atmega32 + LCD no muestra nada

3

Estoy intentando escribir un programa en C para mostrar texto en este LCD, por alguna razón no muestra nada en absoluto. Seguí el este tutorial en YouTube y usé mi libro escolar (recientemente empecé a estudiar eléctrico. ingeniería), pero incluso después de copiar exactamente lo que estaba allí (a excepción de los puertos y esas cosas) todavía no funcionó.

Esperaba que alguien de aquí pudiera echar un vistazo rápido y ver qué está pasando. No sé qué hacer más.

#include <avr/io.h>
#include <util/delay.h>

//These are the DDR and PORT associated with the 8 bits data send/received
#define LCD_DDR             DDRC
#define LCD_PORT            PORTC

//LCD_COMMAND_DDR if you will, so with the three pins Enable/RegisterSelect/ReadWrite
#define LCD_CMD_DDR         DDRD
#define LCD_CMD_PORT        PORTD
#define LCD_CMD_RS          PIND0
#define LCD_CMD_RW          PIND1
#define LCD_CMD_E           PIND2

#define LED_PIN             PIND7

//Just some defenitions to make it easier for me
#define LCD_CLEAR_DISPLAY   0b00000001
#define LCD_CURSOR_HOME     0b00000010
//Enable display/cursor/blink
#define LCD_DISP_ALL        0b00001111
//Set it to 8 bits mode
#define LCD_SET_MODE        0b00111000
// Set Auto-increment noshift
#define LCD_SET_AI_NOSHIFT  0b00000110

void initializeLCD();
void commandLCD(unsigned char d);
void putcLCD(unsigned char c);
void checkIfBusy();
void switchEnable();

int main(void)
{
initializeLCD();

putcLCD(0x41);
putcLCD('A');
putcLCD('L');
putcLCD('L');
putcLCD('O');
}

void initializeLCD()
{
LCD_DDR = 0xFF;
LCD_PORT = 0x00;

LCD_CMD_DDR = 0xFF;
LCD_CMD_PORT = 0x00;

_delay_ms(200);

commandLCD(LCD_SET_MODE);
commandLCD(LCD_DISP_ALL);
commandLCD(LCD_CLEAR_DISPLAY);
commandLCD(LCD_SET_AI_NOSHIFT);
}

void checkIfBusy()
{
    //Set LCD DDR to input
LCD_DDR = 0x00;
    //Set RegisterSelect low so the 'inner registry' is selected (not the characters on the screen)
LCD_CMD_PORT &= ~(1 << LCD_CMD_RS);
    //Set ReadWrite high so I can read data
LCD_CMD_PORT |= 1 << LCD_CMD_RW;

while(LCD_PORT >= 0x80)
{
    switchEnable();
}

    //ReadWrite back to low so I can write to it again
LCD_CMD_PORT &= ~(1 << LCD_CMD_RW);
    //DDR back to output
LCD_DDR = 0xFF;
}

void switchEnable()
{
    //Enable high
LCD_CMD_PORT |= (1 << LCD_CMD_E);
asm volatile ("nop"); //delay a bit (tried it also with _delay_ms(200);
asm volatile ("nop");
    //Enable low
LCD_CMD_PORT &= ~(1 << LCD_CMD_E);
}

void commandLCD(unsigned char d)
{
    //delay untill busyflag is off
checkIfBusy();
    //put command to the port
LCD_PORT = d;
    //set both RegisterSelect and ReadWrite low
LCD_CMD_PORT &= ~((1 << LCD_CMD_RS)|(1 << LCD_CMD_RW));
switchEnable();
    // Clear the port
LCD_PORT = 0x00;
_delay_ms(2);
}

void putcLCD(unsigned char c)
{
    //see if we're done
checkIfBusy();
    // put character to port
LCD_PORT = c;
    //Set ReadWrite low
LCD_CMD_PORT &= ~(1 << LCD_CMD_RW);
    //Set RegisterSelect high
LCD_CMD_PORT |= (1 << LCD_CMD_RS);
switchEnable();
LCD_PORT = 0x00;
_delay_ms(2);
}

Después de la respuesta a continuación:

int main(void)
{
LCD_DDR = 0xFF;
LCD_PORT = 0x00;

LCD_CMD_DDR = 0xFF;
LCD_CMD_PORT = 0x00;
initializeLCD();

putcLCD(0x41);
}


void initializeLCD()
{
_delay_ms(15);

initCommandLCD(0b00110000);
_delay_ms(5);
initCommandLCD(0b00110000);
_delay_ms(100);
initCommandLCD(0b00110000);
_delay_ms(100);
initCommandLCD(0b00111000);
_delay_ms(100);
initCommandLCD(0b00001000);
_delay_ms(100);
initCommandLCD(0b00000001);
_delay_ms(100);
initCommandLCD(0b00000111);
_delay_ms(100);
}

void checkIfBusy()
{
LCD_DDR = 0;
LCD_CMD_PORT |= 1 << LCD_CMD_RW;
LCD_CMD_PORT &= ~(1 << LCD_CMD_RS);

while(LCD_PORT >= 0x80)
{
    switchEnable();
}

LCD_DDR = 0xFF;
}

void switchEnable()
{
LCD_CMD_PORT |= (1 << LCD_CMD_E);
_delay_ms(2);
LCD_CMD_PORT &= ~(1 << LCD_CMD_E);
}

void initCommandLCD(unsigned char d)
{
LCD_PORT = d;
    LCD_CMD_PORT &= ~((1 << LCD_CMD_RW)|(1 << LCD_CMD_RS));
    switchEnable();
    LCD_PORT = 0;
}

void commandLCD(unsigned char d)
{
checkIfBusy();
    initCommandLCD(d);
}

void putcLCD(unsigned char c)
{
checkIfBusy();
LCD_PORT = c;
LCD_CMD_PORT &= ~(1 << LCD_CMD_RW);
LCD_CMD_PORT |= (1 << LCD_CMD_RS);
switchEnable();
LCD_PORT = 0;
}
    
pregunta AmazingDreams

2 respuestas

0

Tuve que deshabilitar JTAG en la parte superior de mi main:

MCUCSR = (1<<JTD);
MCUCSR = (1<<JTD);

Funciona ahora, mi código es bueno, no necesito inicializar mi LCD manualmente. Simplemente borra la pantalla y los comandos opcionales.

Código final:

#include <avr/io.h>
#include <util/delay.h>
#include <math.h>

#define LCD_DDR             DDRC
#define LCD_PORT            PORTC

#define LCD_CMD_DDR         DDRD
#define LCD_CMD_PORT        PORTD
#define LCD_CMD_RS          PIND0
#define LCD_CMD_RW          PIND1
#define LCD_CMD_E           PIND2

#define LED_PIN             PIND7

void initializeLCD();
void commandLCD(unsigned char d);
void putcLCD(unsigned char c, unsigned char c1);
void checkIfBusy();
void switchEnable();
void putsLCD();
void lcdNewLine();
void resetLCD();

int currentLine = 0;
int currentChar = 0;

int main(void)
{
MCUCSR = (1 << JTD);
MCUCSR = (1 << JTD);

LCD_DDR = 0xFF;
LCD_PORT = 0x00;

LCD_CMD_DDR = 0xFF;
LCD_CMD_PORT = 0x00;

initializeLCD();

while(1)
{
    putsLCD("Printstuff");
    _delay_ms(3000);
}
}

void initializeLCD()
{
_delay_ms(15);

commandLCD(0x01);
commandLCD(0b00111100);
}

void checkIfBusy()
{
LCD_DDR = 0x00;
LCD_CMD_PORT |= 1 << LCD_CMD_RW;
LCD_CMD_PORT &= ~(1 << LCD_CMD_RS);

while(LCD_PORT >= 0x80)
{
    switchEnable();
}

LCD_DDR = 0xFF;
}

void switchEnable()
{
LCD_CMD_PORT |= (1 << LCD_CMD_E);
_delay_ms(2);
LCD_CMD_PORT &= ~(1 << LCD_CMD_E);
}

void commandLCD(unsigned char d)
{
checkIfBusy();
LCD_PORT = d;
LCD_CMD_PORT &= ~((1 << LCD_CMD_RW)|(1 << LCD_CMD_RS));
switchEnable();
LCD_PORT = 0;
}

void putcLCD(unsigned char c, unsigned char c1)
{
if(c == '\n')
{
    lcdNewLine();
    return;
}

if (currentChar >= 20 && c != ' ' && c1 != ' ' && c1 != '
MCUCSR = (1<<JTD);
MCUCSR = (1<<JTD);
') { currentChar = 0; putcLCD('-', ' '); lcdNewLine(); } if (c == ' ' && currentChar == 1) return; checkIfBusy(); LCD_PORT = c; LCD_CMD_PORT &= ~(1 << LCD_CMD_RW); LCD_CMD_PORT |= (1 << LCD_CMD_RS); switchEnable(); LCD_PORT = 0x00; currentChar++; } void resetLCD() { checkIfBusy(); commandLCD(0x01); currentChar = 1; currentLine = 1; } void lcdNewLine() { char line = 20; switch(currentLine) { case 1: line *= 2; break; case 2: line *= 1; break; case 3: line *= 4.2; break; } line += 0b10000000; checkIfBusy(); commandLCD(line); currentLine += 1; currentChar = 1; } void putsLCD(unsigned char *s) { checkIfBusy(); resetLCD(); int maxCount = strlen(s); int i; for(i = 0; i < maxCount; i++) { if(s[i] == '
#include <avr/io.h>
#include <util/delay.h>
#include <math.h>

#define LCD_DDR             DDRC
#define LCD_PORT            PORTC

#define LCD_CMD_DDR         DDRD
#define LCD_CMD_PORT        PORTD
#define LCD_CMD_RS          PIND0
#define LCD_CMD_RW          PIND1
#define LCD_CMD_E           PIND2

#define LED_PIN             PIND7

void initializeLCD();
void commandLCD(unsigned char d);
void putcLCD(unsigned char c, unsigned char c1);
void checkIfBusy();
void switchEnable();
void putsLCD();
void lcdNewLine();
void resetLCD();

int currentLine = 0;
int currentChar = 0;

int main(void)
{
MCUCSR = (1 << JTD);
MCUCSR = (1 << JTD);

LCD_DDR = 0xFF;
LCD_PORT = 0x00;

LCD_CMD_DDR = 0xFF;
LCD_CMD_PORT = 0x00;

initializeLCD();

while(1)
{
    putsLCD("Printstuff");
    _delay_ms(3000);
}
}

void initializeLCD()
{
_delay_ms(15);

commandLCD(0x01);
commandLCD(0b00111100);
}

void checkIfBusy()
{
LCD_DDR = 0x00;
LCD_CMD_PORT |= 1 << LCD_CMD_RW;
LCD_CMD_PORT &= ~(1 << LCD_CMD_RS);

while(LCD_PORT >= 0x80)
{
    switchEnable();
}

LCD_DDR = 0xFF;
}

void switchEnable()
{
LCD_CMD_PORT |= (1 << LCD_CMD_E);
_delay_ms(2);
LCD_CMD_PORT &= ~(1 << LCD_CMD_E);
}

void commandLCD(unsigned char d)
{
checkIfBusy();
LCD_PORT = d;
LCD_CMD_PORT &= ~((1 << LCD_CMD_RW)|(1 << LCD_CMD_RS));
switchEnable();
LCD_PORT = 0;
}

void putcLCD(unsigned char c, unsigned char c1)
{
if(c == '\n')
{
    lcdNewLine();
    return;
}

if (currentChar >= 20 && c != ' ' && c1 != ' ' && c1 != '%pre%')
{
    currentChar = 0;
    putcLCD('-', ' ');
    lcdNewLine();
}

if (c == ' ' && currentChar == 1)
return;

checkIfBusy();
LCD_PORT = c;
LCD_CMD_PORT &= ~(1 << LCD_CMD_RW);
LCD_CMD_PORT |= (1 << LCD_CMD_RS);
switchEnable();
LCD_PORT = 0x00;
currentChar++;
}

void resetLCD()
{
checkIfBusy();
commandLCD(0x01);
currentChar = 1;
currentLine = 1;
}

void lcdNewLine()
{
char line = 20;
switch(currentLine)
{
    case 1:
    line *= 2;
    break;
    case 2:
    line *= 1;
    break;
    case 3:
    line *= 4.2;
    break;
}

line += 0b10000000;
checkIfBusy();
commandLCD(line);
currentLine += 1;
currentChar = 1;
}

void putsLCD(unsigned char *s)
{
checkIfBusy();
resetLCD();
int maxCount = strlen(s);

int i;
for(i = 0; i < maxCount; i++)
{
    if(s[i] == '%pre%')
    break;

    char arg2 = ' ';
    if(i + 1 < maxCount)
    arg2 = s[i + 1];

    putcLCD(s[i], arg2);
}
}
') break; char arg2 = ' '; if(i + 1 < maxCount) arg2 = s[i + 1]; putcLCD(s[i], arg2); } }
    
respondido por el AmazingDreams
2

Ok, he mirado a través del video tutorial. No puedo encontrar la hoja de datos del controlador LCD, por lo que simplemente me estoy desviando del ejemplo que he vinculado. Tienes un par de diferencias importantes:

  1. Su secuencia de comandos no está en orden con el ejemplo. Es importante tener la misma secuencia, ya que algunos comandos tienen dos o más bytes a veces.

  2. Solo está esperando 2µs después de cada comando, en lugar de solo después de LCD_CLEAR_DISPLAY . El código del video y página web muestra un retraso de 50µs después de lo que ha llamado el comando LCD_SET_MODE y el siguiente comando.

  3. Luego envías un comando diferente, LCD_SET_AI_NOSHIFT como 0b00000110 , en la página web, él envía un comando similar sin nombre de 0b00001110 .

Intente aumentar los tiempos de demora y envíe la misma secuencia de comandos que en el ejemplo.

Espero que resuelva tu problema.

EDITAR: Ah, encontré la hoja de datos . Además, me doy cuenta de que está buscando ocupado entre comandos. El comando del modo de configuración, su 0b00000110 tarda 37 µs en completarse, pero eso debería estar bien debido a la verificación. Sin embargo, la hoja de datos dice que el indicador de ocupado no se puede verificar antes de que se envíe el comando del modo de ajuste y por unos pocos ms después. Verifique en la página 45 de la hoja de datos vinculada la rutina de inicialización. Intente codificar los retrasos a medida que se escriben y ver si todavía no funciona.

    
respondido por el Samuel

Lea otras preguntas en las etiquetas