Salida extraña en pantalla LCD 16X2 JHD162A

Estoy aprendiendo la interfaz de Atmega 16a con LCD 16X2. Tengo un archivo de encabezado escrito para rutinas que se usarán con frecuencia y cada vez que quiero interactuar con LCD usando Atmega 16a, uso este archivo de encabezado.

aquí está mi archivo de encabezado LCD:

#include<stdlib.h>
#include<avr/io.h>
#include<util/delay.h>
int cx=1;
int cy=1;
void LCD_Send(unsigned char c,unsigned char DC)
{

    if(DC==0)
    {
        PORTC=0x0F & (c>>4);
        PORTC=PORTC|(1<<5);
        _delay_ms(1);
        PORTC=PORTC & (~(1<<5));
        _delay_ms(1);
        PORTC=0x0F & (c);
        PORTC=PORTC | (1<<5);
        _delay_ms(1);
        PORTC=PORTC & (~(1<<5));
        _delay_ms(1);
    }
    else if(DC==1)
    {
        PORTC=0x0F & (c>>4);
        PORTC=PORTC | (1<<7);
        PORTC=PORTC|(1<<5);
        _delay_ms(1);
        PORTC=PORTC & (~(1<<5));
        _delay_ms(1);
        PORTC=0x0F & (c);
        PORTC=PORTC | (1<<7);
        PORTC=PORTC | (1<<5);
        _delay_ms(1);
        PORTC=PORTC & (~(1<<5));
        _delay_ms(1);
    }
    return ;
}
void LCD_init(void)
{
    DDRC=0b11101111;
    LCD_Send(0x01,0);
    LCD_Send(0x0F,0);
    LCD_Send(0x28,0);
    cx=1;cy=1;
    return ;
}
void LCD_Send_String(char* s)
{
    for(int i=0;s[i]!='\0';i++)
    {
        LCD_Send(s[i],1);
        if(cx==16)
        {
            cx=1;cy++;
            LCD_Send(0xC0,0);
        }
        else
        cx++;
    }
    return ;
}
void LCD_GotoXY(unsigned int x,unsigned int y)
{
    if(y==1)
    {
        char addr=0x80;
        addr=addr+(x-1);
        LCD_Send(addr,0);
    }
    else if(y==2)
    {
        char addr=0xC0;
        addr=addr+(x-1);
        LCD_Send(addr,0);
    }    
    cx=x; cy=y;
    return ;
}
void LCD_Print(int data,unsigned int x,unsigned int y)
{
    char string[10];
    LCD_GotoXY(x,y);
    itoa(data,string,10);
    LCD_Send_String(string);
    return ;
}

Aquí RS,R/W y E son PC7,PC6 y PC5 respectivamente, DB4,DB5,DB6,DB7 son PC0,PC1,PC2,PC3 respectivamente. Estoy usando el modo de 4 bits para la entrada.

aquí está mi archivo main.c (el código que se ejecutará en el microprocesador):

#include"lcd.h"
int main(void)
{
    LCD_init();
    char s[20]="1234567890123456789";
    LCD_Send_String(s);
    return 0;
}

Cuando flasheo la memoria con el archivo HEX y luego reinicio, la pantalla LCD se muestra bien

Figura 1

Luego, cuando reinicio más tarde, muestra variables aleatorias (de hecho, puedo ver que la segunda línea no cambia en absoluto, significa que la pantalla no se borra, pero se escribió un comando para borrar la LCD_init()pantalla)

Figura 2

Estoy bastante seguro de que no hay nada malo con la placa y las conexiones porque funciona con otros archivos de encabezado, estoy bastante seguro de que es una falla en mi código. Realmente agradecería si alguien me ayuda a corregir este código. Si reinicio nuevamente, muestra la secuencia correcta como en la primera imagen.

¿Qué y cómo lo estás reiniciando?
por reinicio quiero decir que he arrancado en frío.
Una vez que obtengo esta salida werid y luego reinicio nuevamente, puedo ver la pantalla clara y ver que aparece nuevamente la secuencia correcta.
entonces dices que si quitas y vuelves a conectar la corriente no funciona pero si solo reinicias el micro si funciona?
no, si lo conecto funciona correctamente, si lo restablezco no funciona y si lo restablezco nuevamente, funciona nuevamente. en realidad funciona y no funciona en un patrón alternativo
intente agregar un retraso de 100 ms como primera cosa en su código y vea si funciona
no funciona tiene el mismo error

Respuestas (3)

Su problema es que la pantalla mantiene su estado durante el reinicio de MCU. Al arrancar en frío, el modo de datos inicial es de 8 bits, que cambia inmediatamente a 4 bits, que lee datos con un par de pulsos EN.

Cuando restablece la MCU, no sabe si se envió un número par o impar de pulsos EN. Por lo tanto, debe reiniciar la pantalla de alguna manera, incluso si no tiene un pin de reinicio.

Esto se puede hacer enviando 0x33 0x33 (en el modo de 8 bits significará 4 veces cambiar a 8 bits, en el modo de 4 bits significará una o dos veces cambiar a 8 bits). Entonces puede estar seguro de que siempre comienza desde el mismo estado.

Luego proceda con 0x32 regular (o 0x02 de 4 bits si tiene una función de escritura de 4 bits), 0x28 para ingresar al modo de 2 líneas de 4 bits.

¿Quieres escribir LCD_Send (0x33,0) dos veces antes de LCD_Send (0x01,0)?
Mientras leo la hoja de datos HD44780 (p. 46), ¿debe enviar 0x3? (los ? bits no importan) 3 veces, luego envíe 0x2 ?, y luego puede comenzar a enviar un comando de 8 bits como dos nibbles. Esto es equivalente a enviar 0x33 0x32 como nibbles.
@WoutervanOoijen Sí, solo quería dividir dos cosas (volver al modo de 8 bits y configurar el modo de 4 bits) en dos párrafos de prueba.
@Aditya Como han dicho otros, también debe agregar algo de retraso: _delay_ms(100);LCD_Send(0x33,0);LCD_Send(0x32,0);LCD_Send(0x28,0);LCD_Send(0x0f,0);LCD_Send( 0x01,0);_delay_ms(5);LCD_Send(0x06,0);. El 0x33 se requiere solo una vez cuando es seguido por 0x32.
Como interpreto lo que escribiste, envías el nibble 0x3 5 veces, mientras que la hoja de datos dice 3 veces. Tal vez eso no importa. De todos modos, @Anditya: este es seguramente tu problema. Y lea la hoja de datos, se requieren algunas esperas extra largas en esta inicialización.

Los LCD tienden a hacer esto si el flujo de datos se desincroniza de alguna manera, por ejemplo, enchufándolo mientras la transferencia de datos está en curso o reiniciando la pantalla o el microcontrolador, pero no ambos.

Me doy cuenta de su código que no hay retraso en el inicio. Las pantallas LCD a menudo requieren un breve período de tiempo para "iniciar" antes de que pueda comenzar a enviar datos. Agregue un pequeño retraso al inicio de su código. Consulte la hoja de datos de LCD para saber cuánto.

Este es un muy buen punto. Los zaps de ESD a menudo pueden desincronizar estas cosas, por lo que para los productos comerciales (que tienen que sobrevivir a la inyección de ESD para complicarse) es una buena idea reiniciar periódicamente estas pantallas LCD.

Consulte la hoja de datos de la pantalla LCD. A menudo, debe esperar un tiempo determinado después del encendido antes de enviar la secuencia de inicio. Quizás tu problema sea este:

Cuando está programando el dispositivo, ya ha estado encendido durante un tiempo, por lo que su secuencia de inicio funciona. Cuando lo arranca en frío, no hay demora, por lo que la pantalla LCD aún no está lista para la secuencia de inicio.

También publique un enlace a la hoja de datos

itron.com.cn/PDF_file/JHD162A%20SERIES.pdf este es el enlace a la pantalla LCD que utilicé
si lo restablezco por segunda vez, muestra el resultado correcto, no entiendo cómo la explicación que diste explica esto.
Probablemente todavía le quede suficiente energía para estar listo para su secuencia de inicio. Intente esperar más tiempo antes del segundo reinicio. La hoja de datos no es muy clara, pero dice que el controlador es equivalente a una pieza de Samsung: lcd-module.de/eng/pdf/zubehoer/ks0066.pdf La pieza de Samsung dice que necesita un retraso de 30 ms en el inicio.
he puesto el retraso pero el problema persiste