3 votos

Atmega32 + LCD no muestra nada

Estoy tratando de escribir un programa en C para mostrar texto en este LCD, por alguna razón no muestra nada en absoluto. He seguido este tutorial en youtube y usé mi libro de texto (hace poco empecé a estudiar ingeniería eléctrica), pero incluso después de copiar exactamente lo que había (excepto los puertos y esas cosas) seguía sin funcionar.

Esperaba que alguien de aquí pudiera echar un vistazo rápido y descubrir qué está pasando. Ya no sé qué hacer.

#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 responder 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;
}

2voto

FredB Puntos 496

Ok, he mirado el video tutorial. No puedo encontrar la hoja de datos para el controlador de LCD, así que sólo voy por el ejemplo que ha vinculado. Usted tiene un par de diferencias importantes:

  1. Tu secuencia de comandos está desordenada con respecto al ejemplo. Es importante tener la misma secuencia ya que algunos comandos son dos o más bytes a veces.

  2. Sólo esperas 2µs después de cada comando, en lugar de esperar sólo después de que el LCD_CLEAR_DISPLAY . El código del vídeo y página web muestra un retardo de 50µs después de lo que ha llamado el LCD_SET_MODE y el siguiente comando.

  3. A continuación, envía un comando diferente, LCD_SET_AI_NOSHIFT como 0b00000110 en la página web envía un comando similar sin nombre de 0b00001110 .

Prueba a aumentar los tiempos de retardo y a enviar la misma secuencia de comandos que en el ejemplo.

Espero que eso resuelva tu problema.

EDITAR: Ah, encontrado la ficha técnica . Además, me he dado cuenta de que estás comprobando si está ocupado entre comandos. El comando set mode, tu 0b00000110 tarda 37µs en completarse, pero debería estar bien debido a la comprobación. Sin embargo, la hoja de datos dice que la bandera de ocupado no se puede comprobar antes de que se envíe el comando de modo establecido y durante unos pocos ms después. Comprueba la página 45 de la hoja de datos enlazada para la rutina de inicialización. Prueba a codificar los retardos tal y como están escritos y comprueba si sigue sin funcionar.

0voto

JunkLaw Puntos 13

Tuve que desactivar JTAG en la parte superior de mi principal:

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

Ahora funciona, mi código es bueno, no necesito inicializar mi LCD manualmente. Sólo borrar 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 != '\0')
{
    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] == '\0')
    break;

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

    putcLCD(s[i], arg2);
}
}

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X